> ## Documentation Index
> Fetch the complete documentation index at: https://docs.billions.works/llms.txt
> Use this file to discover all available pages before exploring further.

# Handle a callback

> Verify a payment callback against the authenticated API.

The TypeScript and PHP SDKs provide a helper that retrieves the invoice and
compares it with the callback.

<CodeGroup>
  ```ts TypeScript theme={null}
  import {
    CallbackVerificationError,
    InvoiceNotPaidError,
  } from '@billions-works/sdk-ts';

  try {
    const verifiedInvoice = await api.verifyInvoicePaid({
      id: request.body.id,
      status: request.body.status,
      paid_amount: request.body.paid_amount,
    });

    // Find the order by verifiedInvoice.order_no.
    // Transition it to paid exactly once.
    return response.status(200).send('OK');
  } catch (error) {
    if (
      error instanceof InvoiceNotPaidError ||
      error instanceof CallbackVerificationError
    ) {
      // Reject or postpone processing. Do not mark the order as paid.
      return response.status(202).send('Payment is not verified');
    }

    throw error;
  }
  ```

  ```php PHP theme={null}
  <?php

  use Billions\Exception\CallbackVerificationException;
  use Billions\Exception\InvoiceNotPaidException;

  try {
      $verifiedInvoice = $api->verifyInvoicePaid([
          'id' => $_POST['id'],
          'status' => $_POST['status'],
          'paid_amount' => $_POST['paid_amount'],
      ]);

      // Find the order by $verifiedInvoice['order_no'].
      // Transition it to paid exactly once.
  } catch (InvoiceNotPaidException | CallbackVerificationException $exception) {
      // Reject or postpone processing. Do not mark the order as paid.
  }
  ```

  ```bash cURL theme={null}
  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"
  ```
</CodeGroup>

<Warning>
  Add callback schema validation, order matching, and transactional idempotency
  before using these illustrative handlers in production. With cURL, your
  backend must also require `completed` status and compare the API response with
  the callback before marking the order as paid.
</Warning>
