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

# Verify the status

> How and when to call the confirm endpoint after a direct payin. Polling strategies depending on the validation mode.

The `confirm` endpoint is the same as for hosted payin. The difference is **when you call it**: without a redirect, there is no `return_url` to trigger a verification from the frontend. You must wait for the callback — it is the signal that the operator has finished processing.

```
GET https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/confirm/?invoiceToken={TOKEN}
```

For the full reference (headers, response fields, real payloads), see [Verify the status — hosted payin](/en/payment-api/hosted-payin/verify-status).

## When to call `confirm`

**Always when the callback is received.** Whatever the validation mode, the operator's confirmation can take a variable amount of time — from a few seconds to several minutes, even when the customer has already entered their OTP. The callback is the only reliable signal that the operator has processed the transaction.

Call `confirm` from your callback handler, with the token stored at creation, before fulfilling the order.

<Warning>
  Always call `confirm` with the **token stored at creation**, not the one received in the callback. Both tokens let you call the endpoint, but only the creation token lets you reconcile with your order.
</Warning>

## Request example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/confirm/?invoiceToken={TOKEN}" \
    -H "Apikey: {API_KEY}" \
    -H "Authorization: Bearer {API_TOKEN}" \
    -H "Accept: application/json"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    `https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/confirm/?invoiceToken=${token}`,
    {
      method: "GET",
      headers: {
        Apikey: process.env.LIGDICASH_API_KEY,
        Authorization: `Bearer ${process.env.LIGDICASH_API_TOKEN}`,
        Accept: "application/json",
      },
    }
  );

  const data = await response.json();
  ```

  ```php PHP theme={null}
  $ch = curl_init(
    "https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/confirm/?invoiceToken=" . urlencode($token)
  );
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Apikey: " . $_ENV["LIGDICASH_API_KEY"],
    "Authorization: Bearer " . $_ENV["LIGDICASH_API_TOKEN"],
    "Accept: application/json",
  ]);

  $data = json_decode(curl_exec($ch), true);
  curl_close($ch);
  ```
</CodeGroup>

## `status` values

| `status`       | Meaning                      | Recommended action                        |
| -------------- | ---------------------------- | ----------------------------------------- |
| `completed`    | Payment confirmed            | Fulfill the order                         |
| `pending`      | Awaiting customer validation | Continue polling or wait for the callback |
| `notcompleted` | Payment did not go through   | Offer to retry                            |

## Polling — safety net only

If the callback is delayed or unavailable in your environment, you can poll `confirm` at regular intervals. The status will be `pending` until the operator has finalized the transaction:

```javascript JavaScript theme={null}
async function waitForConfirmation(token, { interval = 4000, maxAttempts = 15 } = {}) {
  for (let i = 0; i < maxAttempts; i++) {
    const res = await fetch(
      `https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/confirm/?invoiceToken=${token}`,
      {
        headers: {
          Apikey: process.env.LIGDICASH_API_KEY,
          Authorization: `Bearer ${process.env.LIGDICASH_API_TOKEN}`,
          Accept: "application/json",
        },
      }
    );
    const data = await res.json();

    if (data.status === "completed") return { success: true, data };
    if (data.status === "notcompleted") return { success: false, data };

    await new Promise((r) => setTimeout(r, interval));
  }
  return { success: false, reason: "timeout" };
}
```

<Note>
  Polling is a safety net, not a replacement for the callback. Always base your business logic on the callback. See [Polling vs callback](/en/payment-api/status-verification/polling-vs-callback) for trade-offs.
</Note>

## Related pages

* [Verify the status — full reference](/en/payment-api/hosted-payin/verify-status) — detailed response fields and real payloads
* [Validation modes](/en/payment-api/direct-payin/validation-modes) — when the status becomes `pending`
* [Callback — security](/en/payment-api/callback/security) — why always re-verify with `confirm`
* [Polling vs callback](/en/payment-api/status-verification/polling-vs-callback) — choosing the right strategy
