What SendGrid answered
On 16.10.2026 we sent the same mail request to SendGrid several ways. The message depends on what the Authorization header contained:
| What we sent | SendGrid's message |
|---|---|
Bearer SG.… with a made-up key | The provided authorization grant is invalid, expired, or revoked |
Bearer with nothing after it | Permission denied, wrong credentials |
The key without the word Bearer | Permission denied, wrong credentials |
| No Authorization header | Permission denied, wrong credentials |
SMTP, user apikey, made-up key | 535 Authentication failed: The provided authorization grant is invalid, expired, or revoked |
| SMTP, user is an email address | 535 Authentication failed: Bad username / password |
So “authorization grant is invalid” means SendGrid read a key and rejected it. “Permission denied, wrong credentials” means it did not find a key in the form it expects.
The library sends “undefined” as a key
With @sendgrid/mail 8.1.6 we called setApiKey(process.env.SENDGRID_API_KEY) while the variable was unset. The library printed one warning, API key does not start with "SG.", and sent the request anyway. SendGrid answered with the same “authorization grant is invalid” 401, and the error had code: 401 and message: "Unauthorized". So this message can also mean the secret is simply not set on the server, which is the first thing to check when it works on your computer and not after deploy.
Fixing it
- In SendGrid, create a new API key with Mail Send access. SendGrid's docs say the console displays the key only once, at creation, so copy it then.
- Put it in the server's secrets (
SENDGRID_API_KEY) and redeploy or restart. A key that was deleted or regenerated stops working at once. - Send it as
Authorization: Bearer SG.…. For SMTP, the user is literallyapikeyand the password is the key. - Call SendGrid from a server. Its API answered the browser's preflight with
Access-Control-Allow-Origin: https://sendgrid.api-docs.io, so a call from your own site is blocked by CORS, and a key in page code would be public anyway.
SendGrid also runs a separate EU host, api.eu.sendgrid.com. With our fake key it gave exactly the same answer as the main host, so this error cannot tell you that you picked the wrong one; check which host your account was set up for.
Do you need a SendGrid key for a contact form?
If the API key is in your project only so a contact form can email you, a form that posts to Formgong at https://formgong.com/submit needs no key from a mail provider, and Formgong sends the notification. See the HTML guide.
Frequently asked questions
What does The provided authorization grant is invalid, expired, or revoked mean?
SendGrid found an API key in your request and did not accept it. The key was deleted, regenerated, mistyped, belongs to another account, or is the text undefined.
What is the difference from Permission denied, wrong credentials?
On our test SendGrid used that message when there was no usable Bearer key at all: an empty header, no header, or the key without the word Bearer.
What username does SendGrid SMTP need?
The word apikey, with the API key as the password. An email address as the user gave 535 Bad username / password on our test.
Sources and documentation
Official references for this guide: SendGrid: API keys, SendGrid: Integrating with the SMTP API, SendGrid: v3 API errors. HTML contact form, where data is stored.
Related guides
- Lovable form submissions to email and Telegram
- HTML contact form without a backend: a working example
- How to send website form submissions to Telegram
- Contact form not sending email? Check where it stops
- Managing website leads in Telegram without a CRM
- Form backend for Lovable, Bolt, v0, Cursor
- Telegram bot for a contact form: build or skip?
- GDPR form backend: 7 checks before you choose
- Lovable form not sending email? 6 fixes
- Netlify Forms not working? React and Bolt fixes
- Stop contact form spam without a CAPTCHA
- GitHub Pages contact form: a working setup
- Mailto Form in HTML: Why It Fails and What to Use
- HTML form to Google Sheets: 2 free methods
- Webflow form submission limit: what to do at 50
- Turnstile vs reCAPTCHA vs hCaptcha for forms
- Contact Form 7 and Elementor forms to Telegram
- Squarespace contact form not sending email?
- Shopify contact form: where do messages go?
- Google Form to Telegram: free Apps Script way
- Wix contact form not sending email? Fixes
- EU / GDPR Formspree alternatives compared
- HTML form action attribute explained
- How do HTML forms work? The HTTP request
- Types of Injection Attacks on Web Forms (2026)
- Indirect Prompt Injection in MCP
- MCP Rug Pull Attack: Detect Tool Changes
- Form without a backend: 7 ways that work
- Thank-you page after form submission (HTML)
- Indirect Prompt Injection Examples (2023–2026)
- Indirect Prompt Injection via Email
- What Is Tool Poisoning in MCP?
- WordPress contact form without a plugin
- Send email from frontend JavaScript
- How to Prevent Indirect Prompt Injection
- Honeypot Form Field: How to Add One That Works
- Contact Form with File Upload (HTML, No PHP)
- Angular contact form without a backend
- Send form submissions to Slack or Discord without Zapier
- Verify a form webhook signature (HMAC-SHA256)
- Contact forms that send nothing: 793 AI-built sites tested
- v0 contact form that actually sends: 3 ways
- How we tested AI-built contact forms, and 12 bugs we hit
- Cloudflare vs Netlify free plan: hosting that never pauses
- EmailJS 412 “Gmail_API: Invalid grant”: reconnect Gmail
- Resend “You can only send testing emails”: verify a domain
- Supabase Edge Function blocked by CORS policy: 3 causes
- Formspree “Form not found” and other errors: fixes
- Web3Forms errors: “Invalid access key” and 403 explained
- How to add customer reviews to your website for free
- Getform not working? “This form has been deleted” and more
- Next.js contact form not working? 6 errors, reproduced
- Webflow form not sending email? What to check, tested
- FormSubmit not working? “This form needs Activation” fix
- Contact form “TypeError: Failed to fetch”: causes and fixes
- WooCommerce product enquiry form
- Contact Form 7 vs WPForms
- Gravity Forms alternative free
- WordPress contact form block
- 535-5.7.8 Username and Password not accepted (Gmail)
- 535 5.7.3 Authentication unsuccessful: Office 365 SMTP
- Nodemailer “Missing credentials for "PLAIN"”: the fix
- Nodemailer “Greeting never received”: port 465 fix
- Nodemailer SSL “wrong version number”: the port fix
- Nodemailer “self-signed certificate in certificate chain”
- Nodemailer ECONNREFUSED 127.0.0.1:587: missing SMTP host
- Mailgun 401 Forbidden: why the API rejects your key
- “Edge Function returned a non-2xx status code”: the fix
- Next.js “Body exceeded 1 MB limit”: Server Action fix
- Unexpected token '<', "<!DOCTYPE "... is not valid JSON
- “TypeError: Body is unusable”: body has already been read
- Turnstile “timeout-or-duplicate” and other siteverify errors
- Turnstile vs hCaptcha vs reCAPTCHA: speed and size tested
- Judge.me reviews not showing on Shopify: how to fix it
- Judge.me review carousel not showing: how to fix it
- Yotpo reviews not showing on Shopify? Check the app embed
- Loox reviews not showing on product page: how to fix
- Shopify reviews not showing: what to check first
- How to show reviews on Shopify
- GDPR for website forms: what each type of form needs
- WooCommerce reviews not showing: how to fix it
- Stamped.io reviews not showing on Shopify: how to fix it
- Etsy reviews not showing: why and what to do
- Trustpilot widget not loading: how to fix TrustBox
- Yotpo problems in 2026: what merchants report
- Contact Form 7 “error trying to send your message” fix
- Elementor form “Your submission failed because of an error”
- Framer form not sending email or not working: what to check
- Carrd contact form not working: plans, spam and errors
- Google review link not working: what customers see and why
- tawk.to widget not showing on your website: causes and fixes
- How to add questions and answers to your product page
- “Failed to send a request to the Edge Function”: fixes
- Next.js “Failed to find Server Action”: what it means
- Brevo “unauthorized: Key not found” 401: the fix
- Amazon SES “Email address is not verified”: the fix
- Shopify contact form not working: how to fix it
- Judge.me alternative for WooCommerce after the 2025 shutdown
- Free WooCommerce review plugins compared on the free version
- WooCommerce review reminder emails without a paid plugin
- Add Voice Recording to a Website Form
- Contact Form 7 spam: how to stop it
- WPForms not sending email: how to fix it
- Contact form emails going to spam: how to fix it
- HTML form not submitting: how to fix it
- Contact form not working: how to find the fault
- Webflow form spam: how to stop it
- Website form to Notion: how to set it up
- Website form to WhatsApp: what works and what does not