Email debugging has two halves: what happened to the message, and what happened when we told your webhook about it. The first used to need the Logs page in the dashboard; the second had no record at all. Both are now APIs, and the second also has a view in the dashboard.
The Logs API
GET /v1/logs returns the same stream the dashboard Logs page shows: every lifecycle event of every email your team sends, newest first. It includes the internal states that never reach a webhook, queued, sending and retrying, alongside scheduled, sent, delivered, delivery_delayed, bounced, complained, opened, clicked, unsubscribed, suppressed and failed.
Every parameter is optional and they combine:
| Parameter | Use it for |
|---|---|
type |
one type or a comma-separated list |
since, until |
an ISO 8601 time window |
recipient |
an exact To address |
domain or domain_id |
one sending domain |
tag |
name:value, matched exactly against the tags the email was sent with |
email_id |
the full history of one email |
limit, after, before |
page size (1 to 100) and cursor paging by event id |
Paging is by cursor rather than page number, so a page never shifts while new events arrive. Reading the log needs a new scope, logs:read. It is not in the default set, so add it when you create the key; existing keys keep working for everything else and get a 403 from this endpoint until you mint one with the scope.
Three queries worth keeping:
# What happened to one email, oldest step at the bottom
curl "https://smtpfa.st/api/v1/logs?email_id=em_01j9x3n8r1" \
-H "Authorization: Bearer $SMTPFAST_API_KEY"
# Everything that happened to one customer this week
curl "https://smtpfa.st/api/v1/[email protected]&since=$(date -u -d '7 days ago' +%FT%TZ)" \
-H "Authorization: Bearer $SMTPFAST_API_KEY"
# Bounces and complaints from the last day, for an alert or a nightly export
curl "https://smtpfa.st/api/v1/logs?type=bounced,complained&since=$(date -u -d '1 day ago' +%FT%TZ)&limit=100" \
-H "Authorization: Bearer $SMTPFAST_API_KEY"
Each event carries the email's from, to, subject, domain id and tags, plus a data object with the same details a webhook would have given you: bounce type and subtype, the clicked URL, the error message on a failure.
{
"object": "event",
"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" }
}
Because the log is the full history, it is also the place to reconcile after a webhook outage: pull the window your handler missed, filtered to the event types you care about, and replay them into your own system.
Webhook deliveries
Every event we POST to a webhook is now recorded with its attempts: the status code, the response time, the first 500 characters of the response body, and the error when there was one. Open a webhook in the dashboard and the new Deliveries view lists them, newest first, with a filter for pending, succeeded and failed.
A non-2xx response, a redirect or a timeout after 10 seconds counts as a failure, and failed deliveries retry on their own after 1 second, 30 seconds, 5 minutes and 30 minutes, five attempts in total. After that the delivery is marked failed and stays in the log for 30 days. Retries now live in a durable queue, so a deploy in the middle of a retry schedule no longer loses it, which used to be the case.
You can retry any entry by hand, from the Deliveries view or with the API. The retry sends the exact payload from the original delivery, once, right now, and returns the result of that attempt.
# Failed deliveries of one webhook
curl "https://smtpfa.st/api/v1/webhooks/wh_abc123/deliveries?status=failed" \
-H "Authorization: Bearer $SMTPFAST_API_KEY"
# One delivery, including the payload that was sent
curl "https://smtpfa.st/api/v1/webhooks/wh_abc123/deliveries/whd_01j9x4" \
-H "Authorization: Bearer $SMTPFAST_API_KEY"
# Send it again
curl -X POST "https://smtpfa.st/api/v1/webhooks/wh_abc123/deliveries/whd_01j9x4/retry" \
-H "Authorization: Bearer $SMTPFAST_API_KEY"
A delivery record looks like this after it has given up:
{
"object": "webhook_delivery",
"id": "whd_01j9x4",
"webhook_id": "wh_abc123",
"event": "email.bounced",
"status": "failed",
"attempts": 5,
"max_attempts": 5,
"status_code": 503,
"duration_ms": 87,
"error": "Endpoint returned 503",
"response": "upstream unavailable",
"attempt_log": [{ "at": "2026-09-03T08:00:00.000Z", "status_code": 503, "duration_ms": 91, "error": "Endpoint returned 503" }],
"next_attempt_at": null,
"delivered_at": null,
"created_at": "2026-09-03T08:00:00.000Z"
}
Listing and reading deliveries needs webhook:read; retrying needs webhook:write.
How the two fit together
The log tells you what happened to the email. The delivery log tells you what happened when we told you about it. When a customer says they never got a receipt, the sequence is: GET /v1/logs?recipient= for their address and read the last event. If it was a bounce your handler should have processed, open that webhook's deliveries around that time, find the email.bounced entry whose payload carries that email id, and read its status. Either it succeeded, and the problem is on your side of the handler, or it failed, and the status code and response excerpt tell you why.
If you use the hosted MCP server, the same log is available to your agent as list_logs with the same filters, and the task tool explain_email walks the first half for you: it reads the email's events and reports what happened and what to do next.
Getting started
- Docs: Logs API and webhook deliveries.
- Create a key with
logs:readon the API keys page, or add the scope to an existing key from its scopes editor.
Ready to get started?
Start sending transactional email today. Free to start, no credit card required.
Get Started for FreeRelated Posts
The Best Free SMTP Services for Developers in 2026
Ten free SMTP services compared for apps, CMSs and devices: free-tier limits, daily caps, ports and TLS. Every number checked on the provider's own pages.
Best Transactional Email Services for SaaS in 2026
SMTPfast, Mailtrap, Postmark, Twilio SendGrid and Amazon SES compared for SaaS products: free tiers, real prices, inbound email, and the tradeoffs each one makes.