the billing provider webhook receiver
POST/api/v1/credits/webhooks/polar
Receive and dispatch the billing provider payment webhooks.
Public endpoint — this is not Bearer-authenticated. the billing provider signs the raw
request body using the Standard Webhooks scheme: webhook-id,
webhook-timestamp, and webhook-signature headers with an HMAC-SHA256
over {webhook-id}.{webhook-timestamp}.{body} keyed by
polar_webhook_secret. Timestamps outside ±5 minutes are rejected. A
mismatch returns 401. In non-dev environments a missing secret fails closed.
Handled event types:
checkout.completed— credits the checkout's organization after re-verifying the checkout ownership against the billing provider API.checkout.failed— logged and ignored.subscription.*— plan transitions. Seeapp/billing/polar_subscriptions.py.order.created/order.paid— the monthly credit grant for a paid subscription period.- Any other event — logged and ignored.
Subscription and order events pass a delivery-id wall first: the
webhook-id header is claimed by insert before any work happens, so a
redelivered renewal cannot grant a second month of credits. A claim is
released again if processing throws, so a genuine fault still gets the billing provider's
retry.
- Rate-limit tier:
webhook(60 req/minute).
Responses
- 200
- 400
- 404
- 409
- 422
- 429
- 500
Successful Response
Bad request — malformed input or failed validation.
Resource not found, or hidden for tenant-enumeration safety (the caller lacks permission to know whether the resource exists).
Conflict — the current resource state does not allow this operation (e.g. assessment already started, email already in use).
Semantic validation failure — request shape was valid but contents were not.
Too many requests — rate limited. Retry after the window resets.
Internal server error — unexpected failure.