Set Up Webhooks
This guide takes you from no webhook configuration to a verified endpoint receiving signed events: register your URL, capture the signing secret, send a test ping, choose your events and keep an eye on deliveries. For payload shapes, signature verification code and retry semantics, see the webhook integration guide.
Every request below authenticates with your API key as a Bearer token and requires the webhooks:manage scope. Merchant keys manage their own endpoint (one per merchant). Partner keys manage a linked merchant's endpoint by adding merchant_id: a query parameter on GET requests and a body field on writes.
Step 1: Register your endpoint
Call PUT /api/v1/webhook with the HTTPS URL that should receive events. The same call creates the endpoint on first use and updates it in place afterwards.
JSON
The secret in this response is shown exactly once. It is stored encrypted and can never be read back, so capture it now and store it in your secret manager. You need it to verify the X-Softlemon-Signature header on every delivery. Later updates respond with HTTP 200 and never include the secret. If you lose it, rotate to get a new one.
The URL must use HTTPS on a publicly resolvable host. URLs with embedded credentials, localhost style hosts or private IP addresses are rejected with HTTP 422.
Step 2: Send a test ping
Confirm reachability and your signature verification before real events flow. The ping is delivered synchronously, signed with your secret and structured like a real event. It never appears in delivery history and does not touch delivery health.
JSON
The HTTP status of this response is 200 whether or not your receiver answered. Check data.success for the outcome: true means your endpoint answered with a 2xx status. Pings are limited to 10 per minute per API key.
Step 3: Choose your events
By default the endpoint receives every event type except transaction.pending (opt in by listing it explicitly). Send an events list to narrow the subscription:
JSON
Subscription rules:
- Omit
eventsto keep the stored subscription unchanged. - Send
"events": nullto reset to the default set. - An empty list is rejected. To pause deliveries entirely, send
"is_active": falseinstead. The configuration and secret survive a pause. - Unsubscribed event types are not recorded at all, so they never appear in delivery history.
The full event catalogue is in the webhook integration guide.
Step 4: Watch your deliveries
GET /api/v1/webhook returns the configuration together with delivery health: last_success_at, last_failure_at and consecutive_failures.
For per-event detail, list the delivery history. Filters cover status (pending, delivered, failed), event_type, transaction_id and a from/to date range:
JSON
List rows never include the payload snapshot. History depth equals the 30 day retention window, older events are pruned.
Step 5: Inspect and replay an event
Fetch a single event to see the stored payload (exactly what was signed and sent) and the full delivery attempt trail:
If your system missed or lost an event, replay it. The replay reuses the same event id and payload, carries a fresh delivery id and adds an X-Softlemon-Replay: true header so your receiver can tell it apart from the original:
JSON
Replaying an already delivered event is allowed, for example when the original was lost downstream. A failing replay never demotes a delivered event. Events older than the 30 day retention window cannot be replayed. Replays are limited to 30 per minute per API key.
Step 6: Rotate the secret
Rotate when the secret may have been exposed or on your own schedule:
JSON
Rotation is a hard cutover: the old secret stops signing immediately and the new one appears exactly once in this response. Update your verifier right away. Deliveries retried after the rotation are signed with the new secret, including retries of events first attempted before it.
Step 7: Delete the endpoint
To stop receiving webhooks for good, delete the endpoint. To pause instead, send "is_active": false with PUT /api/v1/webhook: the configuration and secret survive a pause, and nothing is delivered or retried while it lasts.
JSON
Deliveries stop immediately. Events still queued for the endpoint are marked failed, and the stored URL and signing secret are erased. Your delivery history stays readable through GET /api/v1/webhook/events. Registering again with PUT /api/v1/webhook creates a new endpoint with a new secret, and a replay of an older event is then delivered to the new endpoint. GET /api/v1/webhook returns HTTP 404 once the endpoint is deleted, and deleting when there is no endpoint returns HTTP 404 as well.
Good to know
GET /api/v1/webhookreturns HTTP 404 until the endpoint is first created.has_secretonly ever reports that a secret exists, never its value.- Pause with
"is_active": falseto stop deliveries while keeping the configuration;DELETE /api/v1/webhookremoves the endpoint for good (see Step 7). - Partner keys must send
merchant_idon every request in this guide. A missing or unlinkedmerchant_idreturns HTTP 400. - Build the receiver before you register: verify signatures on the raw request body, answer 2xx within 10 seconds and deduplicate on the event id. Working verification code in five languages is in the webhook integration guide.