API v1Private beta. The API is stable; send limits are low while the shared domain warms up.

Quickstart

cURL quickstart

The same flow with plain HTTP. Works from any language.

Base URL: https://api.send0.dev. Every request needs Authorization: Bearer <key>. Requests and responses are JSON.

export SEND0_API_KEY=s0_live_…

Create an inbox

curl https://api.send0.dev/v1/inboxes \
  -H "Authorization: Bearer $SEND0_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "name": "research-agent" }'
{ "object": "inbox", "id": "ibx_7Hc2…", "address": "research-agent@send0.email", "send_policy": "reply_only", … }

Wait for a message

curl "https://api.send0.dev/v1/inboxes/ibx_7Hc2…/messages/wait?from=*@acme.dev&timeout=60" \
  -H "Authorization: Bearer $SEND0_API_KEY"
{
  "object": "wait_result",
  "timed_out": false,
  "message": {
    "id": "msg_9Kd2…",
    "subject": "Your Acme verification code",
    "extracted": { "otp": "482913", "links": ["https://acme.dev/verify?…"], "action_link": "https://acme.dev/verify?…" },
    …
  }
}

On timeout you get {"timed_out": true, "message": null} with status 200. The longest single wait is 120 seconds.

Reply

curl https://api.send0.dev/v1/messages/msg_9Kd2…/reply \
  -H "Authorization: Bearer $SEND0_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "text": "Thanks, confirmed." }'

201 with the sent message, or 202 with a draft if the inbox requires approval.

Send an Idempotency-Key with every POST. If the network drops and you retry with the same key and body, you get the original response back instead of a second email. Keys are remembered for 24 hours.

The full contract is in the OpenAPI spec. See REST API.

On this page