API reference
Emails
Send transactional email and inspect what was sent.
The emails resource sends a single message and lets you look up its delivery, open, and click status afterward. All requests are authenticated with a secret key.
The email object#
json
{
"id": "email_9f2c1a8b",
"to": "jane@example.com",
"subject": "Welcome to Acme",
"type": "transactional",
"status": "delivered",
"message_id": "0000018f-4c2a-...-amazonses",
"opens": 1,
"clicks": 0,
"created_at": "2026-07-10T14:23:45.123Z"
}Send an email#
POST
/v1/sendProvide either html or a stored template. The from address must be on a verified domain. Supports an optional Idempotency-Key header for safe retries.
Body parameters
fromstringRequiredSender address. Accepts
"Name <addr@domain>" or a bare address. The domain must be verified for your project.tostringRequiredRecipient email address.
subjectstringRequiredSubject line. Supports
{{variables}} when sending a template.htmlstringOptionalHTML body. Required unless
template is provided.templatestringOptionalA stored template id to render instead of
html.textstringOptionalPlain-text alternative. Auto-generated for template sends if omitted.
variablesobjectOptionalValues substituted into the template and subject, e.g.
{ "first_name": "Jane" }.ccstring | string[]OptionalCarbon-copy recipient(s). Invalid addresses are dropped.
bccstring | string[]OptionalBlind carbon-copy recipient(s).
reply_tostring | string[]OptionalReply-To address(es).
attachmentsobject[]OptionalFiles to attach — each
{ filename, content, content_type? } with content base64-encoded. See Attachments.curl -X POST https://app.getdeckle.com/api/v1/send \
-H "Authorization: Bearer sk_live_..." \
-H "Idempotency-Key: order_1234" \
-H "Content-Type: application/json" \
-d '{
"from": "Acme <hello@acme.com>",
"to": "jane@example.com",
"subject": "Welcome to Acme",
"html": "<h1>Hey Jane</h1>"
}'Statuses
200 with status: "sent" on success. If delivery isn’t configured yet you get 202 with status: "queued". Validation errors return 422; a test key sending to a real inbox returns 403; a suppressed recipient returns 422.List emails#
GET
/v1/emailsReturns a cursor-paginated list of sent emails, newest first.
Query parameters
limitintegerOptionalItems per page. Default
50, max 100.cursorstringOptionalPagination cursor from a previous
next_cursor.statusstringOptionalFilter by status, e.g.
sent, delivered, failed.typestringOptionalFilter by type, e.g.
transactional, campaign.ts
const { data, has_more, next_cursor } = await deckle.emails.list({
status: "sent",
limit: 50,
});Retrieve an email#
GET
/v1/emails/:idFetch a single email with its current status and open/click counts.
const email = await deckle.emails.get("email_9f2c1a8b");A missing or cross-project id returns 404.