Webhook deliveries
The signed callbacks your runs asked for: where each stands, and sending one again.
List callbacks
/api/v1/webhook-deliveriesThe signed callbacks your runs asked for, newest first: where each stands, how many attempts it took, and what your server answered last. Narrow to one run with ?executionId= or one match with ?matchId=.
A callback is written when a run that named a callbackUrl ends, and sent within about a minute. See Get told when a match finishes.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:read- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
executionId | Query | string (uuid) | Optional | Only the callback for this run. |
matchId | Query | string (uuid) | Optional | Only the callback for this match. |
limit | Query | integer | Optional | How many to return: 1 to 50, 20 when absent. A number outside that range is clamped; text is ignored. |
cursor | Query | string | Optional | Where the last page ended: the cursor inside the previous page's links.next. Pass links as given; a cursor you edit is refused. |
Examples
curl "https://liviamatch.com/api/v1/webhook-deliveries?executionId=0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83&matchId=1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
One page of callbacks.
{
"data": [
{
"id": "8a3f5d12-6b74-4c90-9e2a-0f8d1c6b3e57",
"type": "match.completed",
"status": "pending",
"url": "https://hooks.example.com/livia",
"attempts": 2,
"lastAttempt": {
"at": "2026-10-12T15:05:41.402Z",
"statusCode": 503,
"error": "http-503"
},
"nextAttemptAt": "2026-10-12T15:10:41.402Z",
"deliveredAt": null,
"occurredAt": "2026-10-12T15:04:05.000Z",
"createdAt": "2026-10-12T15:04:05.000Z",
"executionId": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"matchId": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"mode": "live"
},
{
"id": "8a3f5d12-6b74-4c90-9e2a-0f8d1c6b3e57",
"type": "match.completed",
"status": "delivered",
"url": "https://hooks.example.com/livia",
"attempts": 1,
"lastAttempt": {
"at": "2026-10-12T15:04:41.118Z",
"statusCode": 204,
"error": null
},
"nextAttemptAt": null,
"deliveredAt": "2026-10-12T15:04:41.118Z",
"occurredAt": "2026-10-12T15:04:05.000Z",
"createdAt": "2026-10-12T15:04:05.000Z",
"executionId": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"matchId": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"mode": "live"
}
],
"links": {
"next": null
}
}Fields (19)
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string (uuid) | The delivery's id: the webhook-id header and the callback body's id, the same on every retry and redelivery. |
data[].type | "run.completed" | "run.failed" | "run.canceled" | "match.completed" | "match.failed" | "match.canceled" | The event it announces. |
data[].status | "pending" | "sending" | "delivered" | "stopped" | "dead" | pending (due at nextAttemptAt), sending, delivered, stopped (410, or the key can no longer sign) or dead (every attempt failed). |
data[].url | string | Where it is sent: the callbackUrl the run named. |
data[].attempts | integer | Attempts made since it was written or last redelivered.at least 0 |
data[].lastAttempt | object | null | The latest attempt; null before the first. |
data[].lastAttempt.at | string (date-time) | |
data[].lastAttempt.statusCode | integer | null | What the receiver answered; null when it never answered. |
data[].lastAttempt.error | string | null | Why it did not deliver, as a code: http-500, timeout, refused-address, dns-failed, connect-failed, tls-failed, key-not-live, no-signing-secret. Null when it delivered. |
data[].nextAttemptAt | string (date-time) | null | When the next attempt is due; null unless pending. |
data[].deliveredAt | string (date-time) | null | |
data[].occurredAt | string (date-time) | When the run or match ended. |
data[].createdAt | string (date-time) | |
data[].executionId | string (uuid) | null | The run it is about; null for a data set match, which has none. |
data[].matchId | string (uuid) | null | The match it is about; null for a headless run. |
data[].mode | "live" | "mock" | null | live when the last attempt was sent, mock when a stand-in answered it on a non-production tier; null before any attempt. |
links | object | |
links.next | string | null | The URL of the next page, or null when this is the last. Follow it as given. |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid | executionId or matchId is not a UUID. |
| 400 | invalid-cursor | The cursor is not one a page linked to. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal
Send a callback again
/api/v1/webhook-deliveries/{deliveryId}/redeliverSends a delivered, stopped or dead callback again, under the same webhook-id and the same body, with a fresh retry ladder. The next sweep sends it, within about a minute. Dedupe on webhook-id and a redelivery of something you already handled is a no-op on your side.
An API key carrying the scope named here, or a signed-in session.
- Scope
search:run- Key kinds
- PersonalOrganization
Required and optional fields, allowed values and errors, as the page shows them.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
deliveryId | Path | string (uuid) | Required | The delivery's id: the webhook-id its callback carried. |
Examples
curl -X POST "https://liviamatch.com/api/v1/webhook-deliveries/8a3f5d12-6b74-4c90-9e2a-0f8d1c6b3e57/redeliver" \
-H "Authorization: Bearer $LIVIA_API_KEY"Responses
The callback is pending again.
{
"data": {
"id": "8a3f5d12-6b74-4c90-9e2a-0f8d1c6b3e57",
"type": "match.completed",
"status": "pending",
"url": "https://hooks.example.com/livia",
"attempts": 0,
"lastAttempt": {
"at": "2026-10-12T15:04:41.118Z",
"statusCode": 204,
"error": null
},
"nextAttemptAt": "2026-10-12T16:00:00.000Z",
"deliveredAt": "2026-10-12T15:04:41.118Z",
"occurredAt": "2026-10-12T15:04:05.000Z",
"createdAt": "2026-10-12T15:04:05.000Z",
"executionId": "0d9e7c1a-52b8-4f3a-8e6d-1c7a9b2f4e83",
"matchId": "1e8b4c27-5a93-4d60-b2f7-9c0d3a6e8f15",
"mode": "live"
}
}Fields (17)
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string (uuid) | The delivery's id: the webhook-id header and the callback body's id, the same on every retry and redelivery. |
data.type | "run.completed" | "run.failed" | "run.canceled" | "match.completed" | "match.failed" | "match.canceled" | The event it announces. |
data.status | "pending" | "sending" | "delivered" | "stopped" | "dead" | pending (due at nextAttemptAt), sending, delivered, stopped (410, or the key can no longer sign) or dead (every attempt failed). |
data.url | string | Where it is sent: the callbackUrl the run named. |
data.attempts | integer | Attempts made since it was written or last redelivered.at least 0 |
data.lastAttempt | object | null | The latest attempt; null before the first. |
data.lastAttempt.at | string (date-time) | |
data.lastAttempt.statusCode | integer | null | What the receiver answered; null when it never answered. |
data.lastAttempt.error | string | null | Why it did not deliver, as a code: http-500, timeout, refused-address, dns-failed, connect-failed, tls-failed, key-not-live, no-signing-secret. Null when it delivered. |
data.nextAttemptAt | string (date-time) | null | When the next attempt is due; null unless pending. |
data.deliveredAt | string (date-time) | null | |
data.occurredAt | string (date-time) | When the run or match ended. |
data.createdAt | string (date-time) | |
data.executionId | string (uuid) | null | The run it is about; null for a data set match, which has none. |
data.matchId | string (uuid) | null | The match it is about; null for a headless run. |
data.mode | "live" | "mock" | null | live when the last attempt was sent, mock when a stand-in answered it on a non-production tier; null before any attempt. |
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No such callback in your workspace. |
| 409 | delivery-in-flight | The callback is still pending or sending. |
Any call of this kind can also answer401 unauthenticated401 invalid-api-key403 insufficient-scope429 rate-limited429 monthly-cap-reached500 internal