Webhooks
Subscribe to every metering and settlement event.
Last Price emits HMAC-SHA256 signed webhooks for every meaningful platform event. Verify the x-paid-signature header against the raw body and you can trust the payload end-to-end.
What you can do
- Subscribe any HTTPS endpoint with a per-destination signing secret.
- Verify each request with HMAC-SHA256 over the raw body — header is x-paid-signature.
- Filter by event type, function, or tenant when you only care about a subset.
- Inspect every delivery: request body, response status, retries, and timing.
- Automatic retry with exponential backoff on 5xx and network errors.
Event types
compute.completedA pricing call ran. Includes the metering breakdown.
compute.failedA pricing call failed. Includes the routed function and error.
signal.createdA new anomaly signal was detected.
invoice.createdA new invoice is ready for the tenant.
invoice.paidA tenant paid an invoice.
dispute.openedA dispute was opened against a compute charge.
function.publishedA function was published or updated in the marketplace.
Verify a delivery
import crypto from "node:crypto"
export function verifyWebhook(rawBody: string, header: string, secret: string) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex")
// Constant-time compare to avoid timing leaks.
const a = Buffer.from(expected, "hex")
const b = Buffer.from(header, "hex")
return a.length === b.length && crypto.timingSafeEqual(a, b)
}
// In your route handler:
const ok = verifyWebhook(rawBody, req.headers["x-paid-signature"], process.env.WEBHOOK_SECRET)The signature is HMAC-SHA256 over the raw request body — not the parsed JSON, and no timestamp. Use a constant-time compare to avoid timing attacks. See packages/security/webhook.ts for the canonical implementation.
Ready to try it?
Spin up a free playground tenant in under a minute. No credit card.