Cancel operation
POST /v1/cancel_operation
Request cancellation of a payment operation. Payout cancellation is not available through this endpoint.
Endpoint
POST /v1/cancel_operation
Content-Type: application/json
X-API-Key: nspay_live_…Request
| Field | Type | Required | Description |
|---|---|---|---|
operation_id | UUID | conditional | Server-issued payment operation ID. |
merchant_operation_id | string | conditional | Merchant payment ID used for Create. |
reason | string | no | Cancellation reason for the audit log, at most 2048 bytes. An empty value uses cancel. |
Provide exactly one operation identifier. The shop is resolved from
X-API-Key; an operation from another shop returns 404 Not Found without
revealing that it exists.
To cancel a payment whose Create call may still be in flight, you must
identify it by merchant_operation_id — see
Cancelling a payment you just created.
{
"operation_id": "f6c2e7d4-3e5b-4f1f-8a02-9d6c7e8a1b22",
"reason": "customer_request"
}Response
A successful command returns 200 OK with the cancellation outcome and the
current operation snapshot:
{
"outcome": "cancelled",
"operation": {
"operation_id": "f6c2e7d4-3e5b-4f1f-8a02-9d6c7e8a1b22",
"type": "payment",
"status": "cancelled"
}
}| Outcome | Meaning |
|---|---|
cancelled | Cancellation was confirmed and the payment is terminal. |
already_terminal | The payment was already terminal; no new lifecycle or accounting change was made. |
cancelled means the cancellation is recorded durably and the payment is
terminal, so it can no longer be routed or accept money. This holds even when
the cancellation overtakes its own Create call: the two commands serialise on
one durable admission record on the server, so the outcome you receive is
authoritative in either order.
The guarantee attaches to a cancelled response you actually received. If the
request times out or returns 503, no decision may be assumed — retry the same
command (it is idempotent) or read the operation state.
The command is idempotent. Repeating it with the same identifier returns the same decision and makes no further lifecycle or accounting change, so it is always safe to retry.
Cancelling a payment you just created
A cancellation may arrive while the Create call that it refers to is still being processed — for example when you apply your own timeout to Create and give up on it. That case is supported, with one requirement:
Identify the payment by merchant_operation_id. A payment that does not
exist yet has no server-issued operation_id to match against, so a request
carrying only operation_id returns 404 Not Found. Sending
merchant_operation_id lets the API prove the payment is yours before
refusing it on your behalf.
{
"merchant_operation_id": "order-4711",
"reason": "client_timeout"
}The usual outcome is cancelled, with the in-flight Create refused rather
than routed: it returns no payment details to you, and none are shown to your
customer. If the Create call is still open on your side it completes as a
cancelled payment.
If the Create finished first, the cancellation is applied to the real payment
and the outcome reflects its actual state — cancelled if it could still be
cancelled, or already_terminal if it had reached a terminal state.
A cancelled outcome is authoritative even in this race. When the cancellation
won — the usual outcome above — payment details are never issued for that
operation: not in the Create response, not on a later read.
When the Create finished first, cancelled means the real payment was
cancelled. A Create response already on the wire, or a later read of the
operation, may still show the details that payment had been issued — the two
requests are answered independently and nothing can recall a response already
sent. Those details belong to a cancelled payment that can never complete, so
discard them and do not show them to your customer.
Repeating the command remains free and idempotent, but is not required to trust the result.
One reading caveat: while the racing Create is still running, reading the
operation may return 404. That is the create completing, not the cancellation
being in doubt — and if the Create never reached us at all, the 404 is the
final answer.
Errors and retries
400 Bad Request— the identifier is missing/ambiguous,operation_idis not a UUID, orreasonexceeds 2048 bytes.401 Unauthorized— the API key is missing or invalid.404 Not Found— the operation does not exist in the authenticated shop.412 Precondition Failed— the ID belongs to a payout or the payment cannot be cancelled in its current state.503 Service Unavailable— cancellation could not be durably accepted before the request deadline.
Do not interpret a timeout or 503 as a successful cancellation. Read the
operation state or retry the same command with the same identifier.