A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The SendGrid API is how an app or AI agent works with a SendGrid account: sending an email to a recipient, adding or searching marketing contacts, organizing them into lists and segments, managing transactional templates, or reading delivery and engagement statistics. Access is granted through an API key, and the key can be scoped to specific permissions like sending only or marketing only, so a call reaches only the areas the key allows. SendGrid can also push an event to a registered endpoint whenever a message is delivered, opened, clicked, or bounced.
How an app or AI agent connects to SendGrid determines what it can reach. There is a route for making calls and a route for receiving events, and each is governed by the API key behind it and the permissions that key carries.
The v3 Web API takes JSON request bodies, returns JSON, and is reached at https://api.sendgrid.com/v3. A call authenticates with an API key sent as a Bearer token in the Authorization header. Marketing endpoints under /v3/marketing process some writes asynchronously, returning a 202 and a job to poll.
SendGrid POSTs a JSON array of event objects to an HTTPS endpoint configured in the Mail Settings. Each event reports a delivery or engagement signal for a message, like processed, delivered, open, click, or bounce. Signed Event Webhook adds an ECDSA signature header so the receiver can verify the request came from SendGrid.
Every v3 request authenticates with an API key sent as a Bearer token in the Authorization header. A key is created in the account with a chosen permission level, and a leaked key reaches only the scopes it was granted. The full key value is shown only once, when it is created.
An API key can be limited to specific scopes, like mail.send for sending only, marketing.read for the Email Marketing API, or stats.read for statistics, so a key carries only the access an integration needs. Billing permissions are mutually exclusive from all others. A key with too few scopes for a request returns a 403.
The SendGrid API is split into areas an agent can act on, like sending mail, managing contacts, lists and segments, transactional templates, suppression groups, and statistics. Each area has its own methods and its own permission scope, and a write in some areas sends real email or removes people from a marketing audience.
Methods for sending email, both transactional and one-off.
Methods for adding, finding, and removing marketing contacts.
Methods for working with static lists of contacts.
Methods for working with dynamic audience segments.
Methods for working with transactional templates and their versions.
Methods for working with suppression (unsubscribe) groups.
Methods for reading email delivery and engagement statistics.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
Mail SendMethods for sending email, both transactional and one-off.1 | ||||||
| POST | /v3/mail/send | Send an email, transactional or one-off, with content, recipients, and metadata in a JSON body. | write | mail.send | Current | |
The from address must be a verified sender. Each request may include up to 1,000 recipients. Acts onmail Permission (capability) mail.sendVersionAvailable since the API’s base version Webhook event processedRate limitUp to 10,000 requests per second SourceOfficial documentation ↗ | ||||||
ContactsMethods for adding, finding, and removing marketing contacts.6 | ||||||
| PUT | /v3/marketing/contacts | Add new contacts or update existing ones (upsert), processed asynchronously. | write | marketing.read | Current | |
Asynchronous: returns 202 with a job id; use the search endpoint to confirm the change landed. The marketing.read scope grants read and write on the Email Marketing API. Acts oncontact Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v3/marketing/contacts | Retrieve a sample page of contacts in the account. | read | marketing.read | Current | |
Read-only. Acts oncontact Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v3/marketing/contacts/:id | Retrieve a single contact by its id. | read | marketing.read | Current | |
Read-only. Acts oncontact Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /v3/marketing/contacts/search | Search contacts using SGQL query conditions. | read | marketing.read | Current | |
A POST used to read, not to change data. Acts oncontact Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /v3/marketing/contacts | Delete one or more contacts by id, or delete all contacts. | write | marketing.read | Current | |
Irreversible; a delete_all_contacts flag removes every contact in the account. Acts oncontact Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /v3/marketing/contacts/imports | Start a bulk import of contacts from an uploaded CSV file. | write | marketing.read | Current | |
Returns an upload URL and an import job id; the import runs asynchronously. Acts oncontact_import Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
ListsMethods for working with static lists of contacts.4 | ||||||
| POST | /v3/marketing/lists | Create a static list to hold a fixed set of contacts. | write | marketing.read | Current | |
Adding contacts to the list is done through the Contacts API. Acts onlist Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v3/marketing/lists | Retrieve all lists in the account. | read | marketing.read | Current | |
Read-only. Acts onlist Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /v3/marketing/lists/:id | Update a list, for example to rename it. | write | marketing.read | Current | |
A core write. Acts onlist Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /v3/marketing/lists/:id | Delete a list, optionally deleting the contacts it holds. | write | marketing.read | Current | |
A delete_contacts flag can also delete the contacts that belonged only to this list. Acts onlist Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
SegmentsMethods for working with dynamic audience segments.3 | ||||||
| POST | /v3/marketing/segments/2.0 | Create a dynamic segment defined by query conditions on contacts. | write | marketing.read | Current | |
A segment updates automatically as contacts match or stop matching its conditions. Acts onsegment Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v3/marketing/segments/2.0 | Retrieve all segments in the account. | read | marketing.read | Current | |
Read-only. Acts onsegment Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /v3/marketing/segments/2.0/:id | Delete a segment by its id. | write | marketing.read | Current | |
Deletes the segment definition, not the contacts it matched. Acts onsegment Permission (capability) marketing.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
TemplatesMethods for working with transactional templates and their versions.6 | ||||||
| POST | /v3/templates | Create a transactional template that other sends can reference. | write | templates.create | Current | |
A core write. Acts ontemplate Permission (capability) templates.createVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v3/templates | Retrieve transactional templates, paginated. | read | templates.read | Current | |
Read-only. Acts ontemplate Permission (capability) templates.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v3/templates/:template_id | Retrieve a single transactional template by id. | read | templates.read | Current | |
Read-only. Acts ontemplate Permission (capability) templates.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /v3/templates/:template_id/versions | Create a new version of a transactional template with its own content. | write | templates.versions.create | Current | |
Each template can hold multiple versions, with one active. Acts ontemplate_version Permission (capability) templates.versions.createVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /v3/templates/:template_id/versions/:version_id/activate | Activate a template version so sends using the template render it. | write | templates.versions.activate | Current | |
Full scope is templates.versions.activate.create. Changes which version live mail using the template renders. Acts ontemplate_version Permission (capability) templates.versions.activateVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /v3/templates/:template_id | Delete a transactional template and its versions. | write | templates.delete | Current | |
Irreversible; sends that reference this template id will fail. Acts ontemplate Permission (capability) templates.deleteVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Unsubscribe GroupsMethods for working with suppression (unsubscribe) groups.4 | ||||||
| POST | /v3/asm/groups | Create a suppression (unsubscribe) group recipients can opt out of by category. | write | suppression.create | Current | |
A core write. Acts onunsubscribe_group Permission (capability) suppression.createVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /v3/asm/groups | Retrieve all suppression groups for the account. | read | suppression.read | Current | |
Read-only. Acts onunsubscribe_group Permission (capability) suppression.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /v3/asm/groups/:id | Update a suppression group, for example its name or description. | write | suppression.update | Current | |
A core write. Acts onunsubscribe_group Permission (capability) suppression.updateVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /v3/asm/groups/:id | Delete a suppression group. | write | suppression.delete | Current | |
Removes the group recipients could opt out of. Acts onunsubscribe_group Permission (capability) suppression.deleteVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
StatsMethods for reading email delivery and engagement statistics.1 | ||||||
| GET | /v3/stats | Retrieve global email statistics, like delivered, open, click, and bounce counts over time. | read | stats.read | Current | |
Read-only; aggregated by day, week, or month. Acts onstat Permission (capability) stats.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
SendGrid can notify an app when something happens to a message it sent, like the message being delivered, opened, clicked, or bounced. It posts an array of event objects to a registered HTTPS endpoint, so an integration learns about delivery and engagement without polling.
| Event | What it signals | Triggered by |
|---|---|---|
processed | SendGrid accepted the message and can deliver it. | /v3/mail/send |
delivered | SendGrid succeeded in delivering the message to the receiving server. | /v3/mail/send |
open | A recipient opened the HTML message; requires Open Tracking to be on. | /v3/mail/send |
click | A recipient clicked a link in the message; requires Click Tracking to be on. | /v3/mail/send |
bounce | The receiving server permanently rejected the message for this recipient. | /v3/mail/send |
dropped | SendGrid dropped the message before sending, for example a suppressed or previously bounced address. | /v3/mail/send |
deferred | The receiving server temporarily rejected the message, and SendGrid will retry. | /v3/mail/send |
spamreport | A recipient marked the message as spam. | /v3/mail/send |
unsubscribe | A recipient clicked the Opt Out of All Emails link. | /v3/mail/send |
group_unsubscribe | A recipient unsubscribed from a specific suppression group. | /v3/mail/send |
SendGrid limits how fast an app can call, both at the account level and per endpoint, and returns the remaining quota on each response so an integration can pace itself.
SendGrid limits how fast an app can call, both across the account and per endpoint, and most v3 responses carry X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers so an integration can pace itself before it is throttled. The v3 Mail Send endpoint allows up to 10,000 requests per second. The Marketing contacts upsert endpoint queues work asynchronously and processes in batches rather than per request. Going over a limit returns HTTP 429.
List endpoints page differently by area. The Marketing API (contacts, lists, segments) uses a page_size parameter with a page_token cursor returned in the response for the next page. Other v3 list endpoints use limit and offset query parameters. A response includes the metadata needed to request the next page.
A single Mail Send request may address up to 1,000 recipients. Contacts are added or updated in batches, and bulk imports run asynchronously from an uploaded CSV. Email statistics are aggregated and category statistics are retained for the previous thirteen months.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | Bad request | The request was malformed or a parameter was invalid, with the reasons listed in the response errors array. | Read the errors array, fix the request body or parameters, and resend. The request is not retryable as-is. |
| 401 | Requires authentication | No valid API key was provided, or the key is missing from the Authorization header. | Send a valid API key as a Bearer token, and rotate the key if it may be compromised. |
| 403 | Forbidden | The key lacks a scope the request needs, or the from address does not match a verified sender, or sending is temporarily blocked. | Grant the needed scope on the key, verify the sender identity, or wait out the temporary block. |
| 406 | Missing Accept header | The request did not send an Accept: application/json header. | Add the Accept: application/json header and resend. |
| 429 | Too many requests | A rate limit was exceeded. Responses carry X-RateLimit headers showing the limit, what remains, and when it resets. | Back off and retry after the reset shown in the rate-limit headers, and smooth the request rate. |
| 500 | Internal server error | An error on SendGrid's side. It is rare. | Retry with backoff, and contact SendGrid support if it persists. |
SendGrid serves a single, continuously updated v3 API rather than dated versions, and ships changes through the Twilio changelog. The older v2 Mail Send endpoint still exists but v3 is the supported path for new integrations.
SendGrid serves a single, continuously updated v3 Web API rather than dated versions. Changes ship through the Twilio changelog as additions and occasional deprecations. The v3 Mail Send endpoint and the Marketing API (contacts, lists, segments) are the supported surfaces for new integrations.
The legacy v2 Mail Send endpoint was changed to allow up to 1,000 recipients per request, down from 10,000, aligning its behavior with the v3 Mail Send endpoint. The change took effect on 9 July 2025.
Twilio SendGrid began retiring its free Email API and free Marketing Campaigns plans, requiring an upgrade to a paid plan to keep sending email and using key tools.
SendGrid introduced the current Marketing Campaigns API (the /v3/marketing endpoints for contacts, lists, and segments) and began deprecating the legacy Marketing Campaigns and contactdb endpoints.
There is one current v3 API; track the changelog for additive changes and deprecations.
SendGrid changelog ↗Bollard AI sits between a team's AI agents and SendGrid. Grant each agent exactly the access it needs, read or write, area by area, and every call is checked and logged.