SendGrid 406 Not Acceptable fires when a v3 API request lacks a valid Accept header. Add Accept: application/json — SDKs set this; check raw HTTP clients.
Updated Jul 1, 2026
The short answer
SendGrid returns HTTP 406 Not Acceptable when your v3 API request omits an Accept header the server can satisfy (or sends one it cannot, like application/xml). SendGrid's v3 reference says to send Accept: application/json, which official SDKs already do; SendGrid Support's 4XX article instead recommends removing the Accept header. The two sources disagree, so add the header first, then remove it if that fails. Intermittent 406s without code changes usually indicate a SendGrid incident.
SendGrid's v3 API returns HTTP 406 Not Acceptable during content negotiation: the server cannot return a response in a format your request says it will accept. In practice this almost always means the Accept request header is missing (or set to a media type SendGrid can't produce). 406 is a standard HTTP status (RFC 9110 §15.5.7), but the specific trigger here is SendGrid-side.
Accept header (most common). SendGrid's official v3 API reference lists 406 directly as "Missing the Accept header." SendGrid's v3 API is JSON-only in practice, so the client is expected to advertise that it accepts JSON.Accept header SendGrid can't satisfy. Sending something like Accept: application/xml or Accept: text/html asks for a representation the JSON-only API cannot produce, which also yields 406.Accept: application/json in their default headers; other official SendGrid SDKs (PHP, Node.js, Ruby, C#, Go, Java) are expected to do the same based on historical fixes (e.g., sendgrid-php #177 added the header to that client), though this hasn't been independently re-verified for every listed language's current version. 406 typically appears when you call api.sendgrid.com directly via cURL, fetch, requests, Guzzle, an integration platform, or an old SDK build that predates the fix.A note on conflicting official guidance: SendGrid's own docs disagree with each other on 406. The v3 API reference says it's caused by a missing Accept header and that the fix is to add Accept: application/json. SendGrid Support's 4XX troubleshooting article, by contrast, describes the cause as an inability to negotiate the Accept header and instructs readers to remove the Accept header entirely and resubmit. To make it more confusing, that same Support article's own example of the "problematic" header is itself Accept: application/json — the exact value the v3 reference recommends adding — which reads as either a documentation error on SendGrid's part or a reference to some other malformed/duplicate header state that isn't clearly explained. In practice: add Accept: application/json first, since that matches current SDK behavior and the v3 reference; if the 406 persists, try removing the Accept header entirely per SendGrid Support's guidance, and consider contacting SendGrid support directly since their own docs disagree.
Add an Accept: application/json header to the request (and make sure Content-Type: application/json is set on requests with a body). Using the current v3 Mail Send endpoint:
curl --request POST \--url https://api.sendgrid.com/v3/mail/send \--header 'Authorization: Bearer YOUR_SENDGRID_API_KEY' \--header 'Accept: application/json' \--header 'Content-Type: application/json' \--data '{"personalizations": [{"to": [{"email": "recipient@example.com"}]}],"from": {"email": "verified_sender@example.com"},"subject": "Test Subject","content": [{"type": "text/plain", "value": "testing text body"}]}'
In code, prefer the official SDK, which sets these headers for you:
import osfrom sendgrid import SendGridAPIClientfrom sendgrid.helpers.mail import Mailmessage = Mail(from_email="verified_sender@example.com",to_emails="recipient@example.com",subject="Test Subject",plain_text_content="testing text body",)sg = SendGridAPIClient(os.environ["SENDGRID_API_KEY"])response = sg.send(message) # SDK sends Accept: application/json
Checklist:
Accept: application/json on every request; don't send Accept: application/xml or other non-JSON types. If that doesn't clear the 406, removing the Accept header entirely (so a JSON default applies) is SendGrid Support's documented alternate fix — see the conflicting-guidance note above.Note: the legacy v2 Web API (/api/mail.send.json with api_user/api_key form fields) is deprecated — SendGrid strongly recommends migrating to the v3 Bearer API-key endpoints shown above. (The v2 endpoint still functions, but it no longer receives new features and should not be used for new integrations.)
References
FAQ
SendGrid's v3 API reference lists 406 as 'missing the Accept header,' and the practical fix is to always send Accept: application/json. The official SDKs set it automatically, so you only need to add it manually when calling the API with a raw HTTP client. If adding the header doesn't resolve it, SendGrid Support's troubleshooting doc for 406 also recommends removing the Accept header entirely as an alternate fix — see below.
One API, every provider
Courier connects to your email, SMS, and push providers, handles retries and failover, and surfaces delivery errors in plain language.
Reply-code definitions per RFC 9110 §15.5.7. Last reviewed Jul 1, 2026. Courier is not affiliated with third-party providers; error behavior may vary by implementation.
© 2026 Courier. All rights reserved.