Qsendyx

Send email

POST /email/messages accepts raw content or a template, never both, and returns 202 with a message you can poll.

Send a message

POST /email/messages accepts either raw content or a template, never both. With raw content, subject is required alongside html or text. With template_id, the body comes from the active version of the template and variables fills the placeholders.

curl -X POST https://api.qsendyx.com/api/v1/email/messages \
  -H "Authorization: Bearer $QSENDYX_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "from":    { "email": "you@yourcompany.com", "name": "Your Company" },
    "to":      [{ "email": "user@example.com" }],
    "subject": "Welcome aboard",
    "html":    "<h1>You are in.</h1>"
  }'
json
{
  "from":        { "email": "you@yourcompany.com" },
  "to":          [{ "email": "user@example.com" }],
  "template_id": "019f70c2-2b41-7a5e-9c3e-2f1a8d55b310",
  "variables":   { "name": "Ana", "order_id": "A-1042" }
}
Template mode — no html, no text.

Request fields

FieldNotes
fromObject with email and optional name. Must be a verified domain or sender.
toArray of recipients, at least one.
reply_toObject with email and optional name. Sets the Reply-To header — where answers go.
reply_to_listArray of the same objects, up to 1000. Mutually exclusive with reply_to.
subjectRequired unless template_id is present, where it overrides the template.
html / textRaw content. Mutually exclusive with template_id.
template_id / variablesTemplate mode. Templates are sandboxed — they never execute code.
typetransactional (default) or marketing. Separate identities, separate reputation.
send_atSchedules the send. UTC.
tags / metadataYours. Returned on events, useful for correlation.
trackingPer-message opens and clicks toggles.

Where replies go

reply_to sets the Reply-To header of the delivered message — the address the recipient reaches when they hit Reply. It is independent of from: the message can be signed by no-reply and still be answerable. Send an object with email and an optional name, the same shape as from; the name travels into the header as the display name.

json
{
  "from":     { "email": "no-reply@yourcompany.com", "name": "Your Company" },
  "to":       [{ "email": "support@yourcompany.com" }],
  "reply_to": { "email": "ana@customer.com", "name": "Ana Ribeiro" },
  "subject":  "New contact form submission",
  "text":     "Ana wrote: my invoice has the wrong address."
}
A no-reply From with a Reply-To that reaches a person.

This matters most for the two halves of a contact form. The copy that goes to your team should reply to whoever wrote in; the confirmation that goes back to them should reply to your monitored inbox. Without it, both ends answer into a no-reply address and the message is lost — people reply to "do not reply" messages anyway, to add a detail or attach a document.

Reply-To is an address list in RFC 5322, so more than one address is legal. Use reply_to_list for that, with up to 1000 entries of the same shape. The two fields are mutually exclusive: sending both is a 422, never a silent pick — choosing for you would send a reply somewhere you did not ask for.

json
{
  "from": { "email": "no-reply@yourcompany.com", "name": "Your Company" },
  "to":   [{ "email": "ana@customer.com" }],
  "reply_to_list": [
    { "email": "support@yourcompany.com", "name": "Support" },
    { "email": "billing@yourcompany.com" }
  ],
  "subject": "We received your request",
  "text":    "Reply to this message and both teams will see it."
}
One reply reaches support and billing at once.
Omit both fields and no header is invented — replies fall back to from, which is the right behaviour for an anonymous submission with no address to answer. Reply-To is a header, not an identity: unlike from, it is not checked against your verified domains and senders, so it can point at any address you control, on any domain. It does have to be a well-formed address, though — every entry is validated, and a malformed one is a 422 rather than a header nobody can reply to. The reply_to stored on a registered sender is not applied automatically; only what the request carries is used.

Response and status

json
{
  "id": "019f7141-46ac-76c3-8276-042f38c68cd8",
  "status": "queued",
  "channel": "email",
  "to": "user@example.com",
  "from": "you@yourcompany.com",
  "type": "transactional",
  "created_at": "2026-07-17T18:05:31Z",
  "estimated_cost_micros": 0,
  "currency": "USD"
}
202 Accepted. The message is queued, not yet delivered.

Poll GET /email/messages/{id} for the current state, or — better — subscribe to webhooks and let the status come to you.

cURL
curl https://api.qsendyx.com/api/v1/email/messages/019f7141-46ac-76c3-8276-042f38c68cd8 \
  -H "Authorization: Bearer $QSENDYX_TOKEN"
Money is in micro-dollars: 1 USD = 1,000,000 micros, always an integer. An email costs on the order of US$ 0.0008, which whole cents would round to zero. estimated_cost_micros is 0 when the send falls inside your plan quota — it was already paid by the subscription. Above the quota it carries your plan overage rate, or your credits absorb it.