Wire up email sending for AI agents
A machine-readable path for coding agents and assistants that need to add transactional email to someone else's project — what to call, in what order, and which checks to run before every send.
Download OpenAPI 3.1Before you write any code
- Ask the user for a project API key, or have them create a sandbox key at https://app.srs-postline.com/en/login — never invent, guess, or reuse a key from another project.
- Put the key in a server-side environment variable. Do not place it in frontend code, a mobile app bundle, a public repo, or a committed .env file.
- Use an srs_live_ key. Before domain verification, send from sandbox@srs-postline.com only to a project member; verified domains may send externally within plan quotas.
- Read /llms.txt and openapi/postline.yaml before generating request code; do not guess field names or endpoints.
Minimal send
POST /v1/emails
Authorization: Bearer srs_live_...
Idempotency-Key: <stable-id-per-logical-send>
Content-Type: application/json
{
"from": "Sender Name <info@example.com>",
"to": ["user@example.net"],
"subject": "Subject",
"html": "<p>Body</p>",
"text": "Body"
}Checks to run before every send
- Always send an Idempotency-Key derived from the triggering action (order ID, event ID) so retries cannot double-send.
- Never put OTP codes, password-reset tokens, or other secrets in a field that gets logged or forwarded outside the message body.
- Request the narrowest API key scope the task needs (emails:send is enough for sending; do not ask for domains:write or api_keys:write unless the task requires it).
- Cap recipients per call at 100. Attachments and custom headers are not accepted by the current API; reject or link files instead of implying they were attached.
- Do not silently retry on 4xx responses. Only 429 and 503 are safe to retry, and only with backoff.
Handle every response code
- 202 — queued, not delivered. Store the returned id if you need to look up status later.
- 400 — invalid payload; fix the request, do not retry unchanged.
- 401 — invalid or expired key; stop and surface this to the user, do not fabricate a new key.
- 403 — missing scope or the sending domain is not verified yet; tell the user to verify the domain before continuing.
- 422 — recipient is suppressed (past bounce/complaint); do not retry that recipient.
- 429 — rate limited; back off and retry later, do not loop tightly.
- 503 — queue unavailable; retry with backoff, do not fall back to an unofficial transport.
If the task includes receiving events
Register a webhook endpoint over HTTPS only. Recompute the signature yourself before trusting any payload; do not skip verification because a request 'looks internal'.
signature = HMAC-SHA256(webhook_secret, timestamp + "\0" + event_id + "\0" + raw_body)
compare to header Postline-Signature (constant-time compare)
reject if Postline-Timestamp is outside your allowed window
store event_id and process each event exactly onceMachine-readable references
- /llms.txt — condensed index of these rules for agent context windows.
- /openapi/postline.yaml — full OpenAPI 3.1 schema for every endpoint.
- /en/api/ — human API reference.
- /en/webhooks/ — webhook signature and retry details.
Current access model
Current dashboard keys use srs_live_. Before a customer From-domain is verified, use the shared sandbox sender only for project-member recipients. After DNS verification, external sending is governed by plan quotas, suppression, recipient throttles, and abuse controls. A 202 response means queued, not delivered.
Integration resources
Use the copy-paste guide for humans and AI agents, and treat OpenAPI as the field-level source of truth.