Skip to content

Test and replay deliveries

View as Markdown

This guide checks a webhook receiver end to end, sees how each delivery went, and sends a failed one again.

  • A webhook endpoint registered, and its endpointId, as Get a webhook when a run finishes shows.
  • A receiver listening at its URL, such as one from Verify a webhook.
  • Node 22.12 or later, Python 3.11 or later, or Java 17 or later, with Kindgi 0.1's client, and KINDGI_API_URL and KINDGI_API_TOKEN set.

A test event checks the receiver end to end, without a run.

sendTest, or send_test in Python, queues a signed webhook.test event for an endpoint. Ask your coding agent: "I want to send my webhook endpoint a test event and see whether it arrived." For reference, this function sends one, then reads how it was delivered:

scripts/test-endpoint.ts
import { createClient } from '@kindgi/sdk/client';
const kindgi = createClient(); // KINDGI_API_URL, KINDGI_API_TOKEN
/** Sends the endpoint a test event, and prints how it was delivered. */
export async function testEndpoint(endpointId: string) {
const queued = await kindgi.webhookEndpoints.sendTest(endpointId);
console.log(queued.deliveryId, queued.event.type, queued.status);
// A few seconds later
await new Promise((resolve) => setTimeout(resolve, 5000));
const { data } = await kindgi.webhookEndpoints.listDeliveries(endpointId, { limit: 1 });
console.log(data[0]?.status, data[0]?.attempts, data[0]?.lastResponseStatus);
}
a0e05ab7-6cff-440b-b291-d03c0f4443c0 webhook.test pending
delivered 1 204

It prints the queued delivery, then its outcome: delivered at the first attempt, with the receiver's 204. The test event is signed like any other:

{
"id": "c1214e78-694f-401d-8b92-e374f0846a88",
"type": "webhook.test",
"createdAt": "2026-10-03T20:16:35.159Z",
"data": {
"endpointId": "9c0b9504-c5a6-439f-a5f9-e755f1c5e6e9"
}
}

Each event sent to an endpoint is a delivery. listDeliveries, or list_deliveries in Python, shows them, newest first, with how the endpoint answered:

{
"deliveryId": "6ca19f2b-0c57-481e-a768-ef06283898c0",
"endpointId": "9c0b9504-c5a6-439f-a5f9-e755f1c5e6e9",
"event": { "id": "f2b45827-da3c-4f4e-95ff-9422f0de0e13", "type": "run.finished", … },
"status": "delivered",
"attempts": 1,
"nextAttemptAt": null,
"lastAttemptAt": "2026-10-03T20:15:32.194Z",
"lastResponseStatus": 204,
"lastError": null,
"createdAt": "2026-10-03T20:15:32.095Z",
"deliveredAt": "2026-10-03T20:15:32.194Z"
}
Excerpt
  • status: pending while it waits for its next attempt, delivered once the endpoint answered 2xx, or failed once every attempt failed.
  • lastResponseStatus and lastError say what went wrong. lastError is connection-refused when nothing listened at the URL, for example. It's url-refused when the deployment refuses the receiver's address, as the url describes.
  • nextAttemptAt is when a pending delivery is tried again.

Pass status: 'failed', or status="failed" in Python, to list only the ones that gave up.

A delivery sent again now, after you fix its cause, doesn't wait for its next attempt.

When an endpoint's URL is wrong, its deliveries stay pending. The first attempt's lastError is connection-refused when nothing listens there, and nextAttemptAt is a minute later. Fix the URL, and send the delivery again now. Ask your coding agent: "I want to fix my webhook endpoint's URL and send its delivery again now." For reference, this function does both, for an endpoint and one of its deliveries:

scripts/fix-endpoint.ts
import { createClient } from '@kindgi/sdk/client';
const kindgi = createClient(); // KINDGI_API_URL, KINDGI_API_TOKEN
/** Points the endpoint at the right URL, and sends the delivery again now. */
export async function fixEndpoint(endpointId: string, deliveryId: string) {
await kindgi.webhookEndpoints.update(endpointId, { url: 'http://localhost:8787/hooks/kindgi' });
const again = await kindgi.webhookEndpoints.redeliver(endpointId, deliveryId);
console.log(again.status);
}
pending

It prints pending: the delivery is queued again. A few seconds later, it's delivered. update also changes an endpoint's events, filter, secretRef and description.

unregister stops the endpoint. Its deliveries that were still pending fail, and it no longer appears in list.

The webhook endpoints reference lists every operation.