Webhooks
Endpoints that receive events.
Concepts, behaviour and examples: Webhooks guide.
GET /v1/webhooks
List webhooks
Cursor-paginated (limit, starting_after).
- Authentication
- Merchant API key
- Effect
- Read-only.
Query parameters
| Name | Type | Required | Description |
|---|
limit | integer | no | Page size (1–100). · ≥ 1, ≤ 100, default 20 |
starting_after | string | no | Object ID; return objects after it (ascending ID order). · 26 chars |
Responses
| Status | Meaning | Body / error codes |
|---|
| 200 | Success. | object |
| 401 | Missing or invalid API key. | authentication_error |
| 429 | Rate limited; honor retry-after. | rate_limit_exceeded too_many_auth_failures |
| 500 | Server error. | api_error |
Example response
{
"object": "list",
"url": "string",
"has_more": false,
"data": [
{
"object": "webhook",
"id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"url": "https://example.com/hooks/payware",
"enabled_events": [
"customer.created"
],
"is_active": false,
"created_at": "2026-10-25T18:00:00.000Z",
"updated_at": "2026-10-25T18:00:00.000Z"
}
]
}
POST /v1/webhooks
Create a webhook
Registers a URL to receive events. The signing secret is returned once.
- Authentication
- Merchant API key
- Effect
- Creates an active webhook.
Headers
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | no | Makes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars |
Request body
| Field | Type | Required | Description |
|---|
url | string (uri) | yes | http/https, no credentials. In production: https, no localhost/*.local/*.internal/private addresses (unless WEBHOOK_ALLOW_PRIVATE_HOSTS=true). · ≤ 2048 chars |
enabled_events | EventType[] | no | Omit or leave empty to receive all events. |
is_active | boolean | no | false pauses delivery. |
Example request
{
"url": "https://example.com/hooks/payware",
"enabled_events": [
"customer.created"
],
"is_active": false
}
Responses
| Status | Meaning | Body / error codes |
|---|
| 201 | Webhook created. | WebhookWithSecret |
| 400 | Invalid body or URL. | invalid_webhook_url validation_failed invalid_json |
| 401 | Missing or invalid API key. | authentication_error |
| 429 | Rate limited; honor retry-after. | rate_limit_exceeded too_many_auth_failures |
| 500 | Server error. | api_error |
Example response
{
"object": "webhook",
"id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"url": "https://example.com/hooks/payware",
"enabled_events": [
"customer.created"
],
"is_active": false,
"created_at": "2026-10-25T18:00:00.000Z",
"updated_at": "2026-10-25T18:00:00.000Z",
"secret": "string"
}
GET /v1/webhooks/:id
Retrieve a webhook
The secret is omitted.
- Authentication
- Merchant API key
- Effect
- Read-only.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | yes | Object ID (ULID). · 26 chars |
Responses
| Status | Meaning | Body / error codes |
|---|
| 200 | Success. | Webhook |
| 401 | Missing or invalid API key. | authentication_error |
| 404 | Not found, or not yours. | resource_missing |
| 429 | Rate limited; honor retry-after. | rate_limit_exceeded too_many_auth_failures |
| 500 | Server error. | api_error |
Example response
{
"object": "webhook",
"id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"url": "https://example.com/hooks/payware",
"enabled_events": [
"customer.created"
],
"is_active": false,
"created_at": "2026-10-25T18:00:00.000Z",
"updated_at": "2026-10-25T18:00:00.000Z"
}
POST /v1/webhooks/:id
Update a webhook
Partial update.
- Authentication
- Merchant API key
- Effect
- Updates the webhook.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | yes | Object ID (ULID). · 26 chars |
Headers
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | no | Makes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars |
Request body
| Field | Type | Required | Description |
|---|
url | string (uri) | no | http/https, no credentials. In production: https, no localhost/*.local/*.internal/private addresses (unless WEBHOOK_ALLOW_PRIVATE_HOSTS=true). · ≤ 2048 chars |
enabled_events | EventType[] | no | Omit or leave empty to receive all events. |
is_active | boolean | no | false pauses delivery. |
Example request
{
"url": "https://example.com/hooks/payware",
"enabled_events": [
"customer.created"
],
"is_active": false
}
Responses
| Status | Meaning | Body / error codes |
|---|
| 200 | Success. | Webhook |
| 400 | Invalid request. | empty_update |
| 401 | Missing or invalid API key. | authentication_error |
| 404 | Not found, or not yours. | resource_missing |
| 429 | Rate limited; honor retry-after. | rate_limit_exceeded too_many_auth_failures |
| 500 | Server error. | api_error |
Example response
{
"object": "webhook",
"id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"url": "https://example.com/hooks/payware",
"enabled_events": [
"customer.created"
],
"is_active": false,
"created_at": "2026-10-25T18:00:00.000Z",
"updated_at": "2026-10-25T18:00:00.000Z"
}
DELETE /v1/webhooks/:id
Delete a webhook
Removes the webhook and its delivery history.
- Authentication
- Merchant API key
- Effect
- Deletes the webhook and its events.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | yes | Object ID (ULID). · 26 chars |
Headers
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | no | Makes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars |
Responses
| Status | Meaning | Body / error codes |
|---|
| 200 | Success. | DeletedObject |
| 401 | Missing or invalid API key. | authentication_error |
| 404 | Not found, or not yours. | resource_missing |
| 429 | Rate limited; honor retry-after. | rate_limit_exceeded too_many_auth_failures |
| 500 | Server error. | api_error |
Example response
{
"object": "string",
"id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"deleted": true
}
POST /v1/webhooks/:id/rotate-secret
Rotate the signing secret
The old secret stops working immediately; failed deliveries are retried and re-signed with the new one.
- Authentication
- Merchant API key
- Effect
- Replaces the signing secret.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | yes | Object ID (ULID). · 26 chars |
Headers
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | no | Makes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars |
Responses
| Status | Meaning | Body / error codes |
|---|
| 200 | Success. | WebhookWithSecret |
| 401 | Missing or invalid API key. | authentication_error |
| 404 | Not found, or not yours. | resource_missing |
| 429 | Rate limited; honor retry-after. | rate_limit_exceeded too_many_auth_failures |
| 500 | Server error. | api_error |
Example response
{
"object": "webhook",
"id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"url": "https://example.com/hooks/payware",
"enabled_events": [
"customer.created"
],
"is_active": false,
"created_at": "2026-10-25T18:00:00.000Z",
"updated_at": "2026-10-25T18:00:00.000Z",
"secret": "string"
}
POST webhook: event
Event delivery
Payware POSTs one JSON envelope per event to each matching webhook. Headers: x-signature: t=<unix>,v1=<hex HMAC-SHA256 of <t>.<raw body>, x-event-type, x-webhook-id (unique per delivery, stable across retries). Respond with any 2xx within WEBHOOK_TIMEOUT_MS (default 10 s); redirects are never followed. Delivery is at-least-once, retried after 1 min, 5 min, 30 min, 2 h and 24 h (then failed); dedupe on id and expect out-of-order arrival.
- Authentication
- None
- Effect
- Your endpoint receives one signed envelope per event.
Request body
| Field | Type | Required | Description |
|---|
id | string | yes | Logical event ID; the same for every webhook that receives it. · 26 chars |
object | "event" | yes | |
type | EventType | yes | |
created | string (date-time) | yes | |
data | object | yes | |
data.object | object | no | The full API object (subscription, customer, payment, instrument or enrollment); deletions carry {object, id, deleted: true}. |
data.retry_at | string (date-time) | null | no | payment.failed only: next attempt, null when exhausted or standalone. |
data.replacement_instrument_id | string | null | no | instrument.detached only. · 26 chars |
Example request
{
"id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
"object": "event",
"type": "customer.created",
"created": "2026-10-25T18:00:00.000Z",
"data": {
"object": {},
"retry_at": "2026-10-25T18:00:00.000Z",
"replacement_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C"
}
}
Responses
| Status | Meaning | Body / error codes |
|---|
| 2XX | Acknowledged. | |