Report a result

Tell Localoy how a charge went. A SUCCEEDED result is the only thing that marks an order paid.

POST{BASE_URL}/payments/sessions/{id}/result

Records the outcome of your charge. Requires the PAYMENT scope.

Path parameters

idstringrequired
The session ID.

Headers

Idempotency-Keystringoptional
Up to 255 characters. A key already used on this session is not applied again. See Idempotency.

Body

statusstringrequired
SUCCEEDED, FAILED, CANCELLED or PROCESSING, in any case.
amountMinorintegeroptional
Required for SUCCEEDED. What you charged, in minor units. Must equal the session's amountMinor.
currencystringoptional
If sent with SUCCEEDED, must equal the session's currency.
providerReferencestring | nulloptional
Your gateway's transaction ID. Up to 200 characters.
failureCodestring | nulloptional
Your gateway's failure code, for FAILED. Up to 80 characters.
failureReasonstring | nulloptional
A reason for FAILED, shown to the customer. Up to 500 characters.
notestring | nulloptional
Free text added to the session's history in the Partner Portal. Up to 500 characters.

Response

dataobjectrequired
The session's settlement record — not the checkout view.
replayedbooleanrequired
true when nothing was applied because this was a repeat. Top level, next to data.

Rules#

The request is checked in this order:

  1. The body is validated. An invalid body is a 400, even for an unknown session.

  2. The session must be yours and in the key's environment, or 404.

  3. If the Idempotency-Key was already used on this session, the call answers 200 with "replayed": true and applies nothing.

  4. If the session's lifetime has passed, it is marked EXPIRED first.

  5. If the session already has the reported status, the call answers 200 with "replayed": true.

  6. The transition must be allowed:

    FromAllowed to
    PENDINGPROCESSING, SUCCEEDED, FAILED, CANCELLED
    PROCESSINGSUCCEEDED, FAILED, CANCELLED
    FAILEDPROCESSING, SUCCEEDED
    EXPIREDSUCCEEDED
    SUCCEEDED, CANCELLED, REFUNDED—
  7. For SUCCEEDED, the amount and currency must match the session's, and the order must not already be paid or refunded some other way.

Refused attempts keep their Idempotency-Key

A refused request is remembered with its Idempotency-Key. Resending a corrected body with the same key answers 200 with "replayed": true and applies nothing. Use a new key for a corrected request, and check data.status.

Effects#

ReportedOrderWebhooks
SUCCEEDEDMarked paid. A pending activity booking or dining reservation is confirmed if your confirmation policy is automatic.payment.updated — one per ticket for an event ticket order — and booking.updated if confirmed.
FAILEDMarked failed. Check-ins already recorded on an event ticket order are cleared.payment.updated
PROCESSING, CANCELLEDUnchanged.None.

A sandbox test session has no order: nothing changes and no webhook fires.

Status codes#

StatusCodeMeaning
200—Recorded, or replayed: true.
400—A field is invalid; message names it.
400payment_unreportable_statusstatus is not one you can report. EXPIRED is set by Localoy; refunds use /refund.
400payment_amount_requiredSUCCEEDED without amountMinor.
404payment_session_not_foundNo session of yours in this environment has that ID.
409payment_invalid_transitionNot allowed from the current status. details.from, details.to.
409payment_amount_mismatchdetails.expectedAmountMinor, details.reportedAmountMinor. Not marked paid.
409payment_currency_mismatchdetails.expectedCurrency, details.reportedCurrency. Not marked paid.
409payment_subject_not_chargeableThe order was already settled elsewhere. details.paymentStatus.
409payment_session_conflictAnother request changed the session at the same time. Read it back first.
curl -X POST "$LOCALOY_BASE_URL/payments/sessions/cm5s3ss10n00000000000001/result" \
  -H "Authorization: Bearer $LOCALOY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7d1f0b3e-2c4a-4b9e-8f51-0a6c2d9e4b17" \
  -d '{
    "status": "SUCCEEDED",
    "amountMinor": 90000,
    "currency": "BDT",
    "providerReference": "TXN-88213094"
  }'
Response · 200
{
  "success": true,
  "message": "Payment result recorded.",
  "data": {
    "id": "cm5s3ss10n00000000000001",
    "status": "SUCCEEDED",
    "amountMinor": 90000,
    "paidAmountMinor": 90000,
    "providerReference": "TXN-88213094",
    "settledAt": "2026-09-26T08:41:07.512Z",
    "…": "…"
  },
  "replayed": false
}
Response · 409
{
  "success": false,
  "message": "This session quoted 90000 (minor units, BDT); you reported 9000. The order has NOT been marked paid.",
  "code": "payment_amount_mismatch",
  "details": { "expectedAmountMinor": 90000, "reportedAmountMinor": 9000 },
  "requestId": "3f0c9f8e-6a1d-4f5e-9b1a-2f1c0d9e7a41"
}