Skip to content

Webhooks overview

Every state change in Paylera emits a typed event. You register one or more webhook endpoints — HTTPS URLs in your application — and we deliver matching events as POST requests with a JSON body and a signature header. At-least-once, ordered per aggregate, retried with backoff.

Why webhooks (instead of polling)

  • Latency — react in ~100 ms after the state change, not after the next poll cycle.
  • Cost — no busy-wait against the API.
  • Correctness — events carry the canonical payload at the moment the change happened, including fields like previous_attributes you can’t reconstruct from a later GET.

What a delivered event looks like

POST /your-handler HTTP/1.1
Content-Type: application/json
Paylera-Signature: t=1736179200,v1=… ,v1=…
Paylera-Event-Id: evt_8f4a…
Paylera-Delivery-Id: del_…
Paylera-Event-Type: invoice.paid
{
"id": "evt_8f4a…",
"type": "invoice.paid",
"occurred_at": "2026-05-06T12:34:56.789Z",
"schema_version": 1,
"tenant_id": "ten_…",
"aggregate_type": "invoice",
"aggregate_id": "inv_…",
"data": { the full payload }
}

The Paylera-Signature header carries one or more v1 HMAC-SHA-256 signatures over t.{raw body}. See Verifying signatures.

Registering an endpoint

POST /v1/admin/webhook-endpoints
Idempotency-Key: <uuid>
{
"url": "https://yourapp.example/webhooks/paylera",
"events": ["invoice.paid", "subscription.canceled"],
"description": "production"
}

The response includes the signing secret:

{
"id": "we_…",
"url": "https://yourapp.example/webhooks/paylera",
"secret": "whsec_…",
"events": ["invoice.paid", "subscription.canceled"],
"status": "enabled"
}

Save the secret. It is only returned once. Store it in your secret manager.

Subscribing to events

The events array can be:

  • A list of specific types (["invoice.paid", "invoice.payment_failed"]).
  • A type prefix with .* (["invoice.*"]) to subscribe to all events of a category.
  • ["*"] to receive everything. Don’t. You’ll be paged on usage.* events you don’t care about.

The full catalog is at Event catalog.

Delivery semantics

  • At-least-once. A delivery may repeat. Your handler must be idempotent on event.id.
  • Ordered per aggregate. Events with the same aggregate_id arrive in commit order. Events for different aggregates may interleave.
  • Best-effort within seconds. P95 delivery latency is under 2 seconds from the originating commit.
  • Retries. On non-2xx response or timeout (>10 s), Paylera retries with exponential backoff over 24 hours. After 24 hours, the delivery is marked failed and emits a webhook_endpoint.delivery_failed meta-event.

See Retries & ordering for the full schedule.

What your handler must do

  1. Verify the signature. Reject unsigned or mismatched payloads.
  2. Parse the envelope. Read id, type, data.
  3. Dedupe on id. If you’ve processed this id before, return 2xx and do nothing.
  4. Do the work. Update your DB; trigger your downstream effect.
  5. Ack within 10 seconds with 2xx. Heavy work goes onto a queue; the handler ack’s fast.

Inspecting deliveries

GET /v1/admin/webhook-endpoints/{id}/deliveries?status=failed&limit=50

Each delivery record includes the request body, response status, response body (truncated), attempt count, and final outcome.

To replay a failed delivery:

POST /v1/admin/webhook-endpoints/{id}/deliveries/{delivery_id}/retry

Local testing

For local development, use a tunnel (ngrok, Cloudflare Tunnel) or the sandbox dashboard’s built-in Webhook tester. See Local testing.

Disabling

PATCH /v1/admin/webhook-endpoints/{id}
{ "status": "disabled" }

Disabled endpoints stop receiving deliveries; existing in-flight attempts complete. Re-enable any time.

Where to next