Webhooks

Payment intent transitions emit events. Endpoints receive them as signed POSTs. The catcher is a Mockpay-hosted endpoint: deliveries record as captures for inspection, so integration tests verify webhooks without exposing a URL.

Event types

  • payment_intent.created
  • payment_intent.succeeded
  • payment_intent.amount_capturable_updated (manual capture confirm)
  • payment_intent.payment_failed (decline)
  • payment_intent.canceled

Event bodies follow the Stripe shape: { "id": "evt_...", "object": "event", "type", "created", "data": { "object": { ...resource } } }. Retrieve with GET /v1/events/:id; list with GET /v1/events (limit, starting_after, exact type filter).

Endpoints

MethodPathAction
POST/v1/webhook_endpointsCreate. url for outbound; catcher: true for a hosted catcher (Mockpay extension). enabled_events defaults to ["*"]
GET/v1/webhook_endpointsList
GET / POST / DELETE/v1/webhook_endpoints/:idRetrieve (includes secret — test mode re-displays), update (url, enabled_events, description, disabled, metadata), delete
GET/v1/webhook_endpoints/:id/capturesInspect what a catcher received (Mockpay extension): method, allowlisted headers, raw body

Delivery

Synchronous, one attempt per endpoint, five-second timeout, no retries. Deliveries POST JSON with a Stripe-Signature header. Failures are recorded and do not fail the API request that triggered the event.

Signature verification

Stripe-Signature: t=<epoch seconds>,v1=<hex hmac>

expected = HMAC_SHA256(key: whsec_secret, message: "<t>.<raw body>")
verify: expected == v1  (compare as constant-time hex)

Verify against the raw request body byte for byte. Stripe SDK verification helpers work unchanged with the endpoint's whsec_ secret.

The catcher

# 1. Create a catcher
curl https://api.mockpay.net/v1/webhook_endpoints \
  -u mock_sk_...: -d catcher=true
# → { "id": "we_...", "url": "/hook/mockpay/we_...", "secret": "whsec_..." }

# 2. Exercise the integration (create + confirm an intent)

# 3. Inspect what arrived
curl https://api.mockpay.net/v1/webhook_endpoints/we_.../captures \
  -u mock_sk_...:

The public /hook/mockpay/:id lane also accepts external requests on any method (no API key; the endpoint id is the credential). Point any webhook sender at it and read the captures back.