Test a webhook endpoint
Fire a signed sample event at an endpoint through the real delivery pipeline.
Fires a sample payload at the endpoint through the real delivery pipeline: the same Wemail-Signature-Ed25519 platform signature as organic deliveries, the endpoint’s receiver-side auth (hmac/bearer/basic/custom headers/OAuth 2.0/mTLS), the worker’s 30-second timeout and full SSRF protections. The payload is the native delivery shape with an explicit "test": true marker so your receiver can discriminate test traffic — verify your signature code against it before going live. Note that on organic events data.test: true alone means the message was simulated either by one of your test keys or because wemail support routed the account or API key to the Sandbox — the latter additionally carry data.routed: true, which is how you tell them apart.
POST /v3/webhooks/{id}/test
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | Optional | Event type to simulate: queued, sent, delivered, opened, clicked, bounced, complained, unsubscribed, delayed, rejected or failed. Default delivered. You can omit the body entirely. |
What your endpoint receives
{
"event": "delivered",
"message_id": "msg_test_a1b2c3d4e5f6",
"recipient": "test@example.com",
"timestamp": "2026-08-30T09:15:00.000Z",
"data": {
"from": "sender@yourdomain.com",
"subject": "Test email subject",
"tags": [
"transactional",
"test"
]
},
"test": true
}The attempt is recorded in the endpoint’s delivery history (Console → Webhooks → Activity) as a test row — it never enters the retry schedule and is not resendable. The response reports the outcome per fired event: your endpoint’s HTTP status (null when the request never completed — timeout or network failure), the round-trip latency_ms, and success (a 2xx answer within the timeout).
Responses
| Status | Description |
|---|---|
200 | OK. { deliveries: [{ event, status, latency_ms, success }] } — one entry per fired event. |
400 | Validation error — an unknown event type, an endpoint URL that fails SSRF checks, or receiver auth that could not be resolved (e.g. an OAuth token fetch failure). |
401 | Missing or invalid API key. |
404 | No webhook with this id on your account. |
429 | Rate limit exceeded (10 calls/minute). |
Code examples
# Fire a signed sample "delivered" event at the endpoint
curl -X POST https://api.wemail.io/v3/webhooks/9b2f6c1e-4a8d-4f3b-9c7e-2d1a5b8e0f4c/test \
-H "Authorization: Bearer afn_live_…" \
-H "Content-Type: application/json" \
-d '{ "event": "delivered" }'// Sends a signed sample payload ("test": true) through the real
// pipeline — Ed25519 signature, receiver auth, 30 s timeout.
const { deliveries } = await wemail.webhooks.test(
"9b2f6c1e-4a8d-4f3b-9c7e-2d1a5b8e0f4c",
{ event: "bounced" },
);
console.log(deliveries[0].status, deliveries[0].latency_ms, deliveries[0].success);result = wemail.webhooks.test("9b2f6c1e-4a8d-4f3b-9c7e-2d1a5b8e0f4c", event="bounced")
d = result["deliveries"][0]
print(d["status"], d["latency_ms"], d["success"])$result = $wemail->webhooks->test('9b2f6c1e-4a8d-4f3b-9c7e-2d1a5b8e0f4c', [
'event' => 'bounced',
]);result = wemail.webhooks.test("9b2f6c1e-4a8d-4f3b-9c7e-2d1a5b8e0f4c", event: "bounced")result, _ := client.Webhooks.Test(ctx, "9b2f6c1e-4a8d-4f3b-9c7e-2d1a5b8e0f4c",
&wemail.TestWebhookParams{Event: "bounced"})
fmt.Println(result.Deliveries[0].Success)JSONObject result = wemail.webhooks().test(
"9b2f6c1e-4a8d-4f3b-9c7e-2d1a5b8e0f4c",
TestWebhookParams.builder().event("bounced").build());var result = await wemail.Webhooks.TestAsync(
"9b2f6c1e-4a8d-4f3b-9c7e-2d1a5b8e0f4c",
new TestWebhookParams { Event = "bounced" });{
"deliveries": [
{
"event": "delivered",
"status": 200,
"latency_ms": 184,
"success": true
}
]
}