Cancel a payout intent
POST /payout_intents/:id/cancel while the payout is still awaiting approval.
Cancel a payout intent that is still in the approval gate.
Cancellation is only valid while status is requires_approval. Once the payout is processing
or terminal, this endpoint returns 422 approval_required and the payout proceeds.
Endpoint
POST /payout_intents/:id/cancelRequired headers:
Authorization: Basic <base64(publicKey:secretKey)>.Content-Type: application/json.
Optional but recommended:
Idempotency-Key: <uuid>.
Request
curl -s -X POST "$API_BASE/payout_intents/word_01HZX.../cancel" \
-u "$API_PUBLIC_KEY:$API_SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "reason": "duplicate_request" }'import { randomUUID } from "node:crypto";
const auth =
"Basic " +
Buffer.from(`${process.env.API_PUBLIC_KEY}:${process.env.API_SECRET_KEY}`).toString("base64");
async function cancelPayoutIntent(id: string, reason?: string) {
const res = await fetch(`${process.env.API_BASE}/payout_intents/${id}/cancel`, {
method: "POST",
headers: {
Authorization: auth,
"Idempotency-Key": randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify(reason ? { reason } : {}),
});
if (!res.ok) {
const { error } = (await res.json()) as { error: { code: string; message: string } };
throw new Error(`${error.code}: ${error.message}`);
}
return res.json();
}The body carries one optional field, reason — free text up to 512 characters, persisted to the order and surfaced in the dashboard, audit log, and terminal webhook.
Success
{
"object": "payout_intent",
"id": "word_01HZX...",
"amount": "50000",
"currency": "MYR",
"country": "MY",
"environment": "test",
"status": "cancelled",
"merchant_reference": "payout_98765",
"recipient": {
"type": "bank_account",
"account_last4": "7890",
"bank_code": "MBBEMYKL",
"holder_name": "Alice Tan"
},
"failure_code": "cancelled",
"failure_message": "duplicate_request",
"created_at": "2026-05-09T12:00:00.000Z",
"updated_at": "2026-05-09T12:00:03.000Z"
}A 202 returns the refreshed payout intent after the platform marks it cancelled. The response includes failure_code: "cancelled" and the cancellation reason in failure_message.
Response fields
Prop
Type
Poll GET /payout_intents/:id or watch for payout_intent.cancelled to confirm the terminal state.
Error: 422 approval_required
{
"error": {
"code": "approval_required",
"message": "Payout intent is in status \"processing\"; only requires_approval intents can be cancelled via this endpoint."
}
}Other outcomes:
404 not_found— the id does not exist, belongs to another merchant, or is in the other environment.409 idempotency_conflict— sameIdempotency-Key, different body.