> ## 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 payments

> Requests cancellation of one or more outbound SEPA, SEPA Direct Debit, SWIFT or T2 payments.

## Overview

Cancels up to 100 payments in one request. It is the only way to cancel a SWIFT or T2 payment.

The older per-scheme endpoints remain available for existing integrations: [Cancel SEPA transaction (v1)](/payments/api/sepa/transactions-cancel-v1) and [Cancel SDD payment (v0)](/payments/api/sepa-dd/cancel-transactions).

You do not pass the schema and it is not returned. The platform derives it from the payments you
reference - `SEPA`, `SDD`, `SWIFT` or `T2`, where `SEPA` covers both SEPA CT and Instant - and names
it only when it rejects your `reason` or `additionalComment`.

`reason` and `paymentIds` are required. `additionalComment` is optional, 1-105 characters.

<Note>
  All payments in one request must resolve to the same schema. A request mixing schemas is rejected
  in full with `400 MIXED_CANCELLATION_SCHEMAS`.
</Note>

## Reason codes

`reason` must be valid for the derived schema. The enum in the schema below is the union across all
schemas, so it accepts values your request will reject.

| Schema         | Accepted reasons                                                                                                                                                                      |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SEPA`         | `AC03` `AM09` `CUST` `DUPL` `FRAD` `TECH`                                                                                                                                             |
| `SWIFT`        | `AGNT` `AM09` `COVR` `CURR` `CUST` `CUTA` `DUPL` `FRAD` `TECH` `UPAY`                                                                                                                 |
| `T2`           | `AGNT` `AM09` `CUST` `CUTA` `DT01` `DUPL` `FRAD` `NARR` `TECH` `UPAY`                                                                                                                 |
| `SDD` outbound | `AC01` `AC04` `AC06` `AC13` `AG01` `AG02` `AM04` `AM05` `BE05` `CNOR` `DNOR` `DT01` `ED05` `FF01` `MD01` `MD02` `MD07` `MS02` `MS03` `PY01` `RC01` `RR01` `RR02` `RR03` `RR04` `SL01` |
| `SDD` inbound  | `AGNT` `CURR` `CUST` `CUTA` `DUPL` `FRAD` `TECH` `UPAY`                                                                                                                               |

`SDD` accepts both sets at request level and enforces the direction per payment. A reason valid for
the other direction is rejected in `results`.

## When you can send `additionalComment`

| Schema  | Rule                                       |
| ------- | ------------------------------------------ |
| `SEPA`  | Only with `AC03`, `AM09`, `CUST` or `FRAD` |
| `SWIFT` | Optional with any reason, never required   |
| `T2`    | Any reason, and **required** with `NARR`   |
| `SDD`   | Not permitted                              |

## Reading the response

You get `200 OK` whenever the request itself was well formed - including when every payment in it was
rejected. Check `results`, not the status code.

```json Response theme={null}
{
  "results": [
    { "paymentId": 12345, "status": "ACCEPTED" },
    {
      "paymentId": 12346,
      "status": "REJECTED",
      "error": "Cancellation is not supported for correspondent DEUTDEFFXXX (transaction 12346)"
    }
  ]
}
```

Every payment id you sent appears in `results`, sorted by id. A payment rejected on its own merits
does not affect the others.

<Warning>
  `error` is a human-readable message, not a stable code. Log it and show it to your operators, but
  do not branch on its text.
</Warning>

### Errors

A 4xx response means nothing was cancelled.

| Status | Code                              | Cause                                                                    |
| ------ | --------------------------------- | ------------------------------------------------------------------------ |
| 400    | `ILLEGAL_CANCELLATION_REASON`     | Reason not valid for the derived schema                                  |
| 400    | `VALIDATION_ERROR`                | `additionalComment` sent where not allowed, or missing with `NARR` on T2 |
| 400    | `MIXED_CANCELLATION_SCHEMAS`      | Payments resolve to more than one schema                                 |
| 400    | `UNSUPPORTED_CANCELLATION_SCHEMA` | Payment type has no cancellation path                                    |
| 404    | `TRANSACTION_NOT_FOUND`           | Unknown payment id                                                       |

## What happens to an accepted payment

`ACCEPTED` means different things depending on whether the payment had already left the platform.

<Tabs>
  <Tab title="Not yet sent">
    A payment in `Created`, `To sign` or `Signed` is cancelled outright. Its status becomes
    `Cancelled`, nothing is sent to the beneficiary bank, and no cancellation request is created - so
    you receive a payment-status-change webhook, not a payment-cancellation-status-change one.

    This is final. Nobody can refuse it.
  </Tab>

  <Tab title="Already sent">
    A payment in `Sent to clear`, `Accepted` or `Completed` gets a cancellation request created and a
    cancellation message sent to the beneficiary or correspondent bank.

    `ACCEPTED` here means the request was sent, not that the money is coming back. The other bank
    decides. Track the outcome through the
    [cancellation webhook](/payments/webhooks/payment-cancellation-status-change) until it reaches
    `PAYMENT_RETURNED`, `CANCELLATION_REFUSED` or `CANCELLATION_REJECTED`.
  </Tab>
</Tabs>

<Note>
  Outbound `SDD` payments are the exception. They are cancellable only in `Accepted` and always
  create a cancellation request.
</Note>

## Extra conditions for SWIFT

A SWIFT payment that has already been sent is checked against the correspondent bank first. It is
rejected when the payment has no UETR, when the debtor has no BIC to send the camt.056 from, when
the correspondent BIC cannot be resolved from the payment, or when the correspondent does not
support cancellation.

<Note>
  The capability lookup is live and fails closed: a correspondent that cannot be reached at that
  moment is treated as not supporting cancellation. Retry before treating this rejection as
  permanent.
</Note>

## Retrying

This endpoint takes no `Idempotency-Key` and does not need one. A payment whose cancellation is
already in flight comes back as `REJECTED`, so you can replay a whole batch after a partial failure
and only the payments that did not go through will be processed.

<Warning>
  Do not send two cancellation requests for the same payment at the same time. Retry after the
  previous response, not alongside it.
</Warning>


## OpenAPI

````yaml post /v3/payments/cancellations
openapi: 3.1.0
info:
  description: >
    # General info

    ## Base API URL for environments:

    * TEST: https://api.pgw-sandbox.finventi.com

    * PROD: https://api.pgw.finventi.com


    # Authentication

    <b>NOTE:</b> IP whitelisting is mandatory to gain access to our APIs in both
    TEST and PROD environments. To register your IPs, please contact
    `connectors-support@inventi.lt`.


    Our API uses OAuth 2.0 for authentication. To access the API, you need to
    obtain a bearer token from the authorization server.


    ### Obtain a Bearer Token

    To get a bearer token, use the following cURL command:


    ```

    curl -X POST \

    --location
    '<auth-server-url>/realms/<client-name>/protocol/openid-connect/token' \

    --header 'Content-Type: application/x-www-form-urlencoded' \

    --data-urlencode 'grant_type=client_credentials' \

    --data-urlencode 'client_id=api-sepa-gateway-client' \

    --data-urlencode 'client_secret=<client-secret>'

    ```


    where:


    `<auth-server-url>` is either `https://auth.sandbox.finventi.com/` (TEST) or
    `https://auth.finventi.com/` (PROD).


    `<client-name>` is a value of TenantID that was assigned by INVENTI team
    during initial configuration and could be found in Configuration Matrix that
    was shared to your representative.


    `<client-secret>` is a value that can be obtained by logging into SEPA
    Dashboard UI and going to <i>User Management</i> -> <i>Clients</i> ->
    `api-sepa-gateway-client` -> <i>Credentials</i> -> <i>Client Secret</i>.


    <b>NOTE:</b> The token is valid for 45 minutes.


    ### Include the Bearer Token in Requests

    Include the obtained token in the `Authorization` header of your API
    requests with the `Bearer` prefix:


    ```

    Authorization: Bearer <bearer-token>

    ```


    ### Example Request:

    ```

    curl --location --request POST
    'https://api.pgw-sandbox.finventi.com/gateway/createSepaPmt' \

    --header 'Authorization: Bearer <bearer-token>' \

    ```


    # Idempotency

    In our API, we support idempotency for certain endpoints to ensure that
    repeated requests have the same effect as a single request.

    Idempotent endpoints allow you to safely retry requests without worrying
    about unintended side effects, such as duplicate resource creation or
    modification. \


    To achieve idempotency, you need to include the **Idempotency-Key** header
    in your requests to the supported endpoints.

    If the provided idempotency key corresponds to an existing database object,
    the response will retrieve the data of the existing object instead of
    creating a new one.

    ## Idempotency-Key Header

    The **Idempotency-Key** header is used to uniquely identify a request and
    associate it with a specific operation. While the header value can be any
    string, we recommend using a UUID (Universally Unique Identifier) for
    uniqueness within the scope of the endpoint. This allows you to easily
    generate a unique key for each request.

    ### Example Request

    ```

    curl --location --request POST
    'https://api.pgw-sandbox.finventi.com/gateway/createSepaPmt' \

    --header 'Idempotency-Key: 123e4567-e89b-12d3-a456-426655440000' \

    ```

    ## Supported endpoints:

    * /gateway/createSepaPmt


    # Webhooks

    ## Signature Verification


    ### Introduction

    To ensure the authenticity and integrity of webhooks sent from our system,
    each webhook includes a digital signature. This signature allows the
    receiver to verify that the payload has not been altered during
    transmission. Verifying the signature confirms the webhook's origin and
    ensures its data integrity.


    Each webhook includes the signature in the `finventi-signature-N` HTTP
    header, where `N` represents the version of the signature. The current
    version is `1` (`finventi-signature-1`). When public keys are rotated, new
    header versions are issued, ensuring backward compatibility for clients
    until their code is updated.


    The signature should be verified using the RSASSA-PKCS1-v1.5 algorithm and
    the appropriate public key, based on the environment.


    ### Environment Public Keys

    Use the corresponding public key based on the environment in which you are
    verifying the webhook (current version - `1`)

    #### Test Environment Public Key

    ```text

    -----BEGIN PUBLIC KEY-----

    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvoc7GrFbduCeSVxFPJ3l

    a0NRa0caUqBddQAOUxuHTOuShOvdKbxRYc5u1vb9YNLJWjx4XSHESp8Q7oocqXt8

    +weBFsk/kAtJ4zjbYPY1PvAOLe+WObdxxZtfwzpwVxbtP6GQk5aUi2HbITe3EDf/

    7WEmvnAcWm++Mo6+GSh2Ky1t6o4htrx1lH2gYVg0iRHx1W9lLXjMl/5oLi1C6dtx

    TnBmXMlN/NT5YYU4lVlXQBZzS7a8ZgwosfW+v1uCimzbGcWytmmcFISjSNqkYaeg

    IXDYwKLwlsWtm975ln6UL20KcSt7ia+Lpuv7cdxJlOY95y0ds/PCw1x0HEPxU+44

    swIDAQAB

    -----END PUBLIC KEY-----

    ```


    #### Production Environment Public Key

    ```text

    -----BEGIN PUBLIC KEY-----

    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1pTRk8oUoGAAgXE8Gni8

    xvG2MJz6uYkZcNlXhPTrsxfqD4W5uDZOhy7APLz47Plcv+XL45kO0BFgjYHDRASx

    IIb6K5+YVyf9p1biLdZgf047wxwuC65bT6ddhuSX9FrMEtgPvghltSSfTZjdwVck

    QNE2JEV7vcIfq3ke5US+SP+6AHIcPyXypslp50CtO8wpZG+pz7rSdOoiRFTMhzVZ

    efDetRcnFv6DoAdapOiNVG9MBPqnE+BT5mnAlgF6V551ZJFOMhFvm/cLtP3Gj2a9

    /zNeCT1ZXHIuqxwrBUy/R8RSKJJIBWUbJEHF+pcPite+MgJm529Bt6K4mGCv1Nzv

    GwIDAQAB

    -----END PUBLIC KEY-----

    ```


    ### Additional Headers


    Each webhook includes the following HTTP headers to assist in verifying the
    signature:

    * `finventi-signature-N`: Each webhook contains the signature.

    * `finventi-signature-timestamp`: A UNIX timestamp (UTC) indicating when the
    webhook was sent.

    * `finventi-receiver-tenant-id`: The tenant ID for the webhook recipient.


    These headers must be used during the signature verification process to
    ensure consistency.


    ### Signature Verification Process

    To verify the authenticity of the webhook, the following steps must be
    performed:

    1. Concatenate the following components in the specified order, separated by
    periods (.):
      * The request body
      * The tenant ID from `finventi-receiver-tenant-id`
      * The timestamp from `finventi-signature-timestamp`

    Example:

    ```text

    {"trx_id":10300003,"end_to_end_id":"NOTPROVIDED","type":"Payment","direction":"OUTBOUND","amount":1,"currency":"EUR","status":"Created","updated_at":"2024-09-20T13:46:32.092083Z"}.demo1.1726839992

    ```

    2. Hash the concatenated string using the SHA-256 algorithm.

    3. Base64 decode the received finventi-signature-v header to obtain the
    signature.

    4. Verify the signature using
    [RSASSA-PKCS1-v1_5](https://datatracker.ietf.org/doc/html/rfc8017#section-8.2.2)
    with the hashed data, decoded signature, and the latest public key.


    ### Code Example (Node.js)

    ```js

    const crypto = require('crypto');


    const signatureBase64 =
    "GtZFu1uNFqOir8eDkar7+d/S+FtwQpk4mPGCuByKhJG29K1u7ynbVhkrDF8c3TqyX9wYHxpOa94FsgW2I4CnLh+B24LqL7WVSuACOL6GoSjfKeXP00NSp0ps8QYbVaJ8Ys6E4FePhp+7piAACkIP5vZ91JCLQ8lz36KRJlOnByQMTBH6j924n1GwZiZfbMojOGmMhLA0h8jWgTIeuvYPswiZXZXp0vpqJfWmdoqiU1ldoausTNFyoVwFuuzkxPv1VHvWeEeWirObUv3wNpyAnLnqomDgR7pe/9dDV0bkq5r0JkRhnbPCEFE/zzHeDgZ957hv8Oq3wJkGJarZ0NvPLw=="

    const signature = Buffer.from(signatureBase64, 'base64');


    const publicKey = `-----BEGIN PUBLIC KEY-----

    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvoc7GrFbduCeSVxFPJ3l

    a0NRa0caUqBddQAOUxuHTOuShOvdKbxRYc5u1vb9YNLJWjx4XSHESp8Q7oocqXt8

    +weBFsk/kAtJ4zjbYPY1PvAOLe+WObdxxZtfwzpwVxbtP6GQk5aUi2HbITe3EDf/

    7WEmvnAcWm++Mo6+GSh2Ky1t6o4htrx1lH2gYVg0iRHx1W9lLXjMl/5oLi1C6dtx

    TnBmXMlN/NT5YYU4lVlXQBZzS7a8ZgwosfW+v1uCimzbGcWytmmcFISjSNqkYaeg

    IXDYwKLwlsWtm975ln6UL20KcSt7ia+Lpuv7cdxJlOY95y0ds/PCw1x0HEPxU+44

    swIDAQAB

    -----END PUBLIC KEY-----`;


    const body =
    `{"trx_id":10300003,"end_to_end_id":"NOTPROVIDED","type":"Payment","direction":"OUTBOUND","amount":1,"currency":"EUR","status":"Created","updated_at":"2024-09-20T13:46:32.092083Z"}`;

    const tenantId = "demo1"

    const timestamp = "1726839992";

    const dataToVerify = Buffer.from(body + '.' + tenantId + '.' + timestamp);


    const isVerified = crypto.verify(

    "sha256",

    dataToVerify,

    {
      key: publicKey,
      padding: crypto.constants.RSA_PKCS1_PADDING,
    },

    signature

    );

    console.log("Verification successful:", isVerified);

    ```

    ## Payment status change webhook

    Payment status changes can send notifications using webhook to clients
    provided HTTP POST endpoint.


    Notifications are sent when payment/payment return status changes to one of
    the following statuses: Created, To sign, Signed, Accepted, Completed, Some
    problems, Cancelled, Rejected.


    There is retry mechanism - if an endpoint fails, the notification will be
    repeatedly sent until it is successfully delivered. During this retry
    process, all other notifications will be held back and will only be
    delivered once the initially blocked notification is successfully sent.


    Request is sent in json format.

    ### Request Body Example:

    ```json

    {
      "trx_id": 2018845,
      "end_to_end_id": "2302231660139326",
      "type": "Payment",
      "direction": "OUTBOUND",
      "amount": 10657, (CENTS)
      "currency": "EUR",
      "status": "Created",
      "updated_at": "2023-02-23 07:49:37.524808" (date&time when status was updated),
      "debtor_iban": "LT543210010000000003",
      "creditor_iban": "LT123450010000000004"
    }

    ```


    | Body parameter | Type |

    |-------------------|-------|

    | **trx_id**            | **Integer** |

    | **end_to_end_id**     | **String** |

    | **type**              | **String** classifier.<br>  Available values:
    "Payment", "Payment return", "Payment cancellation", "CSM fees", "Reverse
    payment", "Adjustment" |

    | **direction**         | **Enum**.<br>  Available values: "INBOUND",
    "OUTBOUND" |

    | **amount**            | **Integer** |

    | **currency**          | **String** classifier.<br>  Available values:
    "EUR" |

    | **status**            | **String** classifier.<br>  Available values:
    "Created", "To sign", "Signed", "Accepted", "Completed", "Some problems",
    "Cancelled", "Rejected", "Pending confirmation" |

    | **updated_at**        | **DateTime** |

    | **debtor_iban**       | **String** |

    | **creditor_iban**     | **String** |

     ## Payment cancellation status change webhook
    Payment cancellation status changes can send notifications using webhook to
    clients provided HTTP POST endpoint.


    Notifications are sent when payment cancellation status changes to one of
    the following statuses: CANCELLATION_IN_PROGRESS, CANCELLATION_ACCEPTED,
    CANCELLATION_REJECTED, CANCELLATION_COMPLETED.


    There is retry mechanism - if an endpoint fails, the notification will be
    repeatedly sent until it is successfully delivered. During this retry
    process, all other notifications will be held back and will only be
    delivered once the initially blocked notification is successfully sent.


    Request is sent in json format.

    ### Request Body Example:

    ```json

    {
      "cancellationId": 102,
      "trxId": "2018845",
      "direction": "OUTBOUND",
      "reason": "CUST",
      "status": "CANCELLATION_IN_PROGRESS",
    }

    ```


    | Body parameter | Type |

    |-------------------|-------|

    | **cancellationId**    | **Integer** |

    | **trxId**            | **Integer** |

    | **direction**         | **Enum**.<br>  Available values: "INBOUND",
    "OUTBOUND" |

    | **reason**            | **Enum**.<br>  Available values: "DUPL", "CUST",
    "FRAD", "TECH", "AC03", "AM09", "AGNT", "COVR", "CURR", "CUTA", "DS24",
    "FRNA", "FRTR", "INDM", "SYAD", "UPAY","AC01", "AC04", "AC06", "AC13",
    "AG01", "AG02", "AM01", "AM04", "AM05", "CNOR", "DNOR", "MD01", "MD02",
    "MD07", "MS02", "MS03", "RC01", "RR01", "RR02", "RR04", "SL01", "BE05",
    "FF01", "DT01", "ED05", "PY01" |

    | **status**            | **Enum**.<br>  Available values:
    "CANCELLATION_CREATED", "CANCELLATION_IN_PROGRESS", "RETURNING", "REFUSING",
    "PAYMENT_RETURNED", "CANCELLATION_REFUSED", "PROCESSING_FAILED",
    "CANCELLATION_COMPLETED", "CANCELLATION_REJECTED", "CANCELLATION_ACCEPTED" |


    ### Cancellation request processing statuses

    The table below standardises how you track SEPA cancellation requests from
    start to finish. Each status maps to specific inbound/outbound ISO-20022
    messages, giving you clear, machine-readable checkpoints for monitoring and
    automating your cancellation workflow.


    | Status name | Description |

    | ----------- | ---------------- |

    | CANCELLATION_CREATED | Cancellation request successfully created and
    validated by the Payment Gateway system. |

    | CANCELLATION_IN_PROGRESS | The camt.056 payment cancellation request is
    received from the clearing system and waiting for the User activities. Can
    be accepted and payment will be returned or rejected. |

    | RETURNING | User decides to return the funds. The pacs.004 payment return
    message is sent to the initiator of the payment cancellation request. The
    intermediary cancellation request status, which doesn't allow to execute any
    actions until the final status of the payment return will be set. |

    | REFUSING | User rejects to return the funds. The camt.029 resolution of
    investigation message is sent to the initiator of the payment cancellation
    request. The intermediary cancellation request status, which doesn't allow
    to execute any actions until the final status of the resolution of
    investigation will be set. |

    | PAYMENT_RETURNED | Incoming cancellation: The pacs.004 payment return
    message successfully delivered to the beneficiary bank. This is the final
    processing status, which doest allow to perform any actions with the
    cancellation request. <br> Outgoing cancellation: The payment return
    pacs.004 message, following the sent cancellation request is received from
    the clearing system. The transaction based  on the payment return message is
    successfully created in system, its data linked with the respective
    cancellation request and the original outbound payment. |

    | CANCELLATION_REFUSED | Incoming cancellation: The camt.029 resolution of
    investigation message successfully delivered to the beneficiary bank. This
    is the final processing status, which doest allow to perform any actions
    with the cancellation request. <br> Outgoing cancellation: The resolution of
    investigation camt.029 message, following the sent cancellation request is
    received from the clearing system. The payment return refusal data are
    indicated for the related cancellation request. |

    | PROCESSING_FAILED | The state which indicates that there was an error
    during processing of the response for the cancellation request message. This
    state allows to reprocess the cancellation request after the errors will be
    eliminated. |

    | CANCELLATION_COMPLETED | Incoming cancellation: The payment return
    transaction completed successfully. If failed, the status will be changed to
    the CANCELLATION_IN_PROGRESS and it is possible to reprocess the
    cancellation request. <br> Outgoing cancellation: The pacs.004 payment
    return message following cancellation request is received from the clearing
    system. |

    | CANCELLATION_REJECTED | The payment cancellation request camt.056 message
    was rejected by the clearing system due to errors. The state allows to
    initiated additional cancellation request after the errors will be
    eliminated. |

    | CANCELLATION_ACCEPTED | The payment cancellation request camt.056 message
    successfully delivered to the beneficiary bank. |


    # External code sets
      ## Private identification codes

      | Identification code | Definition |
      |-------------------|-------|
      | **ARNU**    | **Number assigned by a social security agency to identify a non-resident person.** |
      | **CCPT**    | **Number assigned by an authority to identify the passport number of a person.** |
      | **CUST**    | **Number assigned by an issuer to identify a customer.** |
      | **DRLC**    | **Number assigned by an authority to identify a driver's license.** |
      | **EMPL**    | **Number assigned by a registration authority to an employee.** |
      | **NIDN**    | **Number assigned by an authority to identify the national identity number of a person.** |
      | **SOSE**    | **Number assigned by an authority to identify the social security number of a person.** |
      | **TXID**    | **Number assigned by a tax authority to identify a person.** |

      ## Organisation identification codes

      | Identification code | Definition |
      |-------------------|-------|
      | **BANK**    | **Unique and unambiguous assignment made by a specific bank or similar financial institution to identify a relationship as defined between the bank and its client.** |
      | **CBID**    | **A unique identification number assigned by a central bank to identify an organisation.** |
      | **CHID**    | **A unique identification number assigned by a clearing house to identify an organisation.** |
      | **CINC**    | **A unique identification number assigned by a designated authority to a certificate of incorporation and used to identify an organisation.** |
      | **COID**    | **Country authority given organisation identification (e.g., corporate registration number).** |
      | **CUST**    | **Number assigned by an issuer to identify a customer. Number assigned by a party to identify a creditor or debtor relationship.** |
      | **DUNS**    | **A unique identification number provided by Dun & Bradstreet to identify an organisation.** |
      | **EMPL**    | **Number assigned by a registration authority to an employer.** |
      | **GS1G**    | **Global Location Number. A non-significant reference number used to identify legal entities, functional entities, or physical entities according to GS1 numbering scheme rules.The number is used to retrieve detailed information that is linked to it.** |
      | **SREN**    | **The SIREN number is a 9 digit code assigned by INSEE, the French National Institute for Statistics and Economic Studies, to identify an organisation in France.** |
      | **SRET**    | **The SIRET number is a 14 digit code assigned by INSEE, the French National Institute for Statistics and Economic Studies, to identify an organisation unit in France. It consists of the SIREN number, followed by a five digit classification number, to identify the local geographical unit of that entity.** |
      | **TXID**    | **Number assigned by a tax authority to identify an organisation.** |
  title: SEPA Payment Gateway
  version: '1.0'
servers:
  - description: Payment Platform sandbox environment
    url: https://api.pgw-sandbox.finventi.com
security: []
tags:
  - description: >-
      Manage payment investigations. Supports two types: Claim Non-Receipt
      (camt.027) for outbound SEPA CT payments, and Payment Status Request
      (pacs.028) for outbound SEPA INST payments. Inbound investigations
      received from counterparties can be searched, viewed, and resolved via
      :resolve API (camt.029). A stalled SEPA CT claim non-receipt can also be
      chased with a pacs.028 reminder via the :remind API; such a reminder is
      excluded from search and from the per-payment list, and is returned inside
      the claim it belongs to, in claimNonReceiptDetails.reminders. Fetched
      directly by its own id it reads back as type PAYMENT_STATUS_REQUEST with
      schema SEPA.
    name: Investigations
paths:
  /v3/payments/cancellations:
    post:
      tags:
        - SEPA Credit Transfer / SEPA Instant Credit Transfer
        - SEPA Direct Debit
        - SWIFT Payment Transfer
        - T2
      summary: Cancel payments
      description: >

        Requests cancellation of one or more outbound payments.


        The cancellation schema is derived from the methods of the referenced
        payments rather than

        declared in the request. All payments in one request must share the same
        method — a request

        mixing, say, SEPA and SWIFT payments is rejected outright rather than
        partially processed.

        SEPA CT and SEPA INST resolve to the same schema, but they are separate
        schemes towards the

        clearing and one request carries one reason, so they may not be
        cancelled together either.


        Which reasons are accepted, and whether `additionalComment` is
        permitted, depend on the

        derived schema. The schema itself is not returned — when a reason is not
        valid for it, the

        `400` names both the derived schema and the reasons it accepts.


        Every referenced payment appears in the response with its own outcome; a

        payment that cannot be cancelled on its own merits — wrong direction,
        wrong status,

        cancellation already in flight — is reported as rejected without
        affecting the others.


        ## What happens to an accepted payment


        This depends on whether the payment has already left the platform, and
        the two outcomes are

        materially different for an integrator.


        A payment **not yet sent** (`Created`, `To sign`, `Signed`) is cancelled
        outright: its status

        becomes `Cancelled`, no cancellation message is sent to the
        counterparty, and no cancellation

        request is created — so there is no cancellation to track and no
        payment-cancellation-status-change

        webhook. You get a payment-status-change webhook instead. This is final
        and cannot be refused.


        A payment **already sent** (`Sent to clear`, `Accepted`, `Completed`)
        gets a cancellation request

        created and a cancellation message sent to the counterparty. The
        counterparty decides whether to

        return the funds, so acceptance here means the request was sent, not
        that the money is coming

        back. Track the outcome through the payment-cancellation-status-change
        webhook until it reaches

        `PAYMENT_RETURNED`, `CANCELLATION_REFUSED`, or `CANCELLATION_REJECTED`
        (when the clearing

        system rejects the request with a validation error).


        ## Why a payment comes back rejected


        Any payment: it is not a payment (a return or a reversal), it is
        inbound, its status does not permit cancellation, a cancellation is
        already in

        progress for it, or it already has a completed return.


        SWIFT payments that have already been sent are additionally checked
        against the correspondent

        bank, and are rejected when the correspondent cannot be resolved from
        the original payment, when

        the correspondent does not advertise support for cancellation, or when
        the payment lacks the

        references needed to address the cancellation message. These checks
        involve a live lookup and

        fail closed — a correspondent whose capabilities cannot be reached right
        now is treated as not

        supporting cancellation, and the same request may succeed on a later
        retry.
      operationId: cancelPayments
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CancelPaymentsRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CancelPaymentsResponse'
          description: >-
            Request accepted. Every referenced payment carries its own outcome
            in `results`; a payment rejected on its own merits does not fail the
            request. Returned even when every payment was rejected — always
            inspect `results` rather than relying on the status code.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: >-
            The request spans more than one payment method, references a payment
            whose method cannot be cancelled, the reason is not valid for the
            derived schema, or `additionalComment` is missing where required or
            supplied where not permitted
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: Tenant does not have an access to the resource
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
          description: One or more of the referenced payments do not exist
components:
  schemas:
    CancelPaymentsRequest:
      properties:
        additionalComment:
          description: >

            Free-text detail accompanying the reason. Permitted only where the
            derived schema allows it:


            * SEPA CT / INST: with CUST, FRAD, AM09 or AC03

            * SEPA DD: not permitted

            * SWIFT: optional with any reason

            * T2: with any reason, and required when the reason is NARR
          maxLength: 105
          minLength: 1
          type:
            - string
            - 'null'
        paymentIds:
          description: >-
            Ids of the payments to cancel. All must resolve to the same
            cancellation schema.
          items:
            format: int64
            type: integer
          maxItems: 100
          minItems: 1
          type: array
          uniqueItems: true
        reason:
          $ref: '#/components/schemas/PaymentCancellationReason'
          description: >

            Cancellation reason. The set of accepted values depends on the
            schema derived from the

            referenced payments — the enum below is the union across all
            schemas, not the set valid for

            any one request:


            * SEPA CT / INST: DUPL, CUST, FRAD, TECH, AC03, AM09

            * SEPA DD outbound: AC01, AC04, AC06, AC13, AG01, AG02, AM04, AM05,
            CNOR, DNOR, MD01, MD02, MD07, MS02, MS03, RC01, RR01, RR02, RR03,
            RR04, SL01, BE05, FF01, DT01, ED05, PY01

            * SEPA DD inbound: DUPL, AGNT, CURR, CUST, CUTA, UPAY, TECH, FRAD

            * SWIFT: DUPL, CUST, FRAD, TECH, AM09, AGNT, COVR, CURR, CUTA, UPAY

            * T2: DT01, DUPL, CUTA, TECH, UPAY, CUST, AGNT, FRAD, AM09, NARR
      required:
        - paymentIds
        - reason
      type: object
    CancelPaymentsResponse:
      properties:
        results:
          description: >-
            Per-payment outcome, one entry for every requested payment id,
            ordered by payment id
          items:
            $ref: '#/components/schemas/PaymentCancellationResult'
          type: array
      required:
        - results
      type: object
    ErrorResponse:
      description: Error response
      properties:
        code:
          description: Code of error
          type: string
        data:
          description: 'Error data '
          oneOf:
            - $ref: '#/components/schemas/ErrorResponseData'
            - type: 'null'
        message:
          description: Error message
          type:
            - string
            - 'null'
      required:
        - code
      type: object
    PaymentCancellationReason:
      enum:
        - AC01
        - AC03
        - AC04
        - AC06
        - AC13
        - AG01
        - AG02
        - AGNT
        - AM04
        - AM05
        - AM09
        - BE05
        - CNOR
        - COVR
        - CURR
        - CUST
        - CUTA
        - DNOR
        - DT01
        - DUPL
        - ED05
        - FF01
        - FRAD
        - MD01
        - MD02
        - MD07
        - MS02
        - MS03
        - NARR
        - PY01
        - RC01
        - RR01
        - RR02
        - RR03
        - RR04
        - SL01
        - TECH
        - UPAY
      type: string
    PaymentCancellationResult:
      properties:
        error:
          description: Why the cancellation was rejected. Absent when accepted.
          type:
            - string
            - 'null'
        paymentId:
          description: Id of the payment this outcome refers to
          format: int64
          type: integer
        status:
          description: Whether the cancellation was accepted for this payment
          enum:
            - ACCEPTED
            - REJECTED
          type: string
      required:
        - paymentId
        - status
      type: object
    ErrorResponseData:
      description: Error wrapper containing all occurred errors
      properties:
        errors:
          description: All occurred errors
          items:
            $ref: '#/components/schemas/ErrorResponseViolation'
          type: array
        message:
          description: Generic message for occurred errors
          type:
            - string
            - 'null'
      required:
        - errors
      type: object
    ErrorResponseViolation:
      description: Single error wrapper
      properties:
        code:
          description: Error code
          type:
            - string
            - 'null'
        field_name:
          description: Field name which failed
          type: string
        message:
          description: Error message
          type:
            - string
            - 'null'
        value:
          description: Value which was invalid
          type:
            - string
            - 'null'
      type: object

````