Send emails with Trigger.dev
Install the Trigger.dev adapter and call sendEmail from a task.
What you'll build
A Trigger.dev task that sends a welcome email. The adapter tells Trigger.dev which errors to retry, and when.
Before you start
- An API key with Send only access. Full access also works. See Create an API key. Support keys cannot send.
- A verified sending domain. See Add and verify a domain.
frommust be an address on it. - A cluster that is ready to send (
sending_readyistrue). See Clusters. - Your team id and cluster id. Both are on the API keys page.
- Node.js 18 or later.
Install
Install the adapter with @trigger.dev/sdk.
Send your first email
Define a task that calls sendEmail. Use defaultRetry and put catchPostShibaError on catchError. Pass a stable idempotencyKey so a retried run does not send twice.
Trigger the task with { to: "you@example.com", id: "user_123" }. sendEmail returns { queued, messageId }. The message then shows under Events in the dashboard.
clusterId is required. The adapter posts to POST /api/v1/teams/:team_id/clusters/:cluster_id/sends with an Idempotency-Key header.
Attachments and templates
Attach a file
Pass attachments with filename, contentType, and base64 content. Up to 10 files, 18 MB in total. See Attachments for allowed types.
Send a published template
Pass template with the alias or public id and its variables. Leave out html and text.
Keep the key safe
Use a Send only key in your tasks. It can send email and call GET /api/v1/users/me. Every other request returns 403 forbidden.
| If this key leaks | Send only | Full access |
|---|---|---|
| Send mail from your verified domains | Yes | Yes |
| Read events, recipients, templates, and sent messages | No | Yes |
| See SMTP passwords and webhook secrets | No | Yes |
| Change clusters, domains, credentials, webhooks, and suppressions | No | Yes |
- Keep Full access keys for setup scripts, the CLI, and MCP. Don't deploy one with your tasks.
- Add
POSTSHIBA_API_KEYto your Trigger.dev project's environment variables and passprocess.env.POSTSHIBA_API_KEYasapiKey. Don't commit it, log it, or put it in a task payload. - Send from the task. Never put a key, even a Send only key, in browser or mobile code.
- Create one key per Trigger.dev environment, so Development and Production never share one. If a key leaks, delete it on API keys and create a new one. Deleting stops it straight away.
Troubleshooting
A response outside 2xx throws PostShibaHttpError with status, code, and retryable. Permanent errors become AbortTaskRunError.
| Status | error |
What the adapter does |
|---|---|---|
401 |
Invalid token or no user signed in |
Stops the run without retrying. Check the API key. |
403 |
forbidden, domain_unverified, or kyc_required |
Stops the run. Support keys cannot send, so use a Send only key and a verified from. While your team is pending production approval, send only to team members, live inbox addresses, and inbox forward-to addresses. |
409 |
idempotency_conflict |
Stops the run. The same idempotencyKey was used with a different message. |
422 |
invalid |
Stops the run. code and the error message say which field. |
429 |
throttled |
catchPostShibaError schedules the retry for the start of the next UTC hour. See What happens at your cap. |
Every other status is on Errors.
Next steps
- Verify webhook requests, or use the adapter's
handleWebhookto trigger a task for each delivery event. - Unique args to get your own ids back on delivery webhooks.
- Send emails with Node.js for the plain client.
- SDKs for every language client.