Documentation Index
Fetch the complete documentation index at: https://docs.autosend.com/llms.txt
Use this file to discover all available pages before exploring further.

Overview
The official AutoSend Convex component is a drop-in integration for sending transactional email from your Convex backend. It wraps the AutoSend API with queueing, deterministic idempotency, automatic retries, webhook verification, and full delivery lifecycle tracking, so you only need to callsendEmail from a mutation and the component handles the rest.
The package is open source on GitHub and published on npm as @autosend/convex.
Install with your AI assistant
If you use an AI coding assistant (Cursor, Claude Code, Copilot, Codex, etc.), paste the prompt below into your editor. It points the assistant at the official Convex component docs andllms.txt, then asks it to produce a setup checklist tailored to your project.
Install prompt
What you get
- Queue-first sending.
sendEmailandsendBulkenqueue jobs and automatically trigger queue processing. - Idempotency. Duplicate requests resolve to the same
emailId, so retried mutations never double-send. - Retries with backoff. Network errors,
429, and5xxresponses are retried on a configurable schedule. - Lifecycle tracking. Every email moves through
queued,sending,retrying,sent,failed, orcanceled. - Webhook ingestion. HMAC SHA-256 signature verification, timestamp skew protection, and per-delivery dedupe out of the box.
- Templates, CC/BCC, attachments, and unsubscribe groups are all supported.
- Test sandbox. Optional
sandboxTorewrites recipients while you are still wiring things up.
Prerequisites
Before you begin, make sure you have:- An AutoSend account with an API key
- A verified sending domain
- A Convex project (Convex CLI installed and
npx convex devrunnable) - Node.js 18+ installed locally
Install
Add the component and the Convex SDK to your project:Setup
Create a client wrapper
Wrap the generated component reference in an
AutoSend instance you can reuse from any Convex function.convex/email.ts
Set your secrets
Push your AutoSend API key and webhook signing secret to the Convex deployment environment. Both are read by the component at runtime.
The webhook secret is shown when you create a webhook endpoint in the AutoSend dashboard. See Verifying webhook requests for details.
Persist component config
The component keeps its own config in a Convex table so it can read settings from queries, mutations, and actions. Call Run the mutation once from the Convex dashboard, or call it from a setup script. Subsequent calls merge new values into the existing config unless you pass
setConfig once from a mutation to write it.convex/admin.ts
replace: true.Mount the webhook route
The component ships an HTTP handler that verifies AutoSend webhook signatures and updates the email status table. Register it on your Convex HTTP router.The route is mounted at Pass
convex/http.ts
/webhooks/autosend by default. After your next npx convex deploy, point your AutoSend webhook endpoint at:{ path: "/custom/path" } as a third argument to registerRoutes if you need a different URL.Send your first email
CallsendEmail from any Convex mutation. The component enqueues the job and triggers the processor automatically, so you do not need to schedule anything yourself.
convex/sendWelcome.ts
from, the component uses the defaultFrom you set in config. The returned emailId is the handle you use to query status and webhook events later.
Sending variants
Send with a template
Send with a template
Reference an AutoSend email template by ID and pass merge fields via When you use
dynamicData.templateId, subject and html are optional. See template variables for the syntax supported in your template.CC, BCC, and reply-to
CC, BCC, and reply-to
Attachments
Attachments
Attach files inline as base64 or by URL.Provide either
fileUrl or content, never both.Bulk send
Bulk send
Send the same payload to up to 100 recipients in one call.Each recipient is queued as a separate email, so retries and webhook events are tracked per recipient.
Bulk send with per-recipient data
Bulk send with per-recipient data
Pass Per-recipient values are also forwarded as
recipientData keyed by email to interpolate {{placeholders}} into subject, html, and text per recipient.dynamicData for that recipient, overriding any shared dynamicData you pass.Idempotency
Idempotency
Pass Without an explicit key, the component derives one from the payload, so identical payloads also deduplicate.
idempotencyKey to guarantee a single send for a given logical operation. If your mutation runs twice (Convex retries on conflict), the second call returns the same emailId with deduped: true.Track status and events
The component stores every email and its webhook events in Convex, so you can query them from any Convex query.convex/emailStatus.ts
cancelEmail only works while the email is in queued or retrying. Once it reaches sending, sent, or failed, it is locked in.
Email lifecycle
| Status | Meaning |
|---|---|
queued | Accepted and waiting to be claimed by the processor |
sending | Currently being sent by the queue processor |
retrying | Previous attempt failed and a retry is scheduled |
sent | Accepted by AutoSend |
failed | Retries exhausted or non-retryable error |
canceled | Canceled via cancelEmail before send |
maxAttempts and retryDelaysMs in config.
Configuration
setConfig accepts these fields. Anything you omit keeps its existing value (unless you pass replace: true).
| Field | Type | Default | Description |
|---|---|---|---|
autosendApiKey | string | unset | Bearer token for the AutoSend API |
webhookSecret | string | unset | HMAC secret used to verify incoming webhooks |
defaultFrom | string | unset | Fallback sender address when from is omitted |
defaultReplyTo | string | unset | Fallback reply-to address |
testMode | boolean | true | Rewrites every recipient to sandboxTo |
sandboxTo | string[] | [] | Recipients used when testMode is enabled |
rateLimitRps | number | 2 | Max sends per queue run |
retryDelaysMs | number[] | [5000, 10000, 20000] | Delay schedule between retries |
maxAttempts | number | 4 | Total attempts including the first try |
sendBatchSize | number | 25 | Max queue items processed per run |
autosendBaseUrl | string | https://api.autosend.com | API base URL (override for staging) |
projectId | string | unset | Required when using an Account API Key (ASA_ prefix) |
getConfig. It returns every value above except autosendApiKey and webhookSecret, plus hasApiKey and hasWebhookSecret booleans you can use in admin UIs.
Go live checklist
Before flippingtestMode to false:
- Verify your sending domain in the AutoSend dashboard (domain setup).
- Deploy your Convex backend so the webhook route is reachable.
- Add the webhook URL
https://YOUR-DEPLOYMENT.convex.site/webhooks/autosendto your AutoSend project and copy the signing secret intoAUTOSEND_WEBHOOK_SECRET. - Send a test email with
testMode: trueand confirm the status moves tosentand you seeemail.deliveredinlistEvents. - Update config with
testMode: falseand a realdefaultFrom.
Troubleshooting
Emails stay in `queued` forever
Emails stay in `queued` forever
sendEmail triggers the processor automatically, but if a deploy was interrupted you can sweep the queue manually:Webhook signature verification fails
Webhook signature verification fails
Make sure the
webhookSecret in your component config matches the secret shown in the AutoSend dashboard for that exact endpoint. The component validates HMAC SHA-256 over the raw body and rejects timestamps older than 2 minutes. See verifying webhook requests for the full spec.`projectId is required` error on send
`projectId is required` error on send
You are using an Account API Key (
ASA_ prefix) without setting projectId. Either switch to a Project API Key (AS_ prefix), or add projectId to your config.Recipients are getting overridden
Recipients are getting overridden
testMode is still true. Every send is being rewritten to sandboxTo. Update your config with testMode: false to send to real recipients.