AbuseZero

Webhook deliveries

Read every webhook delivery with its request body and attempts, and send a delivery again, with the AbuseZero REST API.

A webhook delivery is one event sent to one endpoint, with every attempt AbuseZero made. The delivery log keeps deliveries for 30 days, with the exact request body and each attempt's status code, timing and reply.

Examples on this page use a server client:

import { AbuseZero } from "abusezero/server";

const abusezero = new AbuseZero({ key: process.env.ABUSEZERO_SECRET_KEY!, outage: "throw" });

The webhook delivery object

{
  "object": "webhook_delivery",
  "id": "whd_1f6b3d84-7a2c-4e95-8b10-6d4e2a9c7f35",
  "endpoint": "whe_7d2e9a40-3c1b-4f65-8e27-b9a0c4d61f53",
  "event": { "id": "evt_9b3e7c21-4d6a-4f58-a1e2-7c0d5b8f3a64", "type": "evaluation.completed" },
  "kind": "event",
  "status": "pending",
  "attempts": 2,
  "last_status_code": 503,
  "last_error": null,
  "next_attempt_at": "2026-10-29T14:07:47.000Z",
  "created_at": "2026-10-29T14:02:47.000Z",
  "completed_at": null
}
FieldTypeDescription
object"webhook_delivery"The object type.
idstringThe delivery ID, starting with whd_.
endpointstringThe endpoint ID, starting with whe_.
eventobjectThe event's id (evt_…) and type.
kindevent, test or resendevent for a delivery of a new event, test for a test event, resend for a delivery sent again.
statusstringSee Delivery statuses.
attemptsintegerHow many attempts were made.
last_status_codeinteger or nullThe HTTP status of the last reply, or null when there was none.
last_errorstring or nullWhy the last attempt got no reply, or why the delivery wasn't sent. See Delivery errors.
next_attempt_atstring or nullWhen the next attempt is due. null once the delivery is finished.
created_atstringWhen the delivery was created.
completed_atstring or nullWhen the delivery succeeded, failed or was marked not sent.

GET /v1/webhook-deliveries/{id} adds two fields:

FieldTypeDescription
payloadobjectThe exact request body: the event object.
attempt_logarrayEvery attempt, oldest first. See below.
attempt_log fieldTypeDescription
attemptintegerThe attempt number, from 1.
started_atstringWhen the attempt started.
duration_msintegerHow long the attempt took, in milliseconds.
status_codeinteger or nullThe HTTP status of the reply.
errorstring or nullWhy there was no reply. See Delivery errors.
countedbooleanWhether the attempt counted as a delivery. See What counts as a delivery.
responsestring or nullThe first 1 KB of your reply's body.

Delivery statuses

statusDashboardMeaning
pendingSendingWaiting for its next attempt, or being sent.
heldWaiting for creditsThe workspace has no included deliveries or credits left. The delivery waits up to 12 hours for them.
succeededDeliveredThe endpoint replied 2xx.
failedFailedEvery attempt failed.
not_sentNot sentThe delivery was never sent: the endpoint was paused, or no included deliveries or credits arrived within 12 hours. last_error says which.

New statuses can be added within v1.

Delivery errors

errorDashboardMeaningCounted
timeoutTimed out after 10 secondsThe endpoint didn't reply within 10 seconds.Yes
connection_failedCouldn't connectThe connection was refused, reset or never accepted.Yes
tls_failedCertificate problemThe endpoint's certificate isn't valid for its host name, or can't be trusted.Yes
domain_not_foundDomain doesn't existThe host name doesn't exist.Yes
address_blockedAddress isn't publicThe host name points to an address that isn't on the public internet. AbuseZero sends only to public addresses.No
lookup_failedAddress lookup failed on our sideAbuseZero couldn't look up the host name. An event delivery is retried.No
internal_errorFailed on our sideThe attempt failed inside AbuseZero. An event delivery is retried.No
endpoint_pausedNot sent: endpoint pausedThe endpoint was paused before the delivery was sent.No
no_creditsNot sent: no included deliveries or credits leftNo included deliveries or credits arrived within 12 hours.No

New errors can be added within v1. Treat an error you don't recognize as a failed attempt.

What counts as a delivery

Each workspace's plan includes deliveries every calendar month (UTC). Beyond them, deliveries use credits. See your plan on the pricing page and your usage in Workspace settings → Billing & Subscriptions.

CountsDoesn't count
Any HTTP reply from your endpoint, including 3xx, 4xx and 5xxTest events
A connection your endpoint refuses, resets or never acceptsAttempts that fail on AbuseZero's side (lookup_failed, internal_error)
A timeout after 10 secondsAddresses that aren't public (address_blocked)
A certificate problem, or a host name that doesn't existDeliveries held or not sent
Every retry and every resend

Each attempt's counted field says how it was counted. Only counted failures move an endpoint toward being paused.

List webhook deliveries

Returns deliveries from the last 30 days, most recent first.

MethodPathScopeIdempotency-Key
GET/v1/webhook-deliverieswebhooks:readNot used

Also available as abusezero webhook-deliveries list in the AbuseZero CLI, abusezero_list_webhook_deliveries on the AbuseZero MCP server and call() in the AbuseZero Node.js SDK.

Query parameters

ParameterTypeRequiredLimitsDescription
endpoint_idstringNoA whe_ IDOnly deliveries to this endpoint.
limitintegerNo1 to 100, default 50How many deliveries to return.
cursorstringNoThe next_cursor from the previous page, unchanged.

Example

const page = await abusezero.call("/v1/webhook-deliveries", {
  input: { endpoint_id: "whe_7d2e9a40-3c1b-4f65-8e27-b9a0c4d61f53", limit: 20 },
});

Response

Returns 200 with a list of webhook delivery objects, without payload and attempt_log.

{
  "object": "list",
  "data": [
    {
      "object": "webhook_delivery",
      "id": "whd_1f6b3d84-7a2c-4e95-8b10-6d4e2a9c7f35",
      "endpoint": "whe_7d2e9a40-3c1b-4f65-8e27-b9a0c4d61f53",
      "event": { "id": "evt_9b3e7c21-4d6a-4f58-a1e2-7c0d5b8f3a64", "type": "evaluation.completed" },
      "kind": "event",
      "status": "succeeded",
      "attempts": 3,
      "last_status_code": 200,
      "last_error": null,
      "next_attempt_at": null,
      "created_at": "2026-10-29T14:02:47.000Z",
      "completed_at": "2026-10-29T14:07:48.000Z"
    }
  ],
  "next_cursor": null
}

Retrieve a webhook delivery

Returns a delivery with its exact request body and every attempt.

MethodPathScopeIdempotency-Key
GET/v1/webhook-deliveries/{id}webhooks:readNot used

Also available as abusezero webhook-deliveries get in the AbuseZero CLI, abusezero_get_webhook_delivery on the AbuseZero MCP server and call() in the AbuseZero Node.js SDK.

Path parameters

ParameterTypeDescription
idstringThe delivery ID, starting with whd_.

Example

const delivery = await abusezero.call("/v1/webhook-deliveries/whd_1f6b3d84-7a2c-4e95-8b10-6d4e2a9c7f35");

Response

Returns 200.

{
  "object": "webhook_delivery",
  "id": "whd_1f6b3d84-7a2c-4e95-8b10-6d4e2a9c7f35",
  "endpoint": "whe_7d2e9a40-3c1b-4f65-8e27-b9a0c4d61f53",
  "event": { "id": "evt_9b3e7c21-4d6a-4f58-a1e2-7c0d5b8f3a64", "type": "evaluation.completed" },
  "kind": "event",
  "status": "succeeded",
  "attempts": 2,
  "last_status_code": 200,
  "last_error": null,
  "next_attempt_at": null,
  "created_at": "2026-10-29T14:02:47.000Z",
  "completed_at": "2026-10-29T14:03:48.000Z",
  "payload": {
    "object": "event",
    "id": "evt_9b3e7c21-4d6a-4f58-a1e2-7c0d5b8f3a64",
    "type": "evaluation.completed",
    "api_version": "v1",
    "created_at": "2026-10-29T14:02:47.000Z",
    "workspace": "ws_2c8f4a1d-7e3b-4c69-9d05-6a1f3e7b2c48",
    "data": { "object": "evaluation", "id": "eval_3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a0c4e93", "result": "deny" }
  },
  "attempt_log": [
    { "attempt": 1, "started_at": "2026-10-29T14:02:47.000Z", "duration_ms": 10003, "status_code": null, "error": "timeout", "counted": true, "response": null },
    { "attempt": 2, "started_at": "2026-10-29T14:03:47.000Z", "duration_ms": 184, "status_code": 200, "error": null, "counted": true, "response": "ok" }
  ]
}

payload.data is shortened here. The real body holds the full object.

Errors

CodeStatusMeaning
WEBHOOK_DELIVERY_NOT_FOUND404No delivery with this ID exists in the workspace, or it's older than the 30 days the delivery log keeps.
INVALID_FIELD422The ID doesn't start with whd_.

Resend a webhook delivery

Sends the delivery's event to the same endpoint again, right away, as a new delivery with kind: "resend". The event ID and body are unchanged, so your duplicate check recognizes it.

MethodPathScopeIdempotency-Key
POST/v1/webhook-deliveries/{id}/resendwebhooks:writeRequired

Also available as abusezero webhook-deliveries resend in the AbuseZero CLI, abusezero_resend_webhook_delivery on the AbuseZero MCP server and call() in the AbuseZero Node.js SDK.

  • Any delivery in the log can be sent again, whatever its status.
  • A resend is attempted once, and counts as a delivery.
  • The endpoint must be active. Resume a paused endpoint first.
  • With an OAuth token, the signed-in member must be the workspace owner or an admin, as in the dashboard.

Path parameters

ParameterTypeDescription
idstringThe delivery ID, starting with whd_.

Example

const resend = await abusezero.call("/v1/webhook-deliveries/whd_1f6b3d84-7a2c-4e95-8b10-6d4e2a9c7f35/resend", {
  method: "POST",
  idempotencyKey: "resend-whd_1f6b3d84",
});

Response

Returns 201 with the new webhook delivery object, with kind: "resend" and status: "pending".

Errors

CodeStatusMeaning
WEBHOOK_DELIVERY_NOT_FOUND404No delivery with this ID exists in the workspace, or it's older than the delivery log keeps.
WEBHOOK_ENDPOINT_PAUSED409The endpoint is paused. Resume it in Developers → Webhooks, then send again.
PERMISSION_REQUIRED403With an OAuth token, the signed-in member isn't the workspace owner or an admin.

For every other code, see REST API errors.

Retention

Deliveries, their attempts and their request bodies are kept for 30 days. Deleting an endpoint deletes its deliveries. A data deletion removes the deliveries of the evaluations and outcomes it deletes.

How is this guide?

Last updated on

On this page