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

# Callbacks and verification

> Where the customer lands after paying, and how to confirm a payment server-side

There are two separate things happening after a payment: the customer's browser comes back to
you, and your server finds out whether the money actually moved. Only the second one is
trustworthy.

## The callback flow

When you [create an order](/api-reference/orders/create-order), you supply a redirect URL:

```json theme={null}
{
  "payment": {
    "RedirectUrl": "https://yourdomain.com/payment/callback"
  }
}
```

After the customer completes 3-D Secure (or abandons it), they are sent back to that URL.

<Warning>
  A customer arriving at your callback URL proves nothing. They may have closed the
  authentication window, hit back, or reached it after a decline. **Always** verify server-side
  before you fulfil anything.
</Warning>

## There are no webhooks

The Checkout API does not push payment notifications. Status is **poll-only**:

* [Get order status](/api-reference/orders/get-order-status) — public key, poll until
  `isFinalStatus` is `true`
* [Verify an order](/api-reference/verification/verify-order) — secret key, server-side, the
  authoritative answer

<Note>
  Because there is no webhook, a customer who closes their browser mid-payment will still
  complete the payment without your callback ever firing. Reconcile pending orders from your
  backend on a schedule — do not rely on the customer coming back.
</Note>

## Verifying a payment

<Steps>
  <Step title="Read the reference">
    Use the order reference you generated at create time. Do not trust a reference supplied in
    the callback query string without checking it belongs to one of your orders.
  </Step>

  <Step title="Call verify from your server">
    With your **secret key**. This endpoint takes plain JSON — no encryption.
  </Step>

  <Step title="Check status and amount">
    Confirm the status is successful **and** the amount matches what you expected. An amount
    check protects you if a reference is ever replayed or tampered with.
  </Step>

  <Step title="Fulfil idempotently">
    Record that you have fulfilled this reference, and make repeat verifications no-ops. Polling
    means you will see the same successful status more than once.
  </Step>
</Steps>

### Example

```javascript theme={null}
const express = require('express');
const router = express.Router();

async function verifyOrder(reference) {
  const res = await fetch('https://api-v4.reeple.ai/charge/order/verify', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'api-key': process.env.REEPLE_SECRET_KEY,
    },
    body: JSON.stringify({ reference }),
  });
  return res.json();
}

router.get('/payment/callback', async (req, res) => {
  const order = await findOrderByReference(req.query.reference);
  if (!order) return res.status(404).send('Unknown order');

  const result = await verifyOrder(order.reference);
  const summary = result?.data?.orderSummary;

  const paid =
    result?.statusCode === '00' &&
    summary?.status === 'Successful' &&
    Number(summary?.totalChargedAmount) >= order.expectedTotal;

  if (paid && !order.fulfilled) {
    await fulfil(order);
  }

  res.redirect(paid ? '/thank-you' : '/payment-failed');
});
```

<Warning>
  Your secret key must never reach the browser. Keep verification on the server, and keep the
  key in an environment variable rather than in source control.
</Warning>

## Threading the callback through the redirect

If you are using the hosted redirect wrapper, pass the customer's destination on the pay-order
request so the wrapper knows where to send them once payment completes:

```
x-reeple-callback-url: https://yourdomain.com/payment/callback
```

The header is consumed by Reeple and never forwarded onward. It must be an absolute `http(s)`
URL; anything else is ignored.

## Next steps

<CardGroup cols={2}>
  <Card title="Verify an order" href="/api-reference/verification/verify-order">
    The endpoint reference, with the full response shape.
  </Card>

  <Card title="Order lifecycle" href="/order-lifecycle">
    Every status value, and how long to keep polling.
  </Card>
</CardGroup>
