Test a webhook with a sample event
/v1/webhooks/{webhook_id}/testconst result = await bird.webhooks.test("whk_01krdgeqcxet5s7t44vh8rt9mg", {
event_type: "email.delivered",
});
console.log(result.status);result = client.webhooks.test(
"whk_01krdgeqcxet5s7t44vh8rt9mg",
event_type="email.delivered",
)
print(result.status)result, err := client.Webhooks.Test(context.Background(), "whk_123", bird.WebhooksTestParams{
EventType: bird.Ptr("email.delivered"),
})
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Status)$result = $bird->webhooks->test(
'whk_01krdgeqcxet5s7t44vh8rt9mg',
(new WebhookTestRequest())->setEventType('email.delivered'),
);
echo $result->getStatus();bird webhooks test <webhook-id> --event-type email.deliveredcurl -X POST "https://us1.platform.bird.com/v1/webhooks/{webhook_id}/test" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_type": "email.delivered"
}'{
"status": "delivered",
"response_status_code": 200,
"response_body": "OK",
"response_duration_ms": 142,
"event_payload": {
"type": "amb.accepted",
"timestamp": "2026-09-25T12:00:00Z",
"data": {
"workspace_id": "ws_01krdgeqcxet5s7t44vh8rt9mg",
"message": {
"id": "amb_01krdgeqcxet5s7t44vh8rt9mg",
"conversation_id": "acv_01krdgeqcxet5s7t44vh8rt9mg",
"business_account_id": "abz_01krdgeqcxet5s7t44vh8rt9mg",
"direction": "outbound",
"status": "accepted",
"kind": "text",
"source": "operator",
"content": {
"type": "text",
"body": "Your order has shipped."
},
"locale": "en_US",
"category": "order_update",
"tags": [
{
"name": "category",
"value": "welcome"
}
],
"cost": null,
"created_at": "2026-09-25T11:59:59Z"
}
}
},
"error": "connection refused"
}
Sends a signed synthetic event and returns whether your endpoint accepted it, its HTTP status, and the round-trip latency. An unreachable endpoint returns status: failed in the response body. The endpoint has 10 seconds to respond.
The body is a minimal JSON object with the event type, signed like a real delivery. It does not mirror that event's payload. Tests work on paused endpoints and do not appear in List delivery attempts.
The operation returns 412 if the endpoint lacks a valid signing secret or, when event_type is omitted, has no subscribed event type to use.
Paramètres
webhook_idstringID of the webhook endpoint (whk_ prefix), as returned when it was created.
Corps de la requête
event_typeEvent type to simulate. Any type from the event catalog is accepted, whether or not the endpoint subscribes to it; an unknown type returns a 422. When omitted, the endpoint's first subscribed event type is used.
Contenu de la réponse
statusWhether your endpoint accepted the test event. delivered means it returned a 2xx status; failed means it returned a non-2xx status or could not be reached (see error for the latter).
Possible values: delivered, failed
response_status_codeHTTP status returned by your endpoint. Null when no response was received (timeout, connection error, DNS failure).
response_bodyResponse body returned by your endpoint, truncated to the first 1024 bytes. Omitted when your endpoint returned no body or could not be reached.
response_duration_msRound-trip delivery latency in milliseconds.
event_payloadThe full event body delivered to your endpoint. Test sends use a minimal synthetic body rather than a full event payload, so this field is omitted.
Afficher les attributs enfants
An outbound message was accepted for processing after confirming billing coverage. This does not confirm receipt by Apple.
event_payload.typeAlways amb.accepted for this event.
Possible values: amb.accepted
event_payload.timestampWhen this lifecycle event occurred, independent of webhook delivery time.
event_payload.dataThe workspace and message snapshot at the time of the lifecycle event.
A customer conversation closed. Closing a conversation is not a message.
event_payload.typeAlways amb.conversation_closed for this event.
Possible values: amb.conversation_closed
event_payload.timestampWhen this lifecycle event occurred, independent of webhook delivery time.
event_payload.dataConversation identity and routing context when a lifecycle event occurred.
An existing customer conversation reopened after it had closed.
event_payload.typeAlways amb.conversation_reopened for this event.
Possible values: amb.conversation_reopened
event_payload.timestampWhen this lifecycle event occurred, independent of webhook delivery time.
event_payload.dataConversation identity and routing context when a lifecycle event occurred.
A customer conversation opened for the first time.
event_payload.typeAlways amb.conversation_started for this event.
Possible values: amb.conversation_started
event_payload.timestampWhen this lifecycle event occurred, independent of webhook delivery time.
event_payload.dataConversation identity and routing context when a lifecycle event occurred.
Bird received an ordinary customer message from Apple. Invitation responses are excluded.
event_payload.typeAlways amb.received for this event.
Possible values: amb.received
event_payload.timestampWhen this lifecycle event occurred, independent of webhook delivery time.
event_payload.dataThe workspace and message snapshot at the time of the lifecycle event.
Bird refused an outbound message before acceptance. This message has no accepted event.
event_payload.typeAlways amb.rejected for this event.
Possible values: amb.rejected
event_payload.timestampWhen this lifecycle event occurred, independent of webhook delivery time.
event_payload.dataThe workspace and message snapshot at the time of the lifecycle event.
An accepted outbound message could not be handed to Apple. The message snapshot carries the failure detail.
event_payload.typeAlways amb.send_failed for this event.
Possible values: amb.send_failed
event_payload.timestampWhen this lifecycle event occurred, independent of webhook delivery time.
event_payload.dataThe workspace and message snapshot at the time of the lifecycle event.
Apple accepted an outbound message from Bird. This does not establish delivery to the customer or a read receipt.
event_payload.typeAlways amb.sent for this event.
Possible values: amb.sent
event_payload.timestampWhen this lifecycle event occurred, independent of webhook delivery time.
event_payload.dataThe workspace and message snapshot at the time of the lifecycle event.
An address was added to the workspace's Apple Messages for Business suppression ledger.
event_payload.typeAlways amb_suppression.created for this event.
Possible values: amb_suppression.created
event_payload.timestampWhen the suppression episode took effect.
event_payload.dataPayload of the amb_suppression.created event.
A sending domain failed DNS verification.
event_payload.typeEvent type.
Possible values: domain.failed
event_payload.timestampWhen the event occurred.
event_payload.dataPayload of the domain.failed event.
A sending domain completed DNS verification successfully.
event_payload.typeEvent type.
Possible values: domain.verified
event_payload.timestampWhen the event occurred.
event_payload.dataPayload of the domain.verified event.
The API accepted the email send and is preparing it for delivery. Fires once per requested recipient.
event_payload.typeEvent type.
Possible values: email.accepted
event_payload.timestampTime the API accepted the send.
event_payload.dataPayload of the email.accepted event.
An outbound email permanently failed at the recipient's mail server. Fires once per recipient.
event_payload.typeEvent type.
Possible values: email.bounced
event_payload.timestampTime the bounce was recorded.
event_payload.dataPayload of the email.bounced event.
A scheduled send was canceled before it fired. Fires once for each message regardless of its recipient count.
event_payload.typeEvent type.
Possible values: email.canceled
event_payload.timestampTime the scheduled send was canceled.
event_payload.dataPayload of the email.canceled event.
The recipient clicked a tracked link in the email. May fire more than once per recipient.
event_payload.typeEvent type.
Possible values: email.clicked
event_payload.timestampTime the click was recorded.
event_payload.dataPayload of the email.clicked event.
The recipient marked the email as spam through their mailbox provider's feedback loop. Fires once per recipient.
event_payload.typeEvent type.
Possible values: email.complained
event_payload.timestampTime the complaint was recorded.
event_payload.dataPayload of the email.complained event.
The recipient's mail server temporarily refused the email. Delivery remains pending and is retried. May fire more than once per recipient.
event_payload.typeEvent type.
Possible values: email.deferred
event_payload.timestampTime the deferral was recorded.
event_payload.dataPayload of the email.deferred event.
An outbound email reached the recipient's mail server and was accepted.
event_payload.typeEvent type.
Possible values: email.delivered
event_payload.timestampTime the recipient's mail server accepted the message.
event_payload.dataPayload of the email.delivered event.
Recipient unsubscribed via the RFC 8058 one-click List-Unsubscribe mechanism. Fires once per recipient.
event_payload.typeEvent type.
Possible values: email.list_unsubscribed
event_payload.timestampTime the unsubscribe was recorded.
event_payload.dataPayload of the email.list_unsubscribed event.
The recipient opened the email (the tracking pixel was loaded). May fire more than once per recipient.
event_payload.typeEvent type.
Possible values: email.opened
event_payload.timestampTime the open was recorded.
A bounce notification arrived after the message had already been accepted for delivery. Fires once per recipient.
event_payload.typeEvent type.
Possible values: email.out_of_band_bounce
event_payload.timestampTime the bounce notification was recorded.
event_payload.dataPayload of the email.out_of_band_bounce event.
The API prepared the message for delivery to the recipient's mail server. Fires once per recipient.
event_payload.typeEvent type.
Possible values: email.processed
event_payload.timestampTime the message was prepared for delivery.
event_payload.dataPayload of the email.processed event.
The API received and parsed an inbound email. The payload carries the message's identifiers, sender and recipients, subject, threading reference, and authentication results, which is enough to route and triage without a fetch. Fetch content separately. Get the parsed body with GET /v1/email/inbound-messages/{id}/body. Get the original MIME with GET /v1/email/inbound-messages/{id}/raw. Get attachment bytes with GET /v1/email/inbound-messages/{id}/attachments/{attachment_id}.
event_payload.typeEvent type.
Possible values: email.received
event_payload.timestampWhen the API received the message.
event_payload.dataPayload of the email.received event.
The API rejected the email before delivery because of suppression, transmission failure, content, or policy. Fires once per recipient.
event_payload.typeEvent type.
Possible values: email.rejected
event_payload.timestampTime the rejection was recorded.
event_payload.dataPayload of the email.rejected event.
The API accepted an email scheduled for a future time. Fires once per message when the schedule is created.
event_payload.typeEvent type.
Possible values: email.scheduled
event_payload.timestampTime the send was scheduled.
event_payload.dataPayload of the email.scheduled event.
Recipient unsubscribed by clicking a tracked unsubscribe link in the email. Fires once per recipient.
event_payload.typeEvent type.
Possible values: email.unsubscribed
event_payload.timestampTime the unsubscribe was recorded.
event_payload.dataPayload of the email.unsubscribed event.
Every recipient of a mailbox message reached a delivered state. This event fires once per message. The same send also emits one email.delivered event for each recipient. Choose one event family for each automation and deduplicate mailbox events by message_id.
event_payload.typeEvent type.
Possible values: email_mailbox.message_delivered
event_payload.timestampWhen the event occurred.
event_payload.dataPayload of the email_mailbox.message_delivered event.
A mailbox message reached a terminal delivery failure. This event fires once per message. The same send also emits per-recipient email.* events. Choose one event family for each automation and deduplicate mailbox events by message_id.
event_payload.typeEvent type.
Possible values: email_mailbox.message_failed
event_payload.timestampWhen the event occurred.
event_payload.dataPayload of the email_mailbox.message_failed event.
An email arrived in a mailbox. The same message also emits an email.received event. The two events can arrive in either order. Choose one event family for each automation and deduplicate mailbox events by message_id.
event_payload.typeEvent type.
Possible values: email_mailbox.message_received
event_payload.timestampWhen the event occurred.
event_payload.dataIdentifiers, threading details, authentication results, and extracted text for a received mailbox message. The thread-message endpoints provide the original source during its 30-day retention window.
A mailbox message was handed off for delivery. This event fires once per message. The same send also emits per-recipient email.* events. Choose one event family for each automation and deduplicate mailbox events by message_id.
event_payload.typeEvent type.
Possible values: email_mailbox.message_sent
event_payload.timestampWhen the event occurred.
event_payload.dataPayload of the email_mailbox.message_sent event.
This mailbox-suspension event is reserved and is not currently emitted.
event_payload.typeEvent type.
Possible values: email_mailbox.suspended
event_payload.timestampWhen the event occurred.
event_payload.dataPayload of the email_mailbox.suspended event.
A new thread was created in a mailbox, from either direction.
event_payload.typeEvent type.
Possible values: email_mailbox.thread_created
event_payload.timestampWhen the event occurred.
event_payload.dataPayload of the email_mailbox.thread_created event.
An email address was added to the workspace's suppression list (manually, via complaint, or via hard bounce).
event_payload.typeEvent type.
Possible values: email_suppression.created
event_payload.timestampWhen the event occurred.
event_payload.dataPayload of the email_suppression.created event.
A stated preference was deleted, superseding it in the ledger without erasing its history.
event_payload.typeAlways preference.deleted for this event.
Possible values: preference.deleted
event_payload.timestampWhen the delete took effect (effective_at), not when it was recorded.
event_payload.dataPayload of the preference.deleted event.
A stated preference was granted (a person consented, or a customer wrote a grant) and became the key's live statement.
event_payload.typeAlways preference.granted for this event.
Possible values: preference.granted
event_payload.timestampWhen the statement took effect (effective_at), not when it was recorded.
event_payload.dataPayload of the preference.granted event.
A stated preference was revoked (a person opted out, or a customer wrote a revoke) and became the key's live statement.
event_payload.typeAlways preference.revoked for this event.
Possible values: preference.revoked
event_payload.timestampWhen the statement took effect (effective_at), not when it was recorded.
event_payload.dataPayload of the preference.revoked event.
The API accepted the SMS send request and queued it for processing.
event_payload.typeEvent type.
Possible values: sms.accepted
event_payload.timestampTime the API accepted the request.
The carrier confirmed delivery of the message to the recipient handset.
event_payload.typeEvent type.
Possible values: sms.delivered
event_payload.timestampTime the carrier confirmed delivery.
event_payload.dataPayload of the sms.delivered event.
The message's validity period elapsed before it could be delivered.
event_payload.typeEvent type.
Possible values: sms.expired
event_payload.timestampTime the message expired.
Message delivery failed permanently.
event_payload.typeEvent type.
Possible values: sms.failed
event_payload.timestampTime the failure was recorded.
A message was received on one of your numbers.
event_payload.typeAlways sms.received for this event.
Possible values: sms.received
event_payload.timestampTime the sender sent the message.
The API rejected the message before sending it to the carrier because of an invalid destination, suppression, or content or policy restriction.
event_payload.typeEvent type.
Possible values: sms.rejected
event_payload.timestampTime the rejection was recorded.
The API handed the message to the carrier for delivery.
event_payload.typeEvent type.
Possible values: sms.sent
event_payload.timestampTime the message was handed to the carrier.
The carrier reported a non-permanent failure to deliver the message.
event_payload.typeEvent type.
Possible values: sms.undelivered
event_payload.timestampTime the non-delivery was recorded.
event_payload.dataPayload of the sms.undelivered event.
A destination was added to the workspace's SMS suppression ledger: a subscriber's STOP, a carrier opt-out, or a manual add.
event_payload.typeAlways sms_suppression.created for this event.
Possible values: sms_suppression.created
event_payload.timestampWhen the episode's opening statement took effect (effective_at).
event_payload.dataPayload of the sms_suppression.created event.
The channel confirmed delivery of a one-time passcode to the recipient.
event_payload.typeEvent type.
Possible values: verify.attempt.delivered
event_payload.timestampTime delivery was confirmed.
event_payload.dataPayload of the verify.attempt.delivered event.
A one-time passcode was dispatched to the recipient on a channel.
event_payload.typeEvent type.
Possible values: verify.attempt.sent
event_payload.timestampTime the passcode was dispatched.
event_payload.dataPayload of the verify.attempt.sent event.
A one-time passcode failed to deliver to the recipient.
event_payload.typeEvent type.
Possible values: verify.attempt.undelivered
event_payload.timestampTime the failure was recorded.
event_payload.dataPayload of the verify.attempt.undelivered event.
A verification session was created and its first one-time passcode is being sent.
event_payload.typeEvent type.
Possible values: verify.verification.created
event_payload.timestampTime the verification session was created.
event_payload.dataPayload of the verify.verification.created event.
The verification ended without the recipient receiving a passcode: every planned channel reported that its send would not arrive.
event_payload.typeAlways verify.verification.failed for this event.
Possible values: verify.verification.failed
event_payload.timestampTime the verification was resolved.
event_payload.dataPayload of the verify.verification.failed event.
The verification was successfully resolved: the recipient confirmed the correct code.
event_payload.typeEvent type.
Possible values: verify.verification.verified
event_payload.timestampTime the verification was verified.
event_payload.dataPayload of the verify.verification.verified event.
The called party answered and media began flowing.
event_payload.typeEvent type.
Possible values: voice_call.answered
event_payload.timestampTime the call was answered.
event_payload.dataPayload of the voice_call.answered event.
The call ended after either party hung up or call setup failed.
event_payload.typeEvent type.
Possible values: voice_call.ended
event_payload.timestampTime either party hung up or call setup failed.
event_payload.dataPayload of the voice_call.ended event.
Call routing began.
event_payload.typeEvent type.
Possible values: voice_call.initiated
event_payload.timestampTime the call was initiated.
event_payload.dataPayload of the voice_call.initiated event.
The API accepted and charged the send request.
event_payload.typeEvent type.
Possible values: whatsapp.accepted
event_payload.timestampTime the API accepted and charged the send request.
event_payload.dataPayload of the whatsapp.accepted event.
The message was delivered to the recipient's device.
event_payload.typeEvent type.
Possible values: whatsapp.delivered
event_payload.timestampTime the message was delivered to the recipient's device.
event_payload.dataPayload of the whatsapp.delivered event.
Message delivery failed permanently.
event_payload.typeEvent type.
Possible values: whatsapp.failed
event_payload.timestampTime the failure was recorded.
event_payload.dataPayload of the whatsapp.failed event.
Someone asked to join a group that requires approval.
event_payload.typeAlways whatsapp.group.join_request_created for this event.
Possible values: whatsapp.group.join_request_created
event_payload.timestampWhen the person asked to join.
event_payload.dataPayload shared by the whatsapp.group.join_request_created and whatsapp.group.join_request_revoked events. Everything about the person who asked is nested under join_request; the sibling identifiers name the business side.
Someone withdrew their request to join a group before it was decided.
event_payload.typeAlways whatsapp.group.join_request_revoked for this event.
Possible values: whatsapp.group.join_request_revoked
event_payload.timestampWhen the person withdrew their request.
event_payload.dataPayload shared by the whatsapp.group.join_request_created and whatsapp.group.join_request_revoked events. Everything about the person who asked is nested under join_request; the sibling identifiers name the business side.
A contact placed, changed or took back a reaction on a message.
event_payload.typeAlways whatsapp.reacted for this event.
Possible values: whatsapp.reacted
event_payload.timestampWhen the contact reacted, as reported by WhatsApp. Meta reports this to the second, so a contact who changes or withdraws a reaction quickly can produce two events sharing one timestamp. Sorting reactions on one message by this field cannot order those, and neither can delivery order, which retries make unreliable. Act on the reaction each event carries, as the change it describes; do not reconstruct the sequence from the events or treat the last one to arrive as the message's standing reaction. Read the message back for the reactions that stand: getWhatsAppMessage (GET /v1/whatsapp/messages/{message_id}) returns one entry per sender in reactions, and listWhatsAppMessageReactionEvents has every change.
event_payload.dataPayload of the whatsapp.reacted event. Names the message the contact reacted to, not the reaction, because a reaction is an annotation on a message rather than a message of its own.
The recipient read the message.
event_payload.typeEvent type.
Possible values: whatsapp.read
event_payload.timestampTime the recipient read the message.
event_payload.dataPayload of the whatsapp.read event.
A contact sent the business a WhatsApp message. Not raised while the Meta Business Agent holds the conversation; the message is still stored and returned by the message reads.
event_payload.typeEvent type.
Possible values: whatsapp.received
event_payload.timestampTime the contact sent the message, as reported by WhatsApp.
event_payload.dataPayload of the whatsapp.received event. Carries the message's content so a subscriber can act on it without reading the message back.
The API rejected the message before sending it to WhatsApp because the recipient is on the workspace suppression list, the wallet has insufficient balance, or the destination is unpriced. The message is not sent or charged.
event_payload.typeEvent type.
Possible values: whatsapp.rejected
event_payload.timestampTime the rejection was recorded.
event_payload.dataPayload of the whatsapp.rejected event.
The message was handed to Meta for delivery. Raised for a message your workspace sent through Bird, for one sent from the WhatsApp Business app on a number shared with it (origin: business_app_echo), and for one the Meta Business Agent sent on your number (origin: business_agent_echo).
event_payload.typeEvent type.
Possible values: whatsapp.sent
event_payload.timestampTime the message was handed to Meta for delivery.
event_payload.dataPayload of the whatsapp.sent event.
An address was added to the workspace's WhatsApp suppression ledger.
event_payload.typeAlways whatsapp_suppression.created for this event.
Possible values: whatsapp_suppression.created
event_payload.timestampWhen the episode's opening statement took effect (effective_at).
event_payload.dataPayload of the whatsapp_suppression.created event.
errorA short explanation of why the event could not be delivered. Present only when your endpoint could not be reached.
Ressources associées
Poursuivez avec la documentation, les guides et les exemples sur ce sujet.