Webhook event catalog
Reference every webhook event Samva delivers, its type string, when it fires, and the payload fields your handler receives.
Samva delivers webhook events to the endpoints you register. This page catalogs the events the platform emits, the type string each carries, when it fires, and the payload fields it delivers. To register an endpoint and verify signatures, see Receive webhooks.
Envelope
Every delivery is a POST with a JSON body in a fixed envelope. type is the event type,
timestamp is when it occurred, and data carries event-specific fields including messageId.
{
"type": "message.delivered",
"timestamp": "2026-01-15T09:42:11.204Z",
"data": {
"messageId": "msg_01j8k3m5n7p9q2r4s6tv",
"channel": "email",
"status": "delivered",
"providerMessageId": "0100018f2a...-000000"
}
}Each request also carries the Standard Webhooks webhook-id, webhook-timestamp, and
webhook-signature headers. Verify them against the exact raw body with a five-minute timestamp
tolerance before you trust the body, as described in Receive webhooks.
Retries retain the same webhook-id but receive a fresh timestamp and signature. Delivery is
at least once and unordered.
The data object is populated on a best-effort basis: a field is present only when the underlying
provider event supplied it. Treat every field inside data as optional and code defensively.
Message events
Message events track a single message through its send and delivery lifecycle. Every message
event carries the message's channel and a status string inside data, plus email provider
fields when available.
message.sent
Fires when a provider accepts the message for delivery. This is the handoff to the upstream mail or messaging provider, not confirmation that the recipient received it.
| Field | Type | Notes |
|---|---|---|
channel | string | email. |
status | string | sent. |
providerMessageId | string | The upstream provider's id for the message, when known. |
metadata | object | Metadata you supplied on the original send, when set. |
cost | number | Provider-reported cost, when the provider reports it. |
{
"type": "message.sent",
"timestamp": "2026-01-15T09:42:10.031Z",
"data": {
"messageId": "msg_01j8k3m5n7p9q2r4s6tv",
"channel": "email",
"status": "sent",
"providerMessageId": "0100018f2a...-000000",
"toEmails": ["ada@example.com"]
}
}message.delivered
Fires when the recipient's mail server accepts the email.
| Field | Type | Notes |
|---|---|---|
channel | string | email. |
status | string | delivered. |
providerMessageId | string | The upstream provider's id, when known. |
metadata | object | Metadata you supplied on the original send, when set. |
{
"type": "message.delivered",
"timestamp": "2026-01-15T09:42:14.882Z",
"data": {
"messageId": "msg_01j8k3m5n7p9q2r4s6tv",
"channel": "email",
"status": "delivered",
"providerMessageId": "0100018f2a...-000000",
"subject": "Welcome to Samva",
"toEmails": ["ada@example.com"]
}
}message.failed
Fires when a message cannot be delivered. The failure may originate from the provider, from a
suppressed recipient, or from an error while processing the send. failureReason is a
human-readable explanation; errorCode is a machine-readable code when the source provides one.
| Field | Type | Notes |
|---|---|---|
channel | string | email. |
status | string | failed. |
failureReason | string | Human-readable reason for the failure. |
errorCode | string | Machine-readable error code, when the provider supplies one. |
errorMessage | string | Provider error detail, when supplied. |
metadata | object | Metadata you supplied on the original send, when set. |
{
"type": "message.failed",
"timestamp": "2026-01-15T09:42:12.507Z",
"data": {
"messageId": "msg_01j8k3m5n7p9q2r4s6tv",
"channel": "email",
"status": "failed",
"failureReason": "Permanent",
"errorCode": "General"
}
}message.bounced
Fires for email when the recipient's mail server rejects the message after acceptance, or when a
recipient marks it as spam. failureReason carries the bounce or complaint type.
| Field | Type | Notes |
|---|---|---|
channel | string | email. |
status | string | bounced or complained. |
providerMessageId | string | The upstream provider's id, when known. |
failureReason | string | Bounce type or complaint type. |
errorCode | string | Bounce sub-type, when supplied. |
subject | string | The message subject, when available. |
toEmails | string[] | The recipient addresses on the message. |
{
"type": "message.bounced",
"timestamp": "2026-01-15T09:43:01.117Z",
"data": {
"messageId": "msg_01j8k3m5n7p9q2r4s6tv",
"channel": "email",
"status": "bounced",
"providerMessageId": "0100018f2a...-000000",
"failureReason": "Permanent",
"errorCode": "General",
"subject": "Welcome to Samva",
"toEmails": ["ada@example.com"]
}
}message.received
Fires when Samva receives an inbound email and routing matches one of your endpoints. The
direction field is inbound.
| Field | Type | Notes |
|---|---|---|
channel | string | email. |
direction | string | inbound. |
from | string | The sender's email address. |
to | string | The email address that received the message. |
conversationId | string | The conversation the inbound message was threaded into. |
subject | string | Email subject. |
hasAttachments | boolean | Whether an inbound email carried attachments. |
isAutoReply | boolean | Whether an inbound email was detected as an auto-reply. |
{
"type": "message.received",
"timestamp": "2026-01-15T10:05:33.900Z",
"data": {
"messageId": "msg_01j8k4n6p8q2r4s6t9vw",
"channel": "email",
"direction": "inbound",
"from": "ada@example.com",
"to": "support@your-domain.com",
"subject": "Re: Welcome to Samva",
"conversationId": "conv_01j8k5p7q9r2s4t6v8wx",
"hasAttachments": false,
"isAutoReply": false
}
}Subscribing to events
You subscribe an endpoint with eventTypes when you create or update it. Pass the type strings
above, for example ["message.delivered", "message.failed"], and select the applicable
channels. Subscribe only to events your application acts on; you can register multiple endpoints
to route different events to different services. See Receive webhooks
for the full registration and verification flow.