Emails

Send, fetch, list and cancel transactional emails (`publiq.emails`).

The emails resource covers a transactional message lifecycle: send (inline body or by template), track status, list history and cancel before dispatch.

Method reference

emails.send

emails.send(params, { idempotencyKey? }) → Promise<Email>

Accepts and queues an email for delivery. The body can be inline (html/text) or come from a template (templateId or templateKey). Returns immediately with 202 — delivery is async; track it via emails.get or webhooks.

Parameters
ParameterTypeDescription
fromRequiredstringSender email. The domain must be verified. See Domains & DNS.
toRequiredstring | string[]Recipient(s). Accepts a single email or a list (up to 50 recipients in the envelope).
ccOptionalstring | string[]Carbon copy (Cc). One email or a list.
bccOptionalstring | string[]Blind carbon copy (Bcc). One email or a list.
subjectOptionalstringSubject (max 998 chars). Required when the body is not from a template that already has a subject.
htmlOptionalstringInline HTML body.
textOptionalstringInline plain-text body (fallback and better deliverability).
templateIdOptionalstringA versioned template ID. Alternative to html/text.
templateKeyOptionalstringReadable template key (e.g. welcome-email) — a friendly alternative to templateId. See Templates.
variablesOptionalobjectInterpolation variables ({ first_name: "Ana" }{{ first_name }}). See Variables.
tagsOptionalobjectFree-form tags for search and reporting (e.g. { campaign: "q3" }).
externalIdOptionalstringYour-side correlation (e.g. order id).
idempotencyKeyOptionalstring (opção)Idempotency key (2nd argument, outside the body). If omitted, the SDK auto-generates one per call. Retries with the same key won't duplicate the email. See Errors & idempotency.

Returns: The created email — { object: "email", id, status: "queued", ... }. Keep the id to query later.

const email = await publiq.emails.send({
from: 'you@yourdomain.com',
to: ['ana@example.com', 'bob@example.com'],
cc: 'boss@example.com',
templateKey: 'welcome-email',
variables: { first_name: 'Ana', plan: 'Pro' },
tags: { campaign: 'onboarding' },
});
console.log(email.id, email.status); // "em_...", "queued"
You must provide some body: html, text or a template (templateId/templateKey). None → 400 validation_error. A suppressed recipient never receives (per-recipient filter). See Suppressions.
Best practice: pass your own idempotencyKey (e.g. order-42-receipt) when the send originates from your own event — that way a retry on your side never duplicates the email.

emails.get

emails.get(id) → Promise<Email>

Fetch an email details by id: current status, recipients (to/cc/bcc), provider, tags and event timestamps (delivered, opened, etc.).

Parameters
ParameterTypeDescription
idRequiredstringEmail ID (returned by emails.send).

Returns: The email with its status and event history. 404 if it does not exist in the organization.

const email = await publiq.emails.get('em_123');
console.log(email.status); // "delivered"

emails.list

emails.list({ status?, limit?, after? }) → Promise<EmailList>

List the organization emails, newest first, cursor-paginated. Filter by status to reconcile deliveries.

Parameters
ParameterTypeDescription
statusOptionalstringFilter by status: queued, processing, delivered, bounced, failed, canceled.
limitOptionalnumberItems per page (default 20, max 100).
afterOptionalstringCursor: id of the last item on the previous page.

Returns: List envelope { object: "list", data: Email[] }. Use the last item id as after on the next call.

const { data } = await publiq.emails.list({ status: 'delivered', limit: 50 });
// next page:
const next = await publiq.emails.list({ after: data[data.length - 1].id });
Listing is cursor-paginated: iterate by passing the last item id in after until data comes back empty. See Errors & pagination.

emails.cancel

emails.cancel(id) → Promise<Email>

Cancel an email still in the queue (queued), preventing dispatch. Useful for scheduled or mistakenly-triggered sends.

Parameters
ParameterTypeDescription
idRequiredstringID of the email to cancel.

Returns: The email with status: "canceled". Returns 409 (conflict) if it already left the queue (processing/delivered).

await publiq.emails.cancel('em_123'); // only while queued
Treat 409 as “too late”: catch the error and move on — the email was already dispatched. See Errors.

Examples show Node, Python and PHP. In Python methods are snake_case (e.g. cancel_run, from_spec) and take a dict; in PHP they are camelCase and take an associative array. Body keys are always camelCase (templateKey, firstName, scheduledAt) — API responses come back in snake_case.

Emails — Publiq Docs