Emails

List sent emails

GET/api/v1/email

GET /email
curl -X GET 'https://www.unitpost.com/api/v1/email' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0'
Response · 200
{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "object": "email",
      "id": "id_123",
      "to": [
        "customer@example.com"
      ],
      "from": "you@yourdomain.com",
      "subject": "Welcome to Acme",
      "template_id": "template_123",
      "campaign_id": "campaign_123",
      "status": "scheduled",
      "last_event": "string",
      "scheduled_at": "2026-01-01T00:00:00.000Z",
      "sent_at": "2026-01-01T00:00:00.000Z",
      "delivered_at": "2026-01-01T00:00:00.000Z",
      "opened_at": "2026-01-01T00:00:00.000Z",
      "clicked_at": "2026-01-01T00:00:00.000Z",
      "canceled_at": "2026-01-01T00:00:00.000Z",
      "last_error": "string",
      "created_at": "2026-01-01T00:00:00.000Z"
    }
  ]
}

Retrieve a list of emails your workspace has sent or scheduled. Results are newest-first and cursor-paginated, and each row is a reference to a single email (status and lifecycle timestamps, not the rendered body). Narrow the list with the status, campaign_id, batch_id, and created_after/created_before filters. Use an email's id with Retrieve an email to read its full record, or Cancel or reschedule an email to change a scheduled send. For aggregate deliverability numbers over a window, see Email deliverability stats. Requires the emails:read capability.

Parameters8 fields
FieldTypeDescription
limitinteger · queryMax rows to return (default 20, max 100).
afterstring · queryReturn rows after this id (forward paging).
beforestring · queryReturn rows before this id (backward paging).
statusstring · queryFilter by send status.
campaign_idstring · queryOnly emails produced by this campaign's fan-out.
batch_idstring · queryOnly emails sent as part of this batch.
created_afterstring · queryOnly emails created at/after this ISO 8601 time.
created_beforestring · queryOnly emails created at/before this ISO 8601 time.
Response · 200 fields17 fields
FieldTypeDescription
objectrequiredstring—
idrequiredstring—
torequiredstring[]—
fromrequiredstring—
subjectrequiredstring—
template_idrequiredobject—
campaign_idrequiredobject—
statusrequiredenumscheduled | queued | sent | delivered | bounced | complained | canceled | failed—
last_eventrequiredstring—
scheduled_atrequiredobject—
sent_atrequiredobject—
delivered_atrequiredobject—
opened_atrequiredobject—
clicked_atrequiredobject—
canceled_atrequiredobject—
last_errorrequiredobject—
created_atrequiredstring—
200401403422

Send or schedule an email

POST/api/v1/email

POST /email
curl -X POST 'https://www.unitpost.com/api/v1/email' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "you@yourdomain.com",
    "to": "customer@example.com",
    "subject": "Welcome to Acme",
    "html": "<h1>Hello</h1>"
  }'
Response · 200
{
  "id": "id_123",
  "status": "queued",
  "scheduled_at": "2026-01-01T00:00:00.000Z"
}

Send a single transactional email — now, or at a future time by passing scheduled_at. Provide the content inline as html/text, or reference a saved template with template (create one with Create a template). Pass an Idempotency-Key header to make retries safe: the same key replays the original result instead of sending twice. The response returns the new email's id — read its delivery status back with Retrieve an email, change a scheduled send with Cancel or reschedule an email, or send many at once with Send a batch of emails. Requires the emails:send capability.

Request body16 fields
FieldTypeDescription
fromrequiredstringSender address on one of your verified domains. Accepts a bare address ("hi@acme.com") or a display name ("Acme <hi@acme.com>") — the name is what inbox clients show next to the message.
torequiredobject—
subjectstring—
ccobject—
bccobject—
reply_toobject—
in_reply_tostring—
headersobject—
tagsobject[]—
templateobjectPublished template plus variable values. Mutually exclusive with `html` and `text`.
htmlstringHTML MIME body. It is sanitized for email safety and may be supplied with `text` to create a multipart alternative. This field does not parse Markdown.
textstringPlain-text MIME body. Newline characters are preserved; Markdown and rich-text styling are not interpreted. It may be supplied with `html` as the fallback alternative. When `html` is sent without `text`, a plain-text alternative is derived from the visible HTML content; an explicit `text` value is always sent unchanged.
attachmentsobject[]—
open_trackingboolean—
click_trackingboolean—
scheduled_atstring—
Response · 200 fields3 fields
FieldTypeDescription
idrequiredstring—
statusrequiredenumqueued | scheduled—
scheduled_atrequiredstring—
200401403404409422429

Send a batch of emails

POST/api/v1/email/batch

POST /email/batch
curl -X POST 'https://www.unitpost.com/api/v1/email/batch' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0' \
  -H 'Content-Type: application/json' \
  -d '{
    "emails": [
      {
        "from": "you@yourdomain.com",
        "to": "a@example.com",
        "subject": "Hi A",
        "html": "<p>Hi A</p>"
      },
      {
        "from": "you@yourdomain.com",
        "to": "b@example.com",
        "subject": "Hi B",
        "html": "<p>Hi B</p>"
      }
    ]
  }'
Response · 200
{
  "object": "list",
  "batch_id": "batch_123",
  "status": "queued",
  "scheduled_at": "2026-01-01T00:00:00.000Z",
  "data": [
    {
      "id": "id_123"
    }
  ],
  "failed": [
    {
      "index": 0,
      "error": "string"
    }
  ]
}

Send up to 100 transactional emails in a single request. Validation is all-or-nothing: if any item is invalid the whole batch is rejected and nothing is queued, so you never end up with a partial send. Pass an Idempotency-Key header to make retries safe — the same key replays the original result instead of re-sending. The response returns a batch_id; track the batch's per-status rollup with Retrieve a batch and stop the rest of it with Cancel a batch. To send one email, use Send or schedule an email. Requires the emails:send capability.

Response · 200 fields1 field
FieldTypeDescription
idrequiredstring—
200401403409422429

Retrieve a batch

GET/api/v1/email/batches/{id}

GET /email/batches/{id}
curl -X GET 'https://www.unitpost.com/api/v1/email/batches/batch_123' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0'
Response · 200
{
  "object": "batch",
  "id": "id_123",
  "count": 1,
  "scheduled_at": "2026-01-01T00:00:00.000Z",
  "created_at": "2026-01-01T00:00:00.000Z",
  "status_counts": {},
  "cancelable": 0
}

Retrieve a batch and its live, per-status rollup (how many of its messages are queued, sent, delivered, bounced, and so on). The counts update as the batch progresses. Create a batch with Send a batch of emails, or stop its remaining messages with Cancel a batch. Requires the emails:read capability.

Parameters1 field
FieldTypeDescription
idrequiredstring · path—
Response · 200 fields7 fields
FieldTypeDescription
objectrequiredenumbatch—
idrequiredstring—
countrequiredinteger—
scheduled_atrequiredstring—
created_atrequiredstring—
status_countsrequiredobjectLive child counts keyed by status (e.g. { delivered: 98, failed: 2 }).
cancelablerequiredinteger—
200401403404

Cancel a batch

POST/api/v1/email/batches/{id}/cancel

POST /email/batches/{id}/cancel
curl -X POST 'https://www.unitpost.com/api/v1/email/batches/batch_123/cancel' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0'
Response · 200
{
  "object": "batch",
  "id": "id_123",
  "count": 1,
  "scheduled_at": "2026-01-01T00:00:00.000Z",
  "created_at": "2026-01-01T00:00:00.000Z",
  "status_counts": {},
  "cancelable": 0
}

Cancel every still-cancelable message in a batch in one call. Messages that have already been sent are left untouched — only queued or scheduled ones are stopped. Check what remains cancelable first with Retrieve a batch. Requires the emails:send capability.

Parameters1 field
FieldTypeDescription
idrequiredstring · path—
Response · 200 fields7 fields
FieldTypeDescription
objectrequiredenumbatch—
idrequiredstring—
countrequiredinteger—
scheduled_atrequiredstring—
created_atrequiredstring—
status_countsrequiredobjectLive child counts keyed by status (e.g. { delivered: 98, failed: 2 }).
cancelablerequiredinteger—
200401403404409

Retrieve an email

GET/api/v1/email/{id}

GET /email/{id}
curl -X GET 'https://www.unitpost.com/api/v1/email/email_123' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0'
Response · 200
{
  "object": "email",
  "id": "id_123",
  "to": [
    "customer@example.com"
  ],
  "from": "you@yourdomain.com",
  "subject": "Welcome to Acme",
  "template_id": "template_123",
  "campaign_id": "campaign_123",
  "status": "scheduled",
  "last_event": "string",
  "scheduled_at": "2026-01-01T00:00:00.000Z",
  "sent_at": "2026-01-01T00:00:00.000Z",
  "delivered_at": "2026-01-01T00:00:00.000Z",
  "opened_at": "2026-01-01T00:00:00.000Z",
  "clicked_at": "2026-01-01T00:00:00.000Z",
  "canceled_at": "2026-01-01T00:00:00.000Z",
  "last_error": "string",
  "created_at": "2026-01-01T00:00:00.000Z"
}

Retrieve a single email by id, including its current send status and lifecycle timestamps (created, scheduled, sent, delivered, and so on). Find an id by browsing List sent emails. Messages submitted over **SMTP** can also be retrieved by the RFC 5322 Message-ID your mail library stamped on them (URL-encode it, e.g. /email/%3Cabc%40example.com%3E; angle brackets optional) — the id in the SMTP 250 Queued as … reply works too. To change a scheduled or queued email, use Cancel or reschedule an email. Requires the emails:read capability.

Parameters1 field
FieldTypeDescription
idrequiredstring · path—
Response · 200 fields17 fields
FieldTypeDescription
objectrequiredstring—
idrequiredstring—
torequiredstring[]—
fromrequiredstring—
subjectrequiredstring—
template_idrequiredobject—
campaign_idrequiredobject—
statusrequiredenumscheduled | queued | sent | delivered | bounced | complained | canceled | failed—
last_eventrequiredstring—
scheduled_atrequiredobject—
sent_atrequiredobject—
delivered_atrequiredobject—
opened_atrequiredobject—
clicked_atrequiredobject—
canceled_atrequiredobject—
last_errorrequiredobject—
created_atrequiredstring—
200401403404

Cancel or reschedule an email

PATCH/api/v1/email/{id}

PATCH /email/{id}
curl -X PATCH 'https://www.unitpost.com/api/v1/email/email_123' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0' \
  -H 'Content-Type: application/json' \
  -d '{
    "scheduled_at": null
  }'
Response · 200
{
  "object": "email",
  "id": "id_123",
  "to": [
    "customer@example.com"
  ],
  "from": "you@yourdomain.com",
  "subject": "Welcome to Acme",
  "template_id": "template_123",
  "campaign_id": "campaign_123",
  "status": "scheduled",
  "last_event": "string",
  "scheduled_at": "2026-01-01T00:00:00.000Z",
  "sent_at": "2026-01-01T00:00:00.000Z",
  "delivered_at": "2026-01-01T00:00:00.000Z",
  "opened_at": "2026-01-01T00:00:00.000Z",
  "clicked_at": "2026-01-01T00:00:00.000Z",
  "canceled_at": "2026-01-01T00:00:00.000Z",
  "last_error": "string",
  "created_at": "2026-01-01T00:00:00.000Z"
}

Cancel a scheduled or queued email, or move it to a new send time. Only emails that haven't been handed off for delivery yet can be changed — once an email is sent this returns 409. Look up the email's current state first with Retrieve an email. Requires the emails:send capability.

Parameters1 field
FieldTypeDescription
idrequiredstring · path—
Request body2 fields
FieldTypeDescription
cancelboolean—
scheduled_atstring—
Response · 200 fields17 fields
FieldTypeDescription
objectrequiredstring—
idrequiredstring—
torequiredstring[]—
fromrequiredstring—
subjectrequiredstring—
template_idrequiredobject—
campaign_idrequiredobject—
statusrequiredenumscheduled | queued | sent | delivered | bounced | complained | canceled | failed—
last_eventrequiredstring—
scheduled_atrequiredobject—
sent_atrequiredobject—
delivered_atrequiredobject—
opened_atrequiredobject—
clicked_atrequiredobject—
canceled_atrequiredobject—
last_errorrequiredobject—
created_atrequiredstring—
200401403404409422

Email deliverability stats

GET/api/v1/email/stats

GET /email/stats
curl -X GET 'https://www.unitpost.com/api/v1/email/stats' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'User-Agent: my-app/1.0'
Response · 200
{
  "windowDays": 0,
  "clampedToRetentionDays": 0,
  "totals": {
    "sent": 0,
    "delivered": 0,
    "opened": 0,
    "clicked": 0,
    "bounced": 0,
    "complained": 0,
    "failed": 0
  },
  "rates": {
    "delivery": 0,
    "open": 0,
    "click": 0,
    "bounce": 0,
    "complaint": 0
  }
}

Retrieve aggregate deliverability and engagement metrics for your workspace over a rolling window. You get totals (sent, delivered, opened, clicked, bounced, complained, failed) alongside the rates that matter — delivery, open, click, bounce, and complaint. Open and click rates count only emails where that tracking was enabled, so turning tracking off for transactional mail won't skew them. Control the window with the days parameter (1–365, default 30). For the individual emails behind these numbers, see List sent emails. Requires the emails:read capability.

Parameters1 field
FieldTypeDescription
daysinteger · queryWindow size in days (1–365). Defaults to 30; values above 365 are rejected.
Response · 200 fields4 fields
FieldTypeDescription
windowDaysrequiredintegerThe rolling window, in days.
clampedToRetentionDaysintegerNon-null when the requested window exceeded the plan's log retention and was clamped to this many days (data past the retention horizon is purged).
totalsrequiredobject—
ratesrequiredobjectPercentages (one decimal). delivery/bounce/complaint are vs sent; open/click are vs delivered.
200401403422

Search docs and guides

Search the docs and product guides.