SendGrid¶
SendGrid (Twilio SendGrid) works with pg_relay two ways: over the SMTP transport with an API key as the password, or over the webhook transport against its v3 Mail Send REST API. Both authenticate with the same API key — create one in the SendGrid dashboard with the Mail Send permission, and keep it out of the database with an _env: reference (Keeping Secrets Out of the Database).
Over SMTP¶
{
"host": "smtp.sendgrid.net",
"port": 587,
"security": "starttls",
"auth": "plain",
"username": "apikey", // literally the string "apikey"
"password": "_env:SENDGRID_API_KEY",
"from": "[email protected]", // an authenticated sender
"timeout_seconds": 30
}
The username is the literal string apikey — not your account name, and not the key's id. The password is the API key itself. The message block is the standard one from the SMTP chapter.
Over the REST API (webhook)¶
// profile
{
"url": "https://api.sendgrid.com/v3/mail/send",
"auth": {"style": "bearer_header", "secret": "_env:SENDGRID_API_KEY"},
"timeout_seconds": 30
}
// message — SendGrid's own request shape, sent verbatim
{
"personalizations": [{"to": [{"email": "[email protected]"}]}],
"from": {"email": "[email protected]"},
"subject": "disk alert",
"content": [
{"type": "text/plain", "value": "volume is filling"},
{"type": "text/html", "value": "<p>volume is filling</p>"}
]
}
As with every webhook target, message is the complete provider-correct body — pg_relay_notifier builds it, and its classify_webhook_response function interprets the reply. For SendGrid, have it treat:
202assent— SendGrid's success is an empty-bodied202 Accepted, with the message's id in thex-message-idresponse header (headers reachclassify_webhook_responselower-cased, so that exact spelling is what to look up; return it as the provider reference).429, any5xx, andhttp_status = 0(no response) asretry.- Any other
4xxasfailed— a malformed body, a bad key, an unauthenticated sender.
Things SendGrid enforces¶
from must be an address you've completed Sender Authentication for (a verified single sender, or an authenticated domain). An unauthenticated sender is rejected — a 5xx over SMTP, a 403 over the API — and resolves as a permanent failure either way.
Continue to Postmark.