Skip to main content
A webhook endpoint is an HTTPS URL you own that Flexprice sends a POST to when something happens in your account. Registering one takes a minute in the dashboard. Writing a handler that stays correct under retries takes a little more care, and this page covers both.

Registering a webhook endpoint

1

Open Webhooks

In the dashboard, go to Developers and open the Webhooks section, or run flexprice open webhooks from the CLI.
2

Add the endpoint

Click Add Endpoint and enter your URL. It must be HTTPS and reachable from the public internet. For local development, use a tunnel or Svix Play as described in Test webhooks locally.
3

Choose events

Subscribe to the events your handler acts on rather than everything. A billing integration usually starts with:
  • invoice.update.finalized
  • invoice.update.payment
  • payment.success and payment.failed
  • subscription.created, subscription.updated, and subscription.cancelled
  • wallet.credit_balance.dropped
The full list, with a link to each payload, is in the event catalog.
4

Copy the signing secret

Open the endpoint and copy its signing secret (it starts with whsec_). Store it with your other secrets. Your handler uses it to verify every delivery; see Signature verification.
Endpoints are per environment. Register one in sandbox and a separate one in production, each with its own secret.

The webhook delivery contract

A finalized invoice looks like this:
Every payload’s exact schema is documented under Webhook Events in the API reference, for example invoice.update.finalized.

Writing the webhook handler

A handler has four jobs, in this order:
  1. Verify the signature on the raw body before parsing anything.
  2. Acknowledge fast. Return 200 and do the real work on a queue. Anything slower than 5 seconds counts as a failure and is retried.
  3. Dedupe. Store the delivery ID (the svix-id header) and skip a delivery you have already processed. Retries and redeliveries mean you will see duplicates. Do not key on the object ID plus event_type alone: two subscription.updated messages for the same subscription would collapse into one. If you key on the object, include its updated_at. See Retries and ordering.
  4. Return 200 for events you do not handle. Otherwise Flexprice keeps retrying them.
The worker that drains the queue parses event_type and the typed payload. Parsing webhook payloads with the SDK shows the typed models in Go, Python, and TypeScript.

Watching webhook deliveries in the dashboard

The endpoint’s page in the dashboard shows its error rate, a Logs tab with every attempt and its response, and an Activity tab with delivery counts over time. Failed attempts can be replayed from Logs after you fix the handler.

Signature verification

Retries and ordering

Test locally