dispatch. / docs Start building →

Send your first email.

Send an email with one API request. We handle the delivery.

{ }Your app
↗Dispatch
Their inbox
Test mode validates requests without sending real email.Let’s go ↓
01

Create an API key

Open Dashboard → API keys and create a test key. Store it in your server environment, never in client-side code.

Test keys start with ds_test_. Live keys start with ds_live_.

02

Send a test email

Make a POST request to /v1/emails. Set your sender, recipient, subject, and HTML.

POSThttps://api.dispatch.email/v1/emails↗

For your first request, use hello@dispatch.email as the sender and delivered@dispatch.test as the recipient.

03

Check the response

A 202 Accepted response means your email is queued for delivery. Keep the email ID to track its status.

email.queuedmsg_8f2c91a7 · accepted for delivery
202

Delivery is asynchronous. Handle email.delivered and email.bounced events in your webhook handler.

A safe place to start

Test mode validates your requests without sending real email. Use a test key and a @dispatch.test recipient while you build.

i

Ready for real inboxes? Verify your sending domain and swap in a live API key. Your code stays the same.

Install an SDK

Our libraries handle authentication, retries, and typed responses.

Was this helpful?

Send an email

Deliver a transactional email with a single request.

POST/v1/emails
Bearer tokenJSON request body202 Accepted

Body parameters

application/json
fromstringrequired

The sender’s email address. Must belong to a verified domain, or use the test sender in test mode.

"Northstar <hello@northstar.studio>"
tostring[]required

Recipient email addresses. Up to 50 recipients per request.

["alex.morgan@example.com"]
subjectstringrequired

The email subject. Maximum 998 characters.

"Your Northstar receipt"
htmlstringconditional

Required if text is omitted. Provide HTML, plain text, or both.

"<p>Thanks for your order, Alex.</p>"
textstringconditional

Required if html is omitted. If HTML is provided, we generate a plain-text version when text is omitted.

reply_tostringoptional

The address that receives replies. Defaults to the sender.

Send once. Even if you retry.

Set an Idempotency-Key header to safely retry a request. Reusing the same key and body returns the original response for 24 hours.

Idempotency-Key: order_ns_1048

A reused key with a different body returns 409 Conflict.

Response

202 Accepted

The email object confirms your request was accepted. Delivery status arrives separately through webhooks.

idstring

Unique email identifier.

statusstring

queued when first accepted.

created_atstring

Creation time in ISO 8601 format.

Error codes

Errors return a consistent JSON body with a code, a message, and a request ID for troubleshooting.

HTTPCode & recovery
400

validation_errorCheck the field named in the error message.

401

invalid_api_keyCheck your Bearer token and environment.

403

domain_not_verifiedVerify the domain used in your sender address.

409

idempotency_conflictUse a new key when the request body changes.

429

rate_limit_exceededWait for the Retry-After interval before retrying.

500

internal_errorRetry with the same idempotency key.

Rate limits

Each workspace can send up to 100 requests per second. Read the X-RateLimit-Remaining header to see your current allowance. A 429 response includes Retry-After in seconds.

No matches for “”

Try a field name, an error code, or “email”.

API keys

Create a test key to validate requests without sending real email. Keep it on your server.

Test environment ds_test_
Test

Set this as DISPATCH_API_KEY in your server environment.

Changelog

Small changes.
Better delivery.

Safer retries, by default

Idempotency keys now remain valid for 24 hours. Retried requests return the original email ID.

More useful error responses

Every error now includes a request ID, making it easier to trace a request with support.