Webhooks Overview
Webhooks let your application hear about changes in Run Payments without polling. We send them when a merchant’s boarding status changes in Run Partner and when a transaction is recorded or changes status. Each webhook is an HTTP POST request with a JSON body, sent to an endpoint you give us.
How Webhooks Work
When an event happens, such as a merchant being sent for signature or a transaction being declined, Run Payments sends a POST request to each endpoint subscribed to that event. The body is JSON: the event type, the Run merchant ID it concerns, and a payload with the details. Your endpoint responds with a 2xx status to confirm it received the webhook. If it doesn’t, the webhook is retried. See Retries.
Event Types
Boarding Events
See Boarding Webhooks for payloads and details.
merchant.new- Merchant created, or application moved back tonewmerchant.sent_for_signature- Application sent for signaturemerchant.signed- Application signedmerchant.in_underwriting- Application in underwritingmerchant.boarded- Merchant boardedmerchant.live- Merchant livemerchant.cancelled- Application cancelledmerchant.declined- Application declinedmerchant.unknown- Merchant status changed tounknownmerchant.deleted- Merchant deleted from Run Partnerboarding.varcomplete- VAR details available for a merchant’s equipment
Transaction Events
See Transaction Webhooks for payloads and the transaction lifecycle.
transaction.entered- Transaction recorded, whatever its outcometransaction.entered.<source>- Transaction recorded from one source, such astransaction.entered.hpp(sent withtransaction.entered). See Sources.transaction.batched- Transaction batchedtransaction.captured- Transaction capturedtransaction.processed- Transaction processedtransaction.decline- Transaction declinedtransaction.reject- Transaction rejectedtransaction.voided- Transaction voidedtransaction.refund- Transaction fully refundedtransaction.partialrefund- Transaction partially refunded
Reporting Events
chargeback.entered- Chargeback recorded for a merchantfunding.entered- Funding information available for a merchantstatement.entered- Merchant statement available
See Reporting Event Payloads for payloads.
Request Body
Every webhook has the same top-level structure. Only payload differs by event.
Verifying Signatures
If your endpoint has a secret key, each request includes a signature header:
<signature> is the HMAC-SHA256 of the raw request body, keyed with your secret key, as lowercase hex. Your Integration Delivery Lead sets up the secret key, and can also set a different header name for your endpoint.
To verify a request:
- Read the raw request body as bytes, before parsing it as JSON. Parsing and re-serializing the body can change it and break the signature.
- Compute the HMAC-SHA256 of the raw body with your secret key and encode it as lowercase hex.
- Compare
sha256=plus your result to the header value with a constant-time comparison. - If they don’t match, reject the request.
The signature doesn’t include a timestamp, so a valid request could be captured and sent again. Use metadata.idempotency_key to ignore events you’ve already processed.
Delivery
- At least once. The same event can be delivered more than once.
metadata.idempotency_keystays the same on every delivery of an event, so store it and skip events you’ve already processed. Store the key only after your handler succeeds. If you store it first and the handler fails, you’ll skip the retry and lose the event. - No ordering guarantee. Events can arrive out of order, especially when a delivery is retried. Use the timestamps in the payload, not arrival order, to decide which event is most recent.
- Respond quickly, then process. Verify the signature, store the event, and return a
2xxresponse. Do any slow work after you respond. - New fields and event types may be added. Ignore fields and event types you don’t recognize instead of rejecting the request.
Retries
How Run Payments handles your endpoint’s response:
If your handler can’t process a valid request, return a 5xx so it’s retried. Don’t return a 4xx.
Failed deliveries are retried, up to 8 attempts in total by default. If your endpoint keeps failing, deliveries to it pause for a few minutes.
Recovering Missed Events
If you miss an event, or delivery fails on every attempt, get the merchant’s current state from the Boarding API with GET /merchants/{merchant_id}.
Getting Started
- Configure endpoints: Send your webhook endpoint URLs, and the event types you want, to your Integration Delivery Lead.
- Verify signatures: Check the signature header on every request. See Verifying Signatures.
- Handle duplicates: Skip events whose
metadata.idempotency_keyyou’ve already processed. - Return the right status code: Return
2xxonce the event is stored, and5xxif you need it sent again. See Retries.