Webhooks API
Base URL: https://txnod.com/api/v1. Same HMAC header requirements as the Invoices API: X-Project-Id, X-Timestamp, X-Signature.
This API exposes the delivery log and resend control surface for outbound webhook events your project receives from TxNod. Both endpoints are production-kind-only — sandbox projects are rejected with production_project_required and use the sandbox mirror (/api/v1/sandbox/webhooks/events) instead. To learn which event types exist and what shapes they carry, see Webhook Event Types. To configure a project’s webhook URL or rotate its API secret, see Configuring partner webhooks and API keys.
List webhook events
GET https://txnod.com/api/v1/webhooks/events — cursor-paginated list of outbound webhook events for the authenticated project. projectId is derived from HMAC; filters (status, event_type, since, invoice_id) are optional snake_case query parameters. The response envelope uses canonical next_cursor (snake_case, omitted on the last page).
Request
Query parameters
| Param | Type | Required | Constraints |
|---|---|---|---|
status | "delivered" | "retrying" | "dlq" | "skipped" | no | — |
event_type | "invoice.detected" | "invoice.paid" | "invoice.overpaid" | "invoice.partial" | "invoice.expired" | "invoice.expired_paid_late" | "invoice.reverted" | "invoice.ambiguous" | no | — |
since | string (ISO 8601) | no | — |
invoice_id | string (ULID) | no | — |
cursor | string (ULID) | no | — |
limit | integer | no | min: 1; max: 200; default: 50 |
Response
200 — Cursor-paginated webhook event list
| Field | Type | Required | Constraints |
|---|---|---|---|
items | array<object> | yes | — |
next_cursor | string (ULID) | no | — |
Errors
| Status | Error code(s) | Trigger |
|---|---|---|
| 400 | validation_error | Query validation error |
| 401 | auth_invalid, signature_invalid, timestamp_out_of_window | HMAC authentication failed |
| 403 | key_revoked, project_suspended | API key revoked or project suspended |
| 500 | internal_error | Internal error |
Examples
curl "https://txnod.com/api/v1/webhooks/events?status=delivered&limit=100" \
-H "X-Project-Id: $TXNOD_API_KEY_ID" \
-H "X-Timestamp: $(date +%s)" \
-H "X-Signature: <hex>"import { TxnodClient } from '@txnod/sdk';
const client = new TxnodClient({
projectId: process.env.TXNOD_API_KEY_ID!,
apiSecret: process.env.TXNOD_API_SECRET!,
});
const page = await client.listWebhookEvents({ status: 'delivered', limit: 100 });
for (const event of page.items) console.log(event.id, event.status);Resend a webhook event
POST https://txnod.com/api/v1/webhooks/events/{event_id}/resend — resends a previously-emitted webhook event with a fresh event_id while preserving the original payload. target_url is re-resolved at resend time from invoices.callback_url (if any) or projects.default_webhook_url. Delivery is asynchronous — the row is enqueued onto the outbox and dispatched by the worker; the HTTP response is 202 Accepted. Resend is allowed for delivered, retrying, and DLQ’d events alike; the original row is never mutated.
Request
(no request parameters)
Response
202 — Resend accepted; new event enqueued
| Field | Type | Required | Constraints |
|---|---|---|---|
event_id | string (ULID) | yes | — |
original_event_id | string (ULID) | yes | — |
event_type | "invoice.detected" | "invoice.paid" | "invoice.overpaid" | "invoice.partial" | "invoice.expired" | "invoice.expired_paid_late" | "invoice.reverted" | "invoice.ambiguous" | yes | — |
project_id | string (ULID) | yes | — |
invoice_id | string | null | yes | — |
target_url | string | null | yes | — |
created_at | integer | yes | min: 0 |
created_at_iso | string (ISO 8601) | yes | — |
Errors
| Status | Error code(s) | Trigger |
|---|---|---|
| 401 | auth_invalid, signature_invalid, timestamp_out_of_window | HMAC authentication failed |
| 403 | key_revoked, project_suspended | API key revoked or project suspended |
| 404 | event_not_found | event_not_found — either the event does not exist, belongs to a different project, or the path id is not a valid ULID |
| 429 | rate_limit_exceeded | Per-project resend rate limit exceeded |
| 500 | internal_error | Internal error |
Examples
curl -X POST https://txnod.com/api/v1/webhooks/events/01HK8MAR2QEXAMPLE000000000/resend \
-H "X-Project-Id: $TXNOD_API_KEY_ID" \
-H "X-Timestamp: $(date +%s)" \
-H "X-Signature: <hex>"import { TxnodClient } from '@txnod/sdk';
const client = new TxnodClient({
projectId: process.env.TXNOD_API_KEY_ID!,
apiSecret: process.env.TXNOD_API_SECRET!,
});
const resent = await client.resendWebhookEvent('01HK8MAR2QEXAMPLE000000000');
console.log(resent.event_id, resent.original_event_id);