data.invoice_id from the webhook envelope and retrieve the authoritative
invoice. This works for both intermediate and final statuses.
try {
const webhook = request.body;
const invoice = await api.getInvoice(webhook.data.invoice_id);
// Update intermediate state when useful.
// Fulfill invoice.order_no exactly once only when status is completed.
return response.status(200).send('OK');
} catch (error) {
// A non-200 response causes Billions to retry the webhook.
return response.status(500).send('Could not retrieve invoice');
}
try:
invoice = api.get_invoice_from_webhook(webhook)
# Update intermediate state when useful.
# Fulfill invoice["order_no"] exactly once only when status is completed.
except Exception:
# Return a non-200 response so Billions retries the webhook.
raise
<?php
try {
$webhook = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR);
$invoice = $api->getInvoice($webhook['data']['invoice_id']);
// Update intermediate state when useful.
// Fulfill $invoice['order_no'] exactly once only when status is completed.
} catch (Throwable $exception) {
// Return a non-200 response so Billions retries the webhook.
}
curl --request GET \
--url "https://api.billions.works/public/v1/invoices/$BILLIONS_INVOICE_ID" \
--header "Content-Type: application/json" \
--header "x-api-key: $BILLIONS_API_KEY"
Add callback schema validation, order matching, and transactional idempotency
before using these illustrative handlers in production. A callback status is
informational until confirmed by the authenticated API.