<!-- Generated by `just docs` from catalog/toolkits/sendgrid.yaml, catalog/expansions/sendgrid.yaml, catalog/evals/scorecard.json. Edit the source, not this file. -->

# SendGrid

Email delivery. Send now or on a schedule, build dynamic templates, verify senders, keep marketing lists, and read delivery stats.

| Property | Value |
| --- | --- |
| Slug | `sendgrid` |
| Definition version | `0.1.0` |
| Base URL | `https://api.sendgrid.com` |
| Auth schemes | `api_key` |
| Action tools | 40 |
| By class | 17 read, 16 write, 7 destructive |
| Triggers | 0 |
| Provider rate limit | not declared, so outbound calls are unpaced |

## Measured routing accuracy

80 golden cases replayed through the router over the whole index: measured over corpus `ea4f12ad2948` (65 toolkits, 2283 tools indexed and 13 declared uncallable), 40 cases written by hand and 40 cases from the paraphrase pass. A case counts as top-1 when its gold tool ranked first and top-8 when it reached the slate at all.

| Measure | Cases | Share |
| --- | --- | --- |
| top-1 | 38/80 | 47.5% |
| top-8 | 56/80 | 70.0% |

The sweep is offline: the reranker is a deterministic identity fake that returns candidates in the order retrieval produced them, so top-1 measures retrieval order rather than a reranked slate. `just eval-live` measures the same cases through the live reranker.

## Authentication

Connect an entity with `ConnectionsService.InitiateConnection`, naming this toolkit's slug. Credentials stay in the connections vault; callers hold connected-account ids only.

### `api_key`

| Property | Value |
| --- | --- |
| Placement | `header` |
| Name | `Authorization` |
| Rendered as | `Bearer {key}` |

Submit the key with `ConnectionsService` rather than putting it in a request; it is sealed at rest and never returned.

## Tools

40 action tools. The catalog-wide slug is `sendgrid.<tool>`, which is what `search_tools` returns and `call_tool` takes.

### `sendgrid.send_email`

Send a transactional email through SendGrid right now, as raw text/HTML or rendered from a dynamic template. Use when the user wants to send, email, deliver, or mail someone directly. Pass send_at to schedule it ahead instead, and batch_id (from create_mail_batch_id) to keep the option to pause or cancel it before it goes out. Distinct from create_single_send, which is a marketing campaign to a list rather than one message.

Class `write` (writes, no confirmation needed). Scopes `mail.send`. Calls `POST /v3/mail/send`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `asm_group_id` | integer | no | Unsubscribe group id (see the sendgrid_suppressions toolkit) this message's opt-out applies to. |
| `batch_id` | string | no | Batch id from create_mail_batch_id, so this send can be paused or canceled before send_at. |
| `bcc` | array of object | no | Blind carbon-copy recipients. |
| `bcc[].email` | string (email) | **yes** |  |
| `bcc[].name` | string | no |  |
| `categories` | array of string | no | Up to 10 labels for later filtering in stats and message activity. |
| `cc` | array of object | no | Carbon-copy recipients. |
| `cc[].email` | string (email) | **yes** |  |
| `cc[].name` | string | no |  |
| `content` | array of object | **yes** | Message bodies. Include a text/plain entry, a text/html entry, or both. |
| `content[].type` | string | **yes** | MIME type, e.g. "text/plain" or "text/html". |
| `content[].value` | string | **yes** |  |
| `dynamic_template_data` | object | no | Merge variables substituted into the template for this send. |
| `from` | object | **yes** | Verified sender address (see list_verified_senders) this message is sent from. |
| `from.email` | string (email) | **yes** |  |
| `from.name` | string | no |  |
| `reply_to` | object | no | Address replies should go to, if different from "from". |
| `reply_to.email` | string (email) | no |  |
| `reply_to.name` | string | no |  |
| `send_at` | integer | no | Unix timestamp to schedule delivery instead of sending immediately, up to 72 hours ahead. |
| `subject` | string | **yes** | Email subject line. |
| `template_id` | string | no | Dynamic transactional template id (starts with "d-"), from list_templates. content is still required by the API even when a template supplies the body. |
| `to` | array of object | **yes** | Recipients. Each entry needs an email and may include a display name. |
| `to[].email` | string (email) | **yes** |  |
| `to[].name` | string | no |  |

Also retrieved by: "shoot someone an email right now", "fire off a message to this address", "get this out to the customer immediately", "mail someone through sendgrid", "render a template and email it to someone".

### `sendgrid.create_mail_batch_id`

Create a new SendGrid batch id for grouping scheduled sends, so a future message (or group of them sharing this batch_id) can be paused or canceled with pause_scheduled_send or cancel_scheduled_send before it goes out. Call this before send_email when the user wants the option to stop a scheduled message later.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/mail/batch`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `batch_id` | string |  |

Also retrieved by: "set up a group id so I can pull this back later", "give me a handle to cancel these messages if needed", "start a batch I can hold before it goes out".

### `sendgrid.list_scheduled_sends`

List every SendGrid batch id currently paused or canceled, with its status. Use to check what scheduled mail is currently held back from sending.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/user/scheduled_sends`.

Takes no arguments.

Also retrieved by: "what's queued up and held back from going out", "show every batch that's currently paused", "what mail is on ice right now".

### `sendgrid.pause_scheduled_send`

Pause a scheduled SendGrid batch so it stops short of sending, without discarding it. Use resume_scheduled_send to let it go out again, or cancel_scheduled_send to stop it for good.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/user/scheduled_sends`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `batch_id` | string | **yes** | Batch id from create_mail_batch_id or list_scheduled_sends. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `batch_id` | string |  |
| `status` | string |  |

Also retrieved by: "put this queued batch on hold", "freeze that scheduled mail for now", "don't let this batch go out yet, but don't kill it".

### `sendgrid.cancel_scheduled_send`

Permanently cancel a scheduled SendGrid batch. Use when the user wants to stop, cancel, or kill a scheduled send for good, not just hold it (that's pause_scheduled_send). Once canceled a batch cannot be resumed.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `POST /v3/user/scheduled_sends`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `batch_id` | string | **yes** | Batch id from create_mail_batch_id or list_scheduled_sends. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `batch_id` | string |  |
| `status` | string |  |

Also retrieved by: "stop this batch from ever going out", "kill the scheduled mail for good", "pull the plug on that queued send permanently".

### `sendgrid.resume_scheduled_send`

Remove the pause or cancel status from a SendGrid batch, letting it send normally again at its original send_at time. Use when the user changes their mind about a held or canceled scheduled send.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `DELETE /v3/user/scheduled_sends/{{params.batch_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `batch_id` | string | **yes** | Batch id currently paused or canceled. |

Also retrieved by: "let that held batch go out after all", "take the hold off and let it send", "never mind, let the queued mail through".

### `sendgrid.list_api_keys`

List every SendGrid API key on the account by id and name (not the key value; SendGrid never returns that again after creation). Use to audit what programmatic access exists.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/api_keys`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `result` | array of object |  |
| `result[].api_key_id` | string |  |
| `result[].name` | string |  |

Also retrieved by: "what programmatic keys exist on this account", "show every credential set up for automation", "audit access to the sending account".

### `sendgrid.create_api_key`

Create a new SendGrid API key with a name and a set of permission scopes. Its secret value is returned exactly once, in this response, and can never be retrieved again.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/api_keys`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `name` | string | **yes** | Label for this key, e.g. "ci-deploy-bot". |
| `scopes` | array of string | no | SendGrid permission scopes to grant, e.g. "mail.send". Omit to create a full-access key. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `api_key` | string |  |
| `api_key_id` | string |  |
| `name` | string |  |

Also retrieved by: "set up a new key for our deploy bot", "mint a fresh credential with limited access", "give the ci pipeline its own key".

### `sendgrid.get_api_key`

Look up one SendGrid API key's name and granted scopes by its id.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/api_keys/{{params.api_key_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `api_key_id` | string | **yes** | API key id from list_api_keys. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `api_key_id` | string |  |
| `name` | string |  |
| `scopes` | array of string |  |

Also retrieved by: "what permissions does this credential have", "check what one key is scoped to do", "look up the details behind this credential".

### `sendgrid.update_api_key`

Rename a SendGrid API key and replace its granted scopes entirely.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `PUT /v3/api_keys/{{params.api_key_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `api_key_id` | string | **yes** | API key id from list_api_keys. |
| `name` | string | **yes** | New label for the key. |
| `scopes` | array of string | no | Full replacement list of permission scopes. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `api_key_id` | string |  |
| `name` | string |  |
| `scopes` | array of string |  |

Also retrieved by: "rename this credential and tighten its scopes", "change what this key is allowed to do", "narrow down what this credential can access".

### `sendgrid.delete_api_key`

Permanently revoke a SendGrid API key. Use when the user wants to delete, revoke, or kill a key. Any integration still using it stops authenticating immediately.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `DELETE /v3/api_keys/{{params.api_key_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `api_key_id` | string | **yes** | API key id from list_api_keys. |

Also retrieved by: "revoke that credential, it's compromised", "kill this key so it stops working", "cut off access for that integration".

### `sendgrid.list_templates`

List SendGrid dynamic transactional templates by id, name, and how many versions each has. Use to see what templates already exist before creating or sending one.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/templates`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `generations` | string, one of legacy, dynamic, both | no | Which template generation to list. Defaults to dynamic, the current kind. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `templates` | array of object |  |
| `templates[].generation` | string |  |
| `templates[].id` | string |  |
| `templates[].name` | string |  |

Also retrieved by: "what dynamic templates do we already have", "show every reusable email layout on the account", "browse the saved message designs".

### `sendgrid.create_template`

Create a new, empty SendGrid dynamic transactional template shell by name. Add its subject and body afterward with create_template_version; a template with no version has nothing to send yet.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/templates`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `name` | string | **yes** | Template name, for identifying it in the dashboard and in list_templates. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `generation` | string |  |
| `id` | string |  |
| `name` | string |  |

Also retrieved by: "start a new reusable email design", "set up a fresh template shell", "build a new layout we can reuse for sends".

### `sendgrid.get_template`

Get one SendGrid template's details, including every saved version and which one is active (the one send_email's template_id renders).

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/templates/{{params.template_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `template_id` | string | **yes** | Template id from list_templates, e.g. "d-abc123". |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `name` | string |  |
| `versions` | array of object |  |
| `versions[].active` | integer |  |
| `versions[].id` | string |  |
| `versions[].subject` | string |  |

Also retrieved by: "pull up the details for one email design", "which version of this template is live right now", "show me every saved draft of this layout".

### `sendgrid.update_template`

Rename a SendGrid template.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `PATCH /v3/templates/{{params.template_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `name` | string | **yes** | New template name. |
| `template_id` | string | **yes** | Template id from list_templates. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `name` | string |  |

Also retrieved by: "rename this email design", "change what this template is called", "give this layout a clearer name".

### `sendgrid.delete_template`

Permanently delete a SendGrid template and every version of it. Any send_email call that references its template_id afterward fails.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `DELETE /v3/templates/{{params.template_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `template_id` | string | **yes** | Template id from list_templates. |

Also retrieved by: "get rid of this email design for good", "remove this template and every version of it", "scrap this layout, we don't use it anymore".

### `sendgrid.create_template_version`

Add a new content version to an existing SendGrid template: the subject line and the HTML or plain-text body that dynamic_template_data fills in at send time. Set active to make it the version send_email renders immediately.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/templates/{{params.template_id}}/versions`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `active` | integer, one of 0, 1 | no | Set to 1 to make this the template's active version immediately. |
| `html_content` | string | no | HTML body, with handlebars for dynamic_template_data fields. |
| `name` | string | **yes** | Label for this version, e.g. "v2-shorter-subject". |
| `plain_content` | string | no | Plain-text body. |
| `subject` | string | **yes** | Subject line this version renders, may include handlebars like "{{Order}}". |
| `template_id` | string | **yes** | Template id from list_templates. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `active` | integer |  |
| `id` | string |  |
| `name` | string |  |
| `subject` | string |  |
| `template_id` | string |  |

Also retrieved by: "add a new draft of this email's copy", "save a fresh subject and body for this design", "make this the live version of the template".

### `sendgrid.list_verified_senders`

List every SendGrid verified single sender identity (a from address cleared to send) and whether each has completed verification. Use before send_email to confirm a from address is actually usable.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/verified_senders`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `results` | array of object |  |
| `results[].from_email` | string |  |
| `results[].id` | integer |  |
| `results[].nickname` | string |  |
| `results[].verified` | boolean |  |

Also retrieved by: "which from addresses are actually cleared to send", "show every sender identity on the account", "who are we allowed to mail from".

### `sendgrid.create_verified_sender`

Request verification of a new SendGrid sender identity. SendGrid emails the from_email address a confirmation link; the identity cannot send until it's clicked. Use when the user wants to add, verify, or set up a new from address.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/verified_senders`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `address` | string | **yes** | Street address, required by SendGrid's anti-spam physical-address rule. |
| `address_2` | string | no |  |
| `city` | string | **yes** |  |
| `country` | string | **yes** |  |
| `from_email` | string (email) | **yes** | The address this identity will send from once verified. |
| `from_name` | string | **yes** | Display name recipients see. |
| `nickname` | string | **yes** | Internal label for this identity, not shown to recipients. |
| `reply_to` | string (email) | **yes** | Address replies go to. |
| `reply_to_name` | string | no | Display name for the reply-to address. |
| `state` | string | no |  |
| `zip` | string | no |  |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `from_email` | string |  |
| `id` | integer |  |
| `verified` | boolean |  |

Also retrieved by: "get this address approved to send from", "set up a new from address for outbound mail", "register a sender identity so we can email from it".

### `sendgrid.delete_verified_sender`

Remove a verified sender identity from SendGrid. Any send_email call using that from address then fails until it's re-verified.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `DELETE /v3/verified_senders/{{params.sender_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `sender_id` | integer | **yes** | Sender identity id from list_verified_senders. |

Also retrieved by: "remove this from address, we don't use it anymore", "take this sender identity off the account", "this from address shouldn't be able to send anymore".

### `sendgrid.list_authenticated_domains`

List SendGrid's authenticated sending domains and whether each has finished DNS verification (DKIM and SPF records). Distinct from a verified single sender: authenticating a domain covers every address at that domain, not just one.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/whitelabel/domains`.

Takes no arguments.

Also retrieved by: "which domains have finished dns setup for mail", "show every domain hooked up for authenticated sending", "what hostnames are cleared to send from at the domain level".

### `sendgrid.authenticate_domain`

Register a new sending domain for SendGrid domain authentication and get back the DNS records to add. The domain isn't authenticated until validate_domain_authentication succeeds afterward.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/whitelabel/domains`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `automatic_security` | boolean | no | Let SendGrid choose the DNS record set (CNAME) instead of manual TXT records. Defaults true. |
| `custom_spf` | boolean | no | Manage SPF separately instead of folding it into the CNAME records. |
| `domain` | string | **yes** | Domain to authenticate, e.g. "example.com". |
| `subdomain` | string | no | Subdomain to send mail from, e.g. "mail". Defaults to a SendGrid-generated one. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `dns` | object |  |
| `domain` | string |  |
| `id` | integer |  |
| `valid` | boolean |  |

Also retrieved by: "hook up a new domain to send authenticated mail from", "get the dns records for a domain we want to send from", "register a domain so we can send with proper dkim and spf".

### `sendgrid.validate_domain_authentication`

Re-check DNS for a SendGrid authenticated domain now that its records have been added, and mark it valid if they resolve correctly. Use when the user says the DNS records are in place and wants to confirm or finish domain authentication.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/whitelabel/domains/{{params.domain_id}}/validate`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `domain_id` | integer | **yes** | Domain id from list_authenticated_domains or authenticate_domain. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | integer |  |
| `valid` | boolean |  |
| `validation_results` | object |  |

Also retrieved by: "recheck the dns now that records are in place", "confirm this domain's authentication went through", "the records are added, please verify the domain now".

### `sendgrid.add_or_update_contacts`

Add new SendGrid marketing contacts or update existing ones by email, optionally adding them to one or more lists in the same call. This runs as a background job; the response is a job id, not the finished contacts.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `PUT /v3/marketing/contacts`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `contacts` | array of object | **yes** |  |
| `contacts[].custom_fields` | object | no | Custom contact field ids mapped to their values for this contact. |
| `contacts[].email` | string (email) | **yes** |  |
| `contacts[].first_name` | string | no |  |
| `contacts[].last_name` | string | no |  |
| `contacts[].phone_number` | string | no |  |
| `list_ids` | array of string | no | Marketing list ids (from list_contact_lists) to add every contact here to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `job_id` | string |  |

Also retrieved by: "upload a batch of subscribers to the account", "add these people to our mailing list", "import contacts and put them on a list".

### `sendgrid.search_contacts`

Search SendGrid marketing contacts with a query expression, e.g. by email, list membership, or a custom field. Use to look up a contact when the user doesn't have its contact id.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /v3/marketing/contacts/search`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `query` | string | **yes** | SendGrid query expression, e.g. "email LIKE 'sarah@%'" or "CONTAINS(list_ids, '<list_id>')". |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `result` | array of object |  |
| `result[].email` | string |  |
| `result[].first_name` | string |  |
| `result[].id` | string |  |
| `result[].last_name` | string |  |

Also retrieved by: "find a contact by their email address", "look up who's on this list", "dig up a subscriber's profile".

### `sendgrid.get_contact_by_id`

Get one SendGrid marketing contact's full profile, including list membership, by its contact id.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/marketing/contacts/{{params.contact_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `contact_id` | string | **yes** | Contact id from search_contacts. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `email` | string |  |
| `first_name` | string |  |
| `id` | string |  |
| `last_name` | string |  |
| `list_ids` | array of string |  |

Also retrieved by: "pull up everything we know about this contact", "show one subscriber's full profile", "what info do we have on record for this person".

### `sendgrid.delete_contacts`

Permanently delete SendGrid marketing contacts by id, or every contact on the account. A removed contact's engagement history goes with it.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `DELETE /v3/marketing/contacts`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `delete_all_contacts` | boolean | no | Delete every contact on the account. When true, ids is ignored. |
| `ids` | string | no | Comma-separated contact ids to delete. Omit only when delete_all_contacts is true. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `job_id` | string |  |

Also retrieved by: "wipe these subscribers off the account entirely", "remove every contact we have on file", "purge these people from our subscriber database".

### `sendgrid.list_contact_lists`

List every SendGrid marketing contact list by id, name, and contact count.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/marketing/lists`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `result` | array of object |  |
| `result[].contact_count` | integer |  |
| `result[].id` | string |  |
| `result[].name` | string |  |

Also retrieved by: "what mailing lists do we have set up", "show every subscriber list on the account", "browse our newsletter and campaign groupings".

### `sendgrid.create_contact_list`

Create a new SendGrid marketing contact list to group contacts under, e.g. a newsletter or a webinar signup list.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/marketing/lists`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `name` | string | **yes** | List name. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `contact_count` | integer |  |
| `id` | string |  |
| `name` | string |  |

Also retrieved by: "start a new subscriber list", "set up a fresh mailing list for the newsletter", "make a new grouping to organize subscribers under".

### `sendgrid.delete_contact_list`

Delete a SendGrid marketing contact list. Only the list grouping is removed; pass delete_contacts to also delete every contact on it, otherwise they stay on the account, just off this list.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `DELETE /v3/marketing/lists/{{params.list_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `delete_contacts` | boolean | no | Also permanently delete every contact that was on this list. Defaults false. |
| `list_id` | string | **yes** | List id from list_contact_lists. |

Also retrieved by: "get rid of this subscriber list", "remove this mailing list, keep the contacts if possible", "shut down this grouping, we don't need it anymore".

### `sendgrid.list_single_sends`

List SendGrid marketing single sends (one-off campaign emails) by id, name, and status. Distinct from send_email, which is a transactional message rather than a scheduled campaign to a list.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/marketing/singlesends`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `result` | array of object |  |
| `result[].id` | string |  |
| `result[].name` | string |  |
| `result[].status` | string |  |

Also retrieved by: "what one-off campaigns have we sent or scheduled", "show every marketing blast on the account", "browse our past and upcoming email campaigns".

### `sendgrid.create_single_send`

Create a SendGrid marketing single send: a one-off campaign email to a contact list or segment, built from a template or raw content. It stays a draft until scheduled or sent from the dashboard; this call only creates it.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /v3/marketing/singlesends`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `email_config` | object | **yes** | The message itself. |
| `email_config.html_content` | string | no |  |
| `email_config.plain_content` | string | no |  |
| `email_config.sender_id` | integer | no | Verified sender identity id from list_verified_senders. |
| `email_config.subject` | string | **yes** |  |
| `email_config.template_id` | string | no | Dynamic template id to render instead of html_content/plain_content. |
| `name` | string | **yes** | Internal campaign name, not shown to recipients. |
| `send_to` | object | **yes** | Which lists or segments (from list_contact_lists) receive this campaign. |
| `send_to.list_ids` | array of string | no |  |
| `send_to.segment_ids` | array of string | no |  |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `name` | string |  |
| `status` | string |  |

Also retrieved by: "set up a one-time campaign to our newsletter list", "draft a marketing blast to a segment", "build a one-off promo email for our subscribers".

### `sendgrid.get_single_send`

Get one SendGrid single send's configuration and current status by id.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/marketing/singlesends/{{params.singlesend_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `singlesend_id` | string | **yes** | Single send id from list_single_sends. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `email_config` | object |  |
| `id` | string |  |
| `name` | string |  |
| `send_to` | object |  |
| `status` | string |  |

Also retrieved by: "what's the status of this campaign", "pull up the details for one marketing send", "check how this one-off blast is configured".

### `sendgrid.delete_single_send`

Permanently delete a SendGrid single send. If it was scheduled, deleting it cancels the send; it can never go out afterward.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `DELETE /v3/marketing/singlesends/{{params.singlesend_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `singlesend_id` | string | **yes** | Single send id from list_single_sends. |

Also retrieved by: "scrap this campaign draft", "cancel this scheduled marketing blast for good", "kill this one-off promo email before it goes out".

### `sendgrid.get_global_email_stats`

Get account-wide SendGrid delivery stats (sent, delivered, opens, clicks, bounces, spam reports) over a date range. Use for an overall sending health check, not one specific campaign or message.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/stats`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `aggregated_by` | string, one of day, week, month | no | Bucket size for the returned stats. Defaults to day. |
| `end_date` | string | no | End of the range, "YYYY-MM-DD". Defaults to today. |
| `start_date` | string | **yes** | Start of the range, "YYYY-MM-DD". |

Also retrieved by: "how's our sending been doing lately", "check overall delivery and open numbers", "give me a health check on our email sending".

### `sendgrid.get_category_stats`

Get SendGrid delivery stats broken down by the categories a send was tagged with (send_email's categories field). Use to compare how different campaigns or message types are performing against each other.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/categories/stats`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `aggregated_by` | string, one of day, week, month | no |  |
| `categories` | array of string | **yes** | Category names to break stats out by. |
| `end_date` | string | no | End of the range, "YYYY-MM-DD". |
| `start_date` | string | **yes** | Start of the range, "YYYY-MM-DD". |

Also retrieved by: "compare how these two campaigns performed", "break delivery numbers down by tag", "show me stats grouped by the labels we used".

### `sendgrid.get_email_activity`

Search recent individual SendGrid message events (delivered, opened, clicked, bounced) by recipient, subject, or a filter query. Use when the user asks what happened to one specific email, rather than aggregate stats over a period.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/messages`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Maximum messages to return. |
| `query` | string | no | Filter expression, e.g. 'to_email="sarah@acme.com"' or 'status="bounce"'. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `messages` | array of object |  |
| `messages[].last_event_time` | string |  |
| `messages[].msg_id` | string |  |
| `messages[].status` | string |  |
| `messages[].subject` | string |  |
| `messages[].to_email` | string |  |

Also retrieved by: "what happened to that one email I sent", "did this specific message actually get delivered", "look up the status of a single message".

### `sendgrid.get_event_webhook_settings`

Get the SendGrid Event Webhook configuration: the URL SendGrid posts delivery events to and which event types are enabled.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/user/webhooks/event/settings`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `bounce` | boolean |  |
| `clicked` | boolean |  |
| `delivered` | boolean |  |
| `enabled` | boolean |  |
| `opened` | boolean |  |
| `spam_report` | boolean |  |
| `unsubscribe` | boolean |  |
| `url` | string |  |

Also retrieved by: "where are delivery events currently posted to", "check the event webhook configuration", "what notifications are currently turned on for deliveries".

### `sendgrid.update_event_webhook_settings`

Change where SendGrid posts delivery events and which event types it sends, e.g. turn on bounce and spam report notifications or point delivery at a new URL.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `PATCH /v3/user/webhooks/event/settings`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `bounce` | boolean | no |  |
| `clicked` | boolean | no |  |
| `delivered` | boolean | no |  |
| `dropped` | boolean | no |  |
| `enabled` | boolean | no | Turn the Event Webhook on or off entirely. |
| `opened` | boolean | no |  |
| `spam_report` | boolean | no |  |
| `unsubscribe` | boolean | no |  |
| `url` | string | no | HTTPS endpoint SendGrid posts events to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `enabled` | boolean |  |
| `url` | string |  |

Also retrieved by: "turn on bounce notifications", "point delivery events at a new endpoint", "change which notifications get sent out on delivery events".

### `sendgrid.get_account_details`

Get the SendGrid account's plan type and sender reputation score. Use to check what tier or limits the account is on, or how healthy its sending reputation currently is.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `GET /v3/user/account`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `reputation` | number |  |
| `type` | string |  |

Also retrieved by: "what plan are we on", "check our sender reputation score", "how healthy is our sending reputation right now".
