Merchant API

Poll payment intent status

Get the latest payment result while waiting for a webhook or a payer-facing update.

Use webhooks to keep your order system up to date. Poll when an active payer-facing screen needs a fresh result or when your webhook endpoint is temporarily unavailable.

Read a payment intent

GET /payment_intents/:id
curl -s "$API_BASE/payment_intents/dord_01HZX..." \
  -u "$API_PUBLIC_KEY:$API_SECRET_KEY"

The intent is scoped to your Merchant and the Environment of the API key. A different Merchant or Environment receives 404 not_found.

{
  "id": "dord_01HZX...",
  "status": "succeeded",
  "payment_method": "FPX",
  "next_action": null,
  "failure_code": null,
  "failure_message": null,
  "updated_at": "2026-05-09T12:01:00.000Z"
}

Interpret the result

StatusMeaningYour application should
requires_payment_methodThe selected method needs replacement or another attempt.Let the payer choose again.
requires_actionThe payer still has an action to complete.Present the current next_action.
requires_captureThe payment is authorised and awaits its required capture step.Follow your capture workflow.
processingThe payment is waiting for an authoritative result.Keep the order pending.
succeededThe payment is complete.Fulfil the order once.
failedThe payment ended without succeeding.Let the payer start a new payment.
expiredThe payment window ended before completion.Let the payer start a new payment.
cancelledThe payment cannot complete.Let the payer start a new payment.

failure_code and failure_message explain a failed attempt. They do not replace the payment intent status. A successful payment can also have separate refund and dispute fields; use those for post-payment money movement.

Each GET reads the newest committed payment projection without triggering a Provider request. Durable Provider observation continues independently while the intent is active. When there is no new result yet, continue waiting for the webhook or poll again with backoff.

Poll with a limit

Poll only while a person is actively waiting. Stop after a short deadline and let the webhook finish the flow.

async function waitForResult(id: string, deadlineMs = 60_000) {
  const deadline = Date.now() + deadlineMs
  let delayMs = 500

  while (Date.now() < deadline) {
    const response = await fetch(`${process.env.API_BASE}/payment_intents/${id}`, {
      headers: { Authorization: process.env.API_AUTHORIZATION! },
    })
    const intent = await response.json()

    if (["succeeded", "failed", "expired", "cancelled"].includes(intent.status)) return intent

    await new Promise((resolve) => setTimeout(resolve, delayMs))
    delayMs = Math.min(delayMs * 2, 5_000)
  }

  return null
}

Do not treat a timeout, return URL, or QR-code expiry as a payment outcome. Leave the order pending until the payment intent reaches a terminal state.

On this page