Poll payment intent status
GET /payment_intents/:id while waiting for processing or a payment callback.
If your integration cannot host a webhook endpoint, poll for status. Webhooks are still preferable in production.
Endpoint
GET /payment_intents/:idScoped to the authenticating merchant and the key's stamped environment. An intent from another merchant or environment returns 404 not_found.
Request
curl -s "$API_BASE/payment_intents/dord_01HZX..." \
-u "$API_PUBLIC_KEY:$API_SECRET_KEY"Success
{
"object": "payment_intent",
"id": "dord_01HZX...",
"amount": "10000",
"currency": "MYR",
"country": "MY",
"environment": "test",
"checkout_mode": "hosted",
"status": "succeeded",
"merchant_reference": "order_12345",
"payment_method": "FPX",
"next_action": null,
"failure_code": null,
"failure_message": null,
"created_at": "2026-05-09T12:00:00.000Z",
"updated_at": "2026-05-09T12:01:00.000Z"
}Statuses are processing, requires_action, succeeded, failed, and expired.
Polling pattern
async function waitForTerminal(id: string, deadlineMs = 60_000) {
const start = Date.now();
let delayMs = 500;
while (Date.now() - start < deadlineMs) {
const intent = await getPaymentIntent(id);
if (!intent) return null;
if (!["processing", "requires_action"].includes(intent.status)) return intent;
await new Promise((resolve) => setTimeout(resolve, delayMs));
delayMs = Math.min(delayMs * 2, 5_000);
}
return null;
}Cap polling. Past 60 seconds the right answer is usually to wait for a webhook or inspect the intent in the dashboard.