Sending

Send email

A single channel-tagged endpoint sends your transactional email.

Send an email

Send an email with one call to POST /v1/send. Each SDK gives you an emails.send helper. The raw API takes a channel-tagged body with three required fields, plus either an inline payload or a template_id.

send.ts
await sendara.emails.send({
  from: "[email protected]",
  to: "[email protected]",
  subject: "Your receipt",
  html: "<h1>Thanks for your order</h1>",
});
When you send from your own domain, the sender address is required. Set metadata.from_email (or the SDK from parameter) to an address on a verified domain. If you omit it, the API returns 422 from_required. If the domain is not verified, the API returns 422 from_not_verified. An account with no verified domain is the exception. It sends from the shared platform sender, so leave from_email unset.

The request body

The raw API accepts the following fields.

channelstringRequired
Use email. It is the only generally available send channel.
idempotency_keystringRequired
Unique key per logical send. Retries with the same key return the original result. Reusing a key with a different body returns 409.
destinationobjectRequired
Channel-specific recipient. For email: { email }.
payloadobjectOptional
Channel-specific content. For email: { subject, body_html, body_text }. Required unless you provide template_id.
message_typestringOptional
transactional. This is the default.
metadataobjectOptional
Per-send options. For email, { from_email } sets the sender and is required when sending from your own domain (omitting it returns 422 from_required). The address must be on a verified domain. from_email accepts a bare address ([email protected]) or a display-name address with the name first and the email in angle brackets (Acme <[email protected]>).
template_idstringOptional
Render a stored template instead of an inline payload.
template_varsobjectOptional
Variables interpolated into the template.
scheduled_atstringOptional
RFC 3339 dispatch time, up to 90 days ahead. Times more than one minute ahead return scheduled; nearer times enter the queue immediately.
validate_recipientbooleanOptional
When true, check the recipient syntax and domain mail records before accepting the send. Defaults to false.
store_payloadbooleanOptional
Whether to retain rendered message content after dispatch. Defaults to true; false redacts the stored payload after safe dispatch.
test_sendbooleanOptional
Send real email free to a verified test recipient, subject to the 10-per-recipient daily cap. Defaults to false.

The sender name

By default an inbox shows the bare address that you send from. To show a name, set metadata.from_email to a display-name address. Put the name first, then the address in angle brackets. Each SDK accepts the same string in its from parameter.

"metadata": { "from_email": "Acme Receipts <[email protected]>" }

If the display name holds a comma or another special character, put it in double quotation marks, as in "Acme, Inc." <[email protected]>. The reversed form <Acme> [email protected] is invalid, and the API returns 422.

The address must belong to a verified sending domain. You can also set a default sender name for a domain. Call PUT /v1/domains/{domain}/from-name, or use the dashboard (Domains → your domain → Default sender name). Every send from that domain then shows the name. A display name on a per-send from_email value replaces the default for that message.

Idempotency

The raw HTTP API requires an idempotency_key. A send with an empty key returns 400 invalid_request. Each official SDK generates a key for you before the request leaves your process. When you call the API directly, pass a stable key for the logical send. A retry with the same key returns the original result, so a network retry never sends the message twice.

A key that you reuse with a different payload returns 409 idempotency_key_reused. Sendara binds a key to the first request that succeeded with it.

Send a batch

Call POST /v1/send/batch to send many messages in one request. One batch holds up to 1000 items. Sendara processes each item on its own. The response keeps the order of the request, and it gives a success or an error for each item. A partial success is normal.

curl https://api.sendara.dev/v1/send/batch \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '[
    { "channel": "email", "idempotency_key": "b1",
      "destination": { "email": "[email protected]" },
      "metadata": { "from_email": "[email protected]" },
      "payload": { "subject": "Hi", "body_html": "<p>Hi</p>" } },
    { "channel": "email", "idempotency_key": "b2",
      "destination": { "email": "[email protected]" },
      "metadata": { "from_email": "[email protected]" },
      "payload": { "subject": "Hi", "body_html": "<p>Hi</p>" } }
  ]'

Templates

Pass a template_id and template_vars in place of an inline payload. Sendara then renders the stored template. This keeps your copy out of your codebase.

The message type

message_type is transactional, which is also the default. Use it for receipts, one-time passwords, account alerts and other messages triggered by a user or system event.

Other channels

Email is the only send channel that is generally available. The send endpoint carries a channel tag so that the platform can add a channel later. The other channels do not accept a production send.

  • The sms channel and the voice channel carry one-time passwords. A feature flag holds both off. A send with channel: "sms" or channel: "voice" returns 422 channel_not_enabled.
  • The push channel and the webhook channel are not production send channels.

Common questions

My SDK call works, but my cURL request returns 400. Why?
The raw API takes a channel-tagged envelope, and the flat shape belongs to the SDKs. POST /v1/send has no top-level from, to, subject or html field. Put the recipient in destination.email, the content in payload, and the sender in metadata.from_email.
Why did my send return 422 from_required?
Your account holds a verified domain, so metadata.from_email is mandatory. Set it to an address on a verified domain. An account with no verified domain is the exception. It sends from the shared platform sender, so leave from_email unset, and it reaches only two kinds of address: the email you registered with, and an inbox you verified as a test recipient. Any other recipient returns 422 domain_not_verified.
Do I have to send an idempotency key?
Yes, on the raw HTTP API. A send with an empty key returns 400 invalid_request. Each official SDK generates a key for you. A retry with the same key returns the original result. A key that you reuse with a different body returns 409 idempotency_key_reused.
How many messages fit in one batch?
Up to 1000. A larger batch returns 413 batch_too_large. Sendara processes each item on its own, and the response keeps the order of the request. A partial success is normal.
Can I use the SMS or the voice channel?
Not today. Email is the only send channel that is generally available. A send with the channel sms or the channel voice returns 422 channel_not_enabled.