> For the complete documentation index, see [llms.txt](https://docs.coda.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coda.co/codapay/hosted-payment-page-integration/cancel-a-payment-request.md).

# Cancel a Payment Request

This reference describes the server-side API used to cancel a payment request on a **best-effort** basis. Use this endpoint to terminate an in-flight transaction before it reaches a final state.

The endpoint accepts the cancellation when the transaction is still in a cancellable state and returns an immediate acknowledgement. The final outcome of the cancellation is confirmed asynchronously via a POST notification.

> **Note:** `status: "failed"` describes the outcome of the **cancel request**, not the outcome of the transaction. It means the cancellation could not be honored — the transaction itself is not failed and will continue to its natural outcome (success or failure). You will still receive the standard transaction notification.

#### Endpoint <a href="#endpoint" id="endpoint"></a>

Method: `POST`

<table data-full-width="true"><thead><tr><th width="131.78515625">Environment</th><th>Base URL</th></tr></thead><tbody><tr><td>Sandbox</td><td><code>https://sandbox.codapayments.com/airtime/api/restful/v2.0/Payment/cancel</code></td></tr><tr><td>Production</td><td><code>https://airtime.codapayments.com/airtime/api/restful/v2.0/Payment/cancel</code></td></tr></tbody></table>

#### When You Can Cancel <a href="#when-you-can-cancel" id="when-you-can-cancel"></a>

Cancellability depends on the payment method and how far the transaction has progressed.

| Payment method                     | Cancellable                                                                                             | Not cancellable                                                                                          |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Cards (single charge)              | Before capture is initiated.                                                                            | Once capture is initiated, or once the transaction has reached a final state.                            |
| Cards (Auth & Capture Split)       | Before authorization, and during the post-authorization / pre-capture window (voids the authorization). | Once capture is initiated, or once the transaction has reached a final state.                            |
| Alternative payment methods (APMs) | Before the payment is dispatched to the provider.                                                       | Once the payment has been dispatched to the provider, or once the transaction has reached a final state. |

If you call the endpoint outside the cancellable window, the API returns `status: "failed"` with a `resultCode` describing why.

#### Request Body <a href="#request-body" id="request-body"></a>

The request body must be sent in JSON format and include the following parameters:

<table><thead><tr><th width="289.85546875">Parameter</th><th width="93.06640625">Type</th><th width="108.59765625">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>cancelPaymentRequest.apiKey</code></td><td>string</td><td>Yes</td><td>Your Coda API key for authentication.</td></tr><tr><td><code>cancelPaymentRequest.projectId</code></td><td>string</td><td>Yes</td><td>The unique identifier for your project.</td></tr><tr><td><code>cancelPaymentRequest.txnId</code></td><td>string</td><td>Yes</td><td>The Coda transaction ID to cancel.</td></tr></tbody></table>

**Example Request**

```json
{
  "cancelPaymentRequest": {
    "apiKey": "your_api_key_here",
    "projectId": "your_project_id",
    "txnId": "7760859208170001746"
  }
}
```

#### Response — Accepted <a href="#response--accepted" id="response--accepted"></a>

Returned when the transaction is in a cancellable state. This is an **acknowledgement only** — the cancellation itself is confirmed asynchronously via a POST notification (`cancellation_request_succeeded` or `cancellation_request_failed`).&#x20;

HTTP status: `200 OK`

```json
{
  "cancelPaymentResult": {
    "status": "received",
    "txnId": "7760859208170001746"
  }
}
```

#### Response — Failed <a href="#response--failed" id="response--failed"></a>

Returned when the cancellation cannot be honored. The HTTP status is `200 OK` because the API call itself succeeded; the cancellation simply cannot proceed. Inspect `resultCode` to determine why.

```json
{
  "cancelPaymentResult": {
    "status": "failed",
    "txnId": "7760859208170001746",
    "resultCode": 208,
    "resultDesc": "Transaction is past the cancellable window. The transaction lifecycle continues unchanged."
  }
}
```

When you receive `failed`, do not retry the cancel. The transaction will proceed to its natural outcome and you will receive the standard transaction notification. The `failed` status refers to the cancel request only — it is not a signal that the transaction itself has failed.

#### Webhook Notification <a href="#webhook-notification" id="webhook-notification"></a>

When the API returns `status: "received"`, the cancellation is processed asynchronously and a POST webhook is delivered to your Complete Notification URL with the final outcome. No webhook fires for `failed` responses — the synchronous response already contains the result.

Two event types are emitted:

| eventType                        | When it fires                                                                                                                                                                                             |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cancellation_request_succeeded` | The cancellation was carried out. The transaction is now in a cancelled terminal state.                                                                                                                   |
| `cancellation_request_failed`    | The cancellation could not be carried out. The transaction is **not** cancelled and will continue to its natural outcome. You will receive the standard transaction-outcome notification when it settles. |

Cancellation notifications are **POST-only** and **sent by default** to any merchant that calls this endpoint. The only prerequisite is a configured Complete Notification URL. If your integration currently consumes only GET transaction notifications, you must implement POST notifications to receive cancellation events.

**Example — `cancellation_request_succeeded`:**

```json
{
  "eventType": "cancellation_request_succeeded",
  "timestamp": "1776085975305",
  "data": {
    "txnId": "7760859208170001746",
    "orderId": "12321312321314",
    "amountValue": 1,
    "amountCurrency": "EUR",
    "originalValue": 1,
    "originalCurrency": "EUR",
    "resultCode": 221,
    "resultDesc": "Transaction has been cancelled.",
    "shopper": {},
    "paymentMethod": {},
    "transactionData": {}
  }
}
```

**Example — `cancellation_request_failed`:**

```json
{
  "eventType": "cancellation_request_failed",
  "timestamp": "1776085979501",
  "data": {
    "txnId": "7760859208170001746",
    "orderId": "12321312321314",
    "amountValue": 1,
    "amountCurrency": "EUR",
    "originalValue": 1,
    "originalCurrency": "EUR",
    "resultCode": 208,
    "resultDesc": "Cancellation request could not be honored. The transaction lifecycle continues unchanged.",
    "shopper": {},
    "paymentMethod": {},
    "transactionData": {}
  }
}
```

#### Result Codes <a href="#result-codes" id="result-codes"></a>

The following `resultCode` values may appear in the response:

| resultCode | status     | Meaning                                                                                     |
| ---------- | ---------- | ------------------------------------------------------------------------------------------- |
| —          | `received` | The cancellation has been accepted. A POST notification will follow with the final outcome. |
| `208`      | `failed`   | Transaction is past the cancellable window. The transaction lifecycle continues unchanged.  |
| `221`      | `failed`   | Transaction has already been cancelled.                                                     |
| `231`      | `failed`   | Transaction is already marked as completed.                                                 |
| `236`      | `failed`   | Transaction does not belong to the merchant.                                                |
| `413`      | `failed`   | Transaction not found.                                                                      |
| `103`      | —          | Invalid request parameters. Returned as HTTP `4xx` without a `status` field.                |
| `204`      | —          | Invalid API key. Returned as HTTP `4xx` without a `status` field.                           |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.coda.co/codapay/hosted-payment-page-integration/cancel-a-payment-request.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
