Logs API

The dashboard Logs page shows every lifecycle event of every email you send. The Logs API returns the same stream so you can pull it into your own tooling: an alert when bounces spike, a nightly export into your warehouse, or a support view that shows what happened to one customer's mail. The log is the full lifecycle history, including the internal steps (queued, sending, retrying) that never reach a webhook, so it is the place to check what happened to a message and to reconcile after a webhook outage.

Scope

Reading the log needs the logs:read scope. It is not in the default set, so add it when you create the key (Dashboard, API Keys, Scopes). Keys you already have keep working for everything else and get a 403 from this endpoint until you mint one with the scope.

GET/v1/logs

List email events for the team, newest first. Every parameter is optional; combine them freely.

Paging is by cursor, not page number, so a page never shifts while new events arrive. The data object carries the event details you also get in webhooks: bounce type and subtype, the clicked URL, the error message on a failure, the delay reason. Received mail is not part of this log; list it with GET /v1/emails/receiving.

Parameters

ParameterTypeRequiredDescription
typestringNoOne event type or a comma-separated list: queued, scheduled, sending, retrying, sent, delivered, delivery_delayed, bounced, complained, opened, clicked, unsubscribed, suppressed, failed
sincestringNoISO 8601. Only events at or after this time
untilstringNoISO 8601. Only events at or before this time
recipientstringNoExact To address
domainstringNoSending domain name, e.g. acme.com
domain_idstringNoSending domain id, as an alternative to domain
tagstringNoname:value, matched exactly against the tags the email was sent with
email_idstringNoAll events of one email, oldest at the bottom
limitintegerNoPage size, 1 to 100, default 20
afterstringNoEvent id. Return events older than it (next page)
beforestringNoEvent id. Return events newer than it (previous page)

Response

json
{
  "object": "list",
  "has_more": true,
  "data": [
    {
      "object": "event",
      "id": "evt_01j9x3p2q7",
      "type": "bounced",
      "created_at": "2026-09-03T08:12:44.000Z",
      "email_id": "em_01j9x3n8r1",
      "from": "[email protected]",
      "to": ["[email protected]"],
      "subject": "Your September invoice",
      "domain_id": "dom_xyz789",
      "tags": [{ "name": "campaign", "value": "invoices" }],
      "data": { "bounceType": "Permanent", "bounceSubType": "General" }
    }
  ]
}

Example

bash
# newest 50 bounces and complaints from the last day
curl "https://smtpfa.st/api/v1/logs?type=bounced,complained&since=$(date -u -d '1 day ago' +%FT%TZ)&limit=50" \
  -H "Authorization: Bearer $SMTPFAST_API_KEY"

# next page: pass the last id you saw as after
curl "https://smtpfa.st/api/v1/logs?type=bounced,complained&after=evt_01j9x3p2q7" \
  -H "Authorization: Bearer $SMTPFAST_API_KEY"

Notes

  • Filters apply before paging, so has_more tells you whether more matching events exist, not whether more events exist at all.
  • recipient is an exact match on the To address, lowercased. Use the Logs page for substring search.
  • Webhooks carry a subset of these events (delivered, bounced, complained, opened, clicked and so on) in their own payload shape. Use webhooks to react and this log to look back.
  • A parameter that is present but malformed returns 400; nothing is silently ignored.
  • recipient matches up to the 5,000 most recent emails to that address (after the domain and tag filters, so combining them narrows the set); use since for older mail to a very busy address.
  • The hosted MCP server exposes the endpoint as the list_logs tool.