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.