Email delivery tracking
Record whether the beta access-code email was accepted, delivered or bounced, and connect the Brevo or Resend delivery webhook.
This page lets you see whether the access-code email sent when you approve a beta request reached the requester, and connect your email provider so that status keeps updating after the send.
What is recorded
Approving a request on the Admin page (Requests tab) generates an access code and emails it. Spectrace records one row per send: the provider (Brevo or Resend), the provider's message id, the recipient address and a status. A send the provider's API refused is stored as Not sent with the error, so the table shows it without waiting for anything else.
From there the provider's delivery webhook (a request the provider sends to Spectrace each time something happens to the email) advances the status by message id. Positive states only move forward; negative states are final and keep the provider's reason.
| Status | Meaning | Brevo events | Resend events |
|---|---|---|---|
| Sent | The provider accepted the message | request | email.sent |
| Delayed | The provider is retrying | deferred, soft_bounce | email.delivery_delayed |
| Delivered | The receiving mail server accepted it | delivered | email.delivered |
| Opened | The recipient opened or clicked it (only when the provider tracks opens) | opened, unique_opened, click | email.opened, email.clicked |
| Bounced | The address rejected it or does not exist | hard_bounce, invalid_email | email.bounced |
| Blocked | The provider refused to send, for example a suppressed address | blocked | email.suppressed |
| Marked as spam | The recipient reported it | spam | email.complained |
| Not sent | The send failed | error | email.failed |
The Admin requests table shows the status in the Code email column with the time of the last event and, for failures, the provider's reason. A request approved before tracking existed shows No record. When the webhook secret for the configured provider is not set, a notice above the table says statuses stop at Sent.
Events for emails Spectrace does not track (invites, digests, password resets) are acknowledged and ignored.
Connect Brevo
Brevo does not sign webhook deliveries, so the endpoint checks a shared secret. Brevo attaches custom headers and bearer auth only to webhooks created through its API, so create the webhook with a request rather than in the Brevo dashboard.
- Set the secret
Generate a long random string (for example
openssl rand -hex 32) and set it asBREVO_WEBHOOK_SECRETon your deployment, then redeploy. While it is unset, the endpoint rejects every delivery. - Create the transactional webhook
Replace
<app-url>with yourNEXT_PUBLIC_APP_URLand<secret>with the value from the previous step. Theeventsnames here are the API's spelling; the payloads Spectrace receives use the names in the table above (hardBouncearrives ashard_bounce). Leavebatchedoff: Spectrace expects one event per delivery.curl -X POST https://api.brevo.com/v3/webhooks \ -H "api-key: $BREVO_API_KEY" \ -H "content-type: application/json" \ -d '{ "type": "transactional", "description": "Spectrace email delivery tracking", "url": "<app-url>/api/webhooks/email/brevo", "events": ["request", "delivered", "deferred", "softBounce", "hardBounce", "invalid", "blocked", "spam", "opened", "click"], "batched": false, "auth": { "type": "bearer", "token": "<secret>" } }'An
x-webhook-secretheader carrying the same value also works: pass"headers": [{ "key": "x-webhook-secret", "value": "<secret>" }]instead ofauth. - Check the first event
Approve a request. Within a minute the Code email column moves from Sent to Delivered (or to a failure state with a reason). A rejected delivery is logged on the server as
[brevo webhook] rejected: ...with the reason and never the secret.
Connect Resend
Resend signs every delivery (Svix), so the endpoint verifies the signature with the webhook's signing secret.
- Add the webhook in Resend
In the Resend dashboard, open Webhooks and add an endpoint with the URL
<app-url>/api/webhooks/email/resend. Select the email events:email.sent,email.delivered,email.delivery_delayed,email.bounced,email.suppressed,email.complainedandemail.failed, plusemail.openedandemail.clickedif you track opens. - Set the signing secret
Copy the webhook's signing secret (it starts with
whsec_) and set it asRESEND_WEBHOOK_SECRETon your deployment, then redeploy. While it is unset, the endpoint rejects every delivery.
Limits
- Only the beta access-code email is recorded. Other transactional emails are sent but not tracked.
- There is no resend action yet. A bounced code is visible, but the fix is to correct the address and approve a fresh request.
- Delivery records are kept until an account with the recipient's email address is deleted; see Data retention and deletion.