DeckleDocs
Dashboard

Sending

Send over HTTP

Send email with a single authenticated POST request — no SDK required. Works from any language or runtime that can make an HTTP call.

The @deckle/sdk is just a thin wrapper around one endpoint. If you’d rather call the API directly — from a language we don’t ship an SDK for, or from a shell script — everything you need is a Bearer token and a JSON body.

The endpoint#

All sends go through a single endpoint. Send a POST request with your JSON body and authenticate with your secret API key in the Authorization header.

POST/api/v1/send
http
POST https://app.getdeckle.com/api/v1/send
Authorization: Bearer sk_live_...
Content-Type: application/json

The base URL is https://app.getdeckle.com/api/v1. Create a key in the dashboard under Developers → API keys — the full sk_live_... value is shown once at creation, so store it somewhere safe. See API keys for details.

Test vs. live keys

A sk_test_ key can only send to the AWS SES simulator (for example success@simulator.amazonses.com) or your own verified domains. Swap in a sk_live_ key to reach real inboxes.

Send a request#

The body is JSON with snake_case fields. to, from, and subject are required, plus either html or template. The from address must be on a domain you’ve verified.

curl -X POST https://app.getdeckle.com/api/v1/send \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <hello@acme.com>",
    "to": "jane@example.com",
    "subject": "Welcome to Acme 👋",
    "html": "<h1>Hey Jane</h1><p>Thanks for joining.</p>"
  }'

You can pass cc, bcc, reply_to (a string or array), a plain-text text alternative, and attachments in the same body. For the full field list, see the emails API reference.

The response#

A successful send returns 200 with a JSON object describing the queued email. The id is Deckle’s email log id (prefixed email_) — use it to look up status later.

json
{
  "id": "email_2Nc8Kx1mQvRz",
  "status": "queued",
  "messageId": "0100019200000000-11111111-2222-3333-4444-555555555555-000000@eu-west-1.amazonses.com"
}

Not sending yet?

If your project doesn’t have delivery configured, the request returns 202 and the email is accepted and queued rather than sent immediately. Verify a domain to start delivering.

Using a template#

Instead of raw html, pass a template id and a variables object. Deckle renders the stored template with your values, injects a plain-text alternative, and — unlike raw HTML sends — automatically adds open and click tracking.

json
{
  "from": "Acme <hello@acme.com>",
  "to": "jane@example.com",
  "subject": "Your Acme receipt",
  "template": "tmpl_welcome",
  "variables": {
    "first_name": "Jane",
    "plan": "Pro"
  }
}

Placeholders in the template use {{variable}} syntax, with an optional fallback like {{first_name | "there"}}. The subject can be overridden per send, as shown above. See Templates and Variables & personalization for more.

Errors#

Errors return the appropriate HTTP status and a JSON body of the shape { "error": "message" }. The most common ones:

StatusMeaning
401Missing or invalid API key. Check the Authorization header and that the key hasn’t been revoked.
422The request was understood but couldn’t be processed — a missing required field, an unverified from domain, or a suppressed recipient.
429Rate limited. You’ve exceeded 120 requests per minute for this project; retry after the number of seconds in the Retry-After header.

Idempotent sends

Add an Idempotency-Key header to safely retry a send. A repeat with the same key returns the first result with idempotent: true instead of sending again. See Idempotency.

Next steps#