PurchaseDocumentation
Purchase

Webhooks and Reconciliation

Route provider callbacks into Purchase and keep local state correct.

Checkout is only the command side. Durable billing state completes through webhooks.

Relevant files:

Webhook routing

The example uses one shared request handler and special-cases provider webhooks:

if (url.pathname === "/api/webhooks/stripe" || url.pathname === "/api/webhooks/paddle") {
  const provider = url.pathname.endsWith("stripe") ? "stripe" : "paddle"
  const signature = request.headers.get(provider === "stripe" ? "stripe-signature" : "paddle-signature") ?? ""
  const body = await request.text()
  const webhook = await processWebhook({ provider, body, signature })
  return Response.json({ webhook })
}

SDK processing

The runtime sends raw webhook data to Purchase:

const result =
  yield *
  sdk.webhooks.handle({
    provider: input.provider,
    body: input.body,
    signature: input.signature
  })

This keeps provider parsing, verification, normalization, and reconciliation inside the SDK.

On this page