curl -X POST "https://api.liddie.io/invoice/exampleslug1/cancel" \
-H "Content-Type: application/json" \
-d '{"confirm":true}'
// Public endpoint — no credentials required, safe from the payer's browser.
const res = await fetch('https://api.liddie.io/invoice/exampleslug1/cancel', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ confirm: true }),
});
const result = await res.json();
console.log(result.status); // "CANCELLED"
{
"success": true,
"status": "CANCELLED"
}
Public checkout
Cancel invoice (payer)
Cancel an unpaid Liddie invoice from the payer's side using the public invoice id — the request body must be exactly {"confirm":true}.
POST
/
invoice
/
{invoiceId}
/
cancel
curl -X POST "https://api.liddie.io/invoice/exampleslug1/cancel" \
-H "Content-Type: application/json" \
-d '{"confirm":true}'
// Public endpoint — no credentials required, safe from the payer's browser.
const res = await fetch('https://api.liddie.io/invoice/exampleslug1/cancel', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ confirm: true }),
});
const result = await res.json();
console.log(result.status); // "CANCELLED"
{
"success": true,
"status": "CANCELLED"
}
Cancels an unpaid invoice from the payer’s side. This powers the hosted invoice page, and it’s safe to call from the payer’s browser if you’re building a custom checkout UI. All data is redacted — no fees, no merchant internals.
Authorization
None — this endpoint is public. It only accepts the public invoice id (the last segment ofinvoiceUrl, e.g. exampleslug1); raw 24-hex payment ids are rejected so payments can’t be enumerated. Rate limit: 3/min.
Parameters
string
required
The public invoice id — the last segment of the payment’s
invoiceUrl. Raw 24-hex payment ids are rejected.boolean
required
Must be
true. The body must be exactly {"confirm":true} — without it the request is rejected with the 400 shown below.Send
{"confirm":true} as the request body. confirm must be present and true; any extra properties are silently ignored (stripped before validation), not rejected — so {"confirm":true,"x":1} still succeeds. Only a missing or non-true confirm fails validation.curl -X POST "https://api.liddie.io/invoice/exampleslug1/cancel" \
-H "Content-Type: application/json" \
-d '{"confirm":true}'
// Public endpoint — no credentials required, safe from the payer's browser.
const res = await fetch('https://api.liddie.io/invoice/exampleslug1/cancel', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ confirm: true }),
});
const result = await res.json();
console.log(result.status); // "CANCELLED"
{
"success": true,
"status": "CANCELLED"
}
Response
boolean
true when the invoice was cancelled.string
The new invoice status:
CANCELLED.Errors
| Status | Body | Why |
|---|---|---|
| 400 | {"ok":false,"error":{"code":"VALIDATION_ERROR","message":"body must have required property 'confirm'"}} | The body did not include confirm |
| 400 | {"error":"Payment not found or cannot be cancelled"} | Unknown invoice id, or the invoice is not in a cancellable state (already cancelled/funded, or any state other than WAITING/AWAITING_CURRENCY). Note this is a 400, never a 404. |
See also
- Get invoice status — verify the invoice now reports
CANCELLED. - List currency options — the selection step this cancel abandons on an
AWAITING_CURRENCYinvoice. - Webhooks & IPN — how your backend learns about status changes without polling.