MolnPayDocs
Guides

Manage endpoints

Register an endpoint, prove it, rotate its secret, recover a gap, and read the event log — from the console or the API.

The Webhooks contract says what arrives and how to verify it. This page is the receiving side: where deliveries go, and what you do when they stop.

Everything below is also a screen in the console. From the API it needs the webhooks:write scope (replay needs webhooks:replay, reads need webhooks:read); any key kind may hold them.

Register

curl -X POST https://api.molnpay.com/v1/webhooks \
  -H "Authorization: Bearer $MOLNPAY_KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/molnpay/webhook","event_types":["deposit.confirmed","deposit.orphaned"]}'

The 201 is the endpoint plus its secret (whsec_…) — the only time it is ever shown. Store it now; no endpoint returns it again, and a lost secret is answered by rotating. An empty event_types, the default, subscribes to every event, including types added later, so keep a default branch in your handler.

The URL must be https, on port 443 or 8443, with no credentials, resolving to a public address. It is checked before the endpoint exists and again on every send, because DNS is mutable. Up to 16 endpoints per project.

Prove it

curl -X POST https://api.molnpay.com/v1/webhooks/$ENDPOINT_ID/test \
  -H "Authorization: Bearer $MOLNPAY_KEY"

Queues one endpoint.test through the real pipeline — signed, SSRF-checked, retried — and answers 202 with a delivery_id. Read GET /v1/webhook_deliveries/{delivery_id} until status is succeeded; if it is not, response_status, response_body and error_detail say why, in that order of usefulness.

Rotate the secret

curl -X POST https://api.molnpay.com/v1/webhooks/$ENDPOINT_ID/rotate_secret \
  -H "Authorization: Bearer $MOLNPAY_KEY" -H "Content-Type: application/json" \
  -d '{"overlap_hours":24}'

Until overlap_until, every delivery carries two v1 values and either secret verifies, so switch your receiver at your own pace. 0 hours is for a leaked secret. The new secret is shown only in that response.

Pause, resume, re-enable

PATCH /v1/webhooks/{id} with {"status":"paused"} stops sends while still recording every event as a skipped delivery; {"status":"active"} resumes. The same PATCH re-enables an endpoint we disabled — five consecutive exhausted deliveries, or a 410 Gone from you — and resets its strike count. Fix the receiver first: re-enabling a broken one burns the retry budget again.

Recover a gap

curl -X POST https://api.molnpay.com/v1/webhook_deliveries/replay \
  -H "Authorization: Bearer $MOLNPAY_KEY" -H "Content-Type: application/json" \
  -d '{"endpoint_id":"'$ENDPOINT_ID'","status":"skipped","since":"2026-09-15T00:00:00Z"}'

Re-sends up to 100 failed, exhausted or skipped deliveries for the endpoint, oldest first, each as a new delivery of the same event — so a handler that dedupes on event.id is unaffected. Call it again for a larger gap. One delivery at a time: POST /v1/webhook_deliveries/{id}/replay.

The event log

GET /v1/events is every event your project emitted, newest first, ordered by sequence — the number the envelope carries. Reconciling "did we miss one?" is a comparison against this list, never a guess. GET /v1/events/{id} returns the event with its data; GET /v1/events/{id}/deliveries shows where each send of it stood.

Deleting an endpoint deletes its delivery history

DELETE /v1/webhooks/{id} removes the endpoint and every delivery record. The events themselves stay. If you are debugging a receiver, pause it instead.

The full shapes are in the Webhooks and Events reference.

On this page