> ## Documentation Index
> Fetch the complete documentation index at: https://docs.finventi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cancel Outbound Payments

> Request cancellation of outgoing SEPA payments before settlement.

# Cancel Payments When Plans Change

Sometimes payments need to be stopped - a customer changes their mind, duplicate payment detected, or wrong beneficiary details. Inventi handles the cancellation protocol with the beneficiary bank on your behalf.

<Info>
  **What happens when you cancel a payment:**

  1. You submit a cancellation request via API
  2. Inventi sends a **camt.056** message through CSM
  3. The beneficiary bank accepts or rejects the request
  4. You receive the outcome via webhook
</Info>

<Note>
  Cancellation is a **request**, not a guarantee. The beneficiary bank may accept or reject based on whether funds have been credited.
</Note>

## API Reference

<CardGroup cols={2}>
  <Card title="Cancel Transaction" icon="ban" href="/payments/api/sepa/cancel-transaction">
    Initiate a cancellation request
  </Card>

  <Card title="Cancellation Status Webhook" icon="bell" href="/payments/webhooks/payment-cancellation-status-change">
    Track cancellation lifecycle
  </Card>

  <Card title="Get Cancellation Request" icon="magnifying-glass" href="/payments/api/accounts/get-cancellation-request">
    Retrieve cancellation details
  </Card>

  <Card title="List Cancellation Requests" icon="list" href="/payments/api/accounts/get-cancellation-requests-list">
    Search cancellation requests
  </Card>
</CardGroup>

## How It Works

<AccordionGroup>
  <Accordion title="Request Flow" icon="paper-plane">
    1. You submit a cancellation request via API
    2. The platform creates a cancellation record and returns a `cancellationId`
    3. A **camt.056** message is sent to the beneficiary bank
    4. You receive webhook updates as the request progresses
  </Accordion>

  <Accordion title="Possible Outcomes" icon="code-branch">
    The beneficiary bank can:

    * **Accept**: funds come back as a payment return (pacs.004) - a new linked inbound transaction; the original settled payment stays `Completed`
    * **Reject**: Original transaction proceeds normally
    * **Refuse**: the beneficiary bank declines to return the funds (camt.029 refusal - `CANCELLATION_REFUSED`)

    <Warning>
      Never assume cancellation succeeded until the webhook indicates `PAYMENT_RETURNED`.
    </Warning>
  </Accordion>
</AccordionGroup>

```mermaid actions={true} theme={null}
sequenceDiagram
  autonumber
  participant App as Your System
  participant Platform as Payments Platform
  participant Webhook as Your Webhook
  participant DB as Your Database

  App->>Platform: POST /v1/transactions:cancel
  Platform-->>App: 200 {cancellationId}
  App->>DB: Store cancellationId

  Platform-->>Webhook: Cancellation created
  Platform-->>Webhook: Cancellation in progress

  alt Accepted
    Platform-->>Webhook: Returning
    Platform-->>Webhook: Payment returned (new linked return transaction)
    Webhook->>DB: Update statuses (original stays Completed)
  else Refused
    Platform-->>Webhook: Refusing
    Platform-->>Webhook: Cancellation refused (camt.029)
    Webhook->>DB: Original transaction proceeds
  end
```

## Initiate Cancellation

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.pgw-sandbox.finventi.com/v1/transactions:cancel \
    -H "Authorization: Bearer {token}" \
    -H "Content-Type: application/json" \
    -d '{
      "transaction_ids": ["trx_123456"],
      "reason": "CUST"
    }'
  ```

  ```json Response theme={null}
  {
    "cancellationId": "cancel_789",
    "status": "CANCELLATION_CREATED"
  }
  ```
</CodeGroup>

## Cancellation Statuses

<Tabs>
  <Tab title="In Progress">
    | Status                     | Description                           |
    | -------------------------- | ------------------------------------- |
    | `CANCELLATION_CREATED`     | Request initiated                     |
    | `CANCELLATION_IN_PROGRESS` | camt.056 sent to the beneficiary bank |
    | `RETURNING`                | Payment return in progress            |
    | `REFUSING`                 | Refusal in progress                   |
  </Tab>

  <Tab title="Final States">
    | Status                 | Description                                                                   |
    | ---------------------- | ----------------------------------------------------------------------------- |
    | `PAYMENT_RETURNED`     | Funds returned - a new linked return transaction is created (success outcome) |
    | `CANCELLATION_REFUSED` | Beneficiary bank refused to return the funds (camt.029)                       |
    | `PROCESSING_FAILED`    | Processing failed - the request needs attention                               |

    Historical cancellation requests may also show the legacy statuses `CANCELLATION_ACCEPTED`, `CANCELLATION_REJECTED`, and `CANCELLATION_COMPLETED` - these are no longer emitted for new requests.
  </Tab>
</Tabs>

## Track Both States

Cancellation and transaction states are independent. Monitor both via webhooks.

<CardGroup cols={2}>
  <Card title="Cancellation Accepted" icon="circle-check">
    **Cancellation**: `CANCELLATION_IN_PROGRESS` → `RETURNING` → `PAYMENT_RETURNED`

    **Transaction**: original stays `Completed`; a new linked payment return transaction credits the funds back
  </Card>

  <Card title="Cancellation Refused" icon="circle-xmark">
    **Cancellation**: `CANCELLATION_IN_PROGRESS` → `REFUSING` → `CANCELLATION_REFUSED`

    **Transaction**: `Completed`

    Payment settles normally
  </Card>
</CardGroup>

## Data Model

<ResponseField name="trx_id" type="string" required>
  Original transaction reference
</ResponseField>

<ResponseField name="cancellationId" type="string" required>
  Cancellation request identifier
</ResponseField>

<ResponseField name="cancellation_status" type="string" required>
  Track separately from transaction status
</ResponseField>

<ResponseField name="status_history" type="array" required>
  Append-only for audit
</ResponseField>

## Integration Checklist

<Steps>
  <Step title="Handle cancellation webhooks">
    Upsert by `cancellationId` to track cancellation state separately from transaction state
  </Step>

  <Step title="Link cancellation to transaction">
    Maintain the relationship between `trx_id` and `cancellationId` in your database
  </Step>

  <Step title="Display states separately">
    Show cancellation progress independently from transaction status in your UI
  </Step>

  <Step title="Wait for completion">
    Only consider a cancellation final when the webhook indicates `PAYMENT_RETURNED` or `CANCELLATION_REFUSED`
  </Step>
</Steps>

## What's Next?

You now understand exception handling for outbound payments. Complete your integration with inbound exceptions and reconciliation:

<CardGroup cols={2}>
  <Card title="Respond to Cancellations" icon="reply" href="/payments/integration-guide/inbound-cancellation">
    Handle incoming cancellation requests
  </Card>

  <Card title="Return Inbound Payments" icon="rotate-left" href="/payments/integration-guide/as">
    Return funds when you can't credit the beneficiary
  </Card>

  <Card title="Track and Reconcile" icon="chart-line" href="/payments/integration-guide/payment-information">
    Monitor transactions and reconcile with statements
  </Card>
</CardGroup>
