DocsComing soon

Quickstart

Send your first email with one request and check what happened to it.

You need an active account, a verified sending domain and an API key from the dashboard. Every request goes to https://api.letr.dev with the key as a Bearer token.

No domain verified yet? Send to [email protected] from [email protected] with an API key that may send (sending_access or full_access): the email never leaves letr.dev, its events are real, and it does not count toward usage. Test recipients lists every outcome.

Send an email

The smallest valid request names a sender, a recipient, a subject and a body:

curl https://api.letr.dev/v1/emails \
  -H "Authorization: Bearer $LETR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <[email protected]>",
    "to": "[email protected]",
    "subject": "Hello from Acme",
    "text": "It works."
  }'

letr.dev stores the email and answers 202 Accepted with its id. Delivery happens in the background.

{ "id": "em_gk3lx0aqw2rz9vb7nc1ep4ty", "status": "queued" }
Sending an emailYour app posts the email with an idempotency key and gets 202 with its id. Independently of each other, letr.dev posts the event email.sent, signed, to your webhook endpoint and hands the email to the recipient's mail server; once that server accepts it, letr.dev posts email.delivered. Your app verifies each signature and answers 2xx.Recipient's mail serverletr.devYour apppar[event][delivery]verify the signaturePOST /v1/emails, Idempotency-Key202 { id, status: queued }webhook email.sent, signed2xxSMTP, DKIM-signed250 acceptedwebhook email.delivered, signed2xx

The from-address must use a verified domain of your account, otherwise the answer is 422 domain_not_verified. Errors lists every code.

Check the status

curl https://api.letr.dev/v1/emails/em_gk3lx0aqw2rz9vb7nc1ep4ty \
  -H "Authorization: Bearer $LETR_API_KEY"

The answer carries the current status (scheduled, canceled, queued, sent, delivered, deferred, bounced, complained or failed) and every event with its type, recipient, SMTP detail and time. Instead of asking, let letr.dev tell you: a webhook receives each event as it happens.

Email statusA new email is queued, or scheduled when it has scheduledAt. A scheduled email becomes queued when its time comes, canceled before that, or failed when its time comes while the account is paused or disabled. From queued an email moves on to sent, deferred or one of the final statuses delivered, bounced and failed; a late bounce report turns delivered into bounced, and every final status can become complained. Whatever its status, an email becomes canceled when an address is erased while a recipient still waits.queued or laterdelivered, bounced or failedlate bounce reportwith scheduledAtcancel, key revoked, key rolled(due after its grace period),address eraseddue while the accountis paused or disabledPOST /v1/emailsscheduledAt reachedaddress erased whilea recipient still waitsdeliveredbouncedfailedqueuedsentdeferredcomplainedscheduledcanceled

Each arrow without a label is the event of the same name, for example email.sent. The status never moves back to an earlier stage, but it can skip one. A final status (delivered, bounced or failed) can still change to another final status or to complained: for one recipient through a late bounce report, for several recipients through the event letr.dev processed last.

Next