---
title: "Recurring payments with cards and wallets"
description: "Recurring payments let you charge the customer's payment method after the purchase. In this guide you will learn how to initialise the series with an authenticated First transaction and how to process Next transactions with card, Apple Pay, Google Pay and Click to Pay."
url: "https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/recurring-payments/"
language: "en"
---

# Recurring payments with cards and wallets

Merchant Initiated Transactions (*MIT*) are typical of business models in which payments are made at a later time than the purchase.

In these scenarios the buyer authorises the merchant to make future charges by accepting the **terms and conditions** set out in the contractual agreement between the parties.

> **Use cases**
>
> - **Fixed amount and frequency**: subscriptions, digital services.
> - **Variable amount or frequency**: utility bills, pay-per-use services.

A recurring payment flow consists of two types of transaction:

| Transaction                                      | Initiated by | Customer present | Authentication                                            |
| ------------------------------------------------ | ------------ | ---------------- | --------------------------------------------------------- |
| **First – Customer Initiated Transaction (CIT)** | The customer | Yes              | **Strong Customer Authentication (SCA)** always mandatory |
| **Next – Merchant Initiated Transaction (MIT)**  | The merchant | No               | Not required                                              |

The **First** transaction verifies the payer's identity and generates the reference identifier needed to process the **Next** transactions. The payment method token can be requested together with the First, or a previously generated token can be used. Next transactions are processed by the merchant without the customer being present.

> **Token request**
>
> The token can also be generated separately from the recurring transaction and used later for the First. For how to request it, see the [Tokenization](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/token/) section.

> **Regulatory scope**
>
> MIT transactions are considered **out of scope of PSD2** and therefore **do not require two-factor authentication**.

---

## Recurrence types

Fabrick Payment Orchestra supports two types of recurring payment. The choice determines the value of the `transDetails.type` field for all the transactions in the series.

|                | Scheduled                          | Unscheduled                                                                        |
| -------------- | ---------------------------------- | ---------------------------------------------------------------------------------- |
| **Amount**     | Fixed                              | Variable                                                                           |
| **Frequency**  | Constant and defined               | Variable, not scheduled                                                            |
| **Use cases**  | Subscriptions and digital services | Utility bills, pay-per-use services, no-show fees, damage charges for rented goods |
| **First type** | `01F`                              | `03F`                                                                              |
| **Next type**  | `01N`                              | `03N`                                                                              |

---

## Supported payment methods

| Method       | First (CIT)                                                                       | Next (MIT)                           |
| ------------ | --------------------------------------------------------------------------------- | ------------------------------------ |
| Card         | Hosted integrations or API Only, with card data or an existing token              | Token generated or used in the First |
| Apple Pay    | Hosted integrations or API Only, with the Apple Pay payload or an existing token  | Token generated or used in the First |
| Google Pay   | Hosted integrations or API Only, with the Google Pay payload or an existing token | Token generated or used in the First |
| Click to Pay | Hosted integrations only                                                          | Token generated or used in the First |

For **Next** transactions the flow is the same for all methods. Wallets are handled as cards: the token generated or used during the First must always be sent in the `paymentTypeDetails.creditcard.token` field.

---

## Common requirements

Next transactions are valid only if all these conditions are met:

- there is an **agreement between merchant and buyer** authorising the charges
- each Next **includes the reference to the First transaction** (`paymentID`)
- each Next is submitted with the **same shopLogin** as the First
- the First **has not been cancelled**: otherwise the recurring chain would no longer be valid
- the First was **authenticated with SCA**

> **Tokenization is mandatory**
>
> Each recurring series is associated with a payment method **token**, to be used for the Next transactions. The token can be requested together with the First, or a previously generated token can be used for a card or wallet that has already been tokenized: in this case the First does not request a new tokenization (see [API Only integration](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/recurring-payments/#api-only-integration)). For how to request a token, see the [Tokenization](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/token/) section.

---

## First flow (CIT)

### Request fields

To tell the system that the transaction is the first of a recurring series, add the `transDetails` object to the `payment/create` call, in addition to the mandatory fields:

| Field                                         | Scheduled `01F` | Unscheduled `03F` | Description                                                                               |
| --------------------------------------------- | --------------- | ----------------- | ----------------------------------------------------------------------------------------- |
| `transDetails.type`                           | `01F`           | `03F`             | Recurrence type                                                                           |
| `transDetails.authenticationAmount`           | ✅               | ✅                 | Maximum amount expected under the agreement between the parties                           |
| `transDetails.recurringTransaction.expiry`    | ✅               | ❌                 | Expiry date of the agreement, `YYYYMMDD` format. No Next can be processed after this date |
| `transDetails.recurringTransaction.frequency` | ✅               | ❌                 | Minimum number of days between two charges of the same series                             |

> **Maximum authorised amount**
>
> If `authenticationAmount` is not populated, or if `amount` is greater than `authenticationAmount`, the system uses `amount` as the **maximum authorised amount** for the Next transactions and, at the same time, charges the initial payment for that amount.

### Zero initial amount (ASI)

If the service includes a **free trial period** or a **deferred charge**, you can set `amount` to **zero**. In this case the request is called **ASI** (*Account Status Inquiry*) and `authenticationAmount` must be populated with the maximum amount set out in the agreement for the Next transactions.

The amount in `authenticationAmount` **may be shown to the buyer** during authentication, depending on their bank's settings; alternatively, the amount in the `amount` field may be shown.

> **ASI**
>
> The ASI is intended to verify the payment method and initialise the recurring series: the transaction cannot be captured or cancelled.

### Choosing the integration mode

The First can be handled in two ways, which differ in who collects the payment details and in the number of calls needed:

| Scenario                                                                                                                   | Integration                                                                                                                                                                     | Calls                                                                     |
| -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| The customer enters the card or chooses a wallet (Apple Pay, Google Pay, Click to Pay) through the **hosted integrations** | [Hosted](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/recurring-payments/#hosted-integration) (Checkout Page, Pay By Link, Lightbox, Web Component) | `payment/create`                                                          |
| The card or wallet has **already been tokenized**                                                                          | [API Only](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/recurring-payments/#api-only-integration)                                                   | `payment/create` without `requestToken` + `payment/submit` with the token |
| The customer enters the card details in a **payment form** on the merchant's website                                       | [API Only](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/recurring-payments/#api-only-integration)                                                   | `payment/create` + `payment/submit` with the card data                    |
| The customer pays with **Apple Pay or Google Pay** directly from the **checkout** of the merchant's website                | [API Only](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/recurring-payments/#api-only-integration)                                                   | `payment/create` + `payment/submit` with the wallet payload               |

> **Click to Pay**
>
> Click to Pay is available **with hosted integrations only**. Unlike Apple Pay and Google Pay, it does not require a dedicated payload and follows the same flow as the card.

> **Authentication always mandatory**
>
> The First **always** requires Strong Customer Authentication (SCA). Exemptions cannot be requested, regardless of the integration mode and of whether a token is available. With hosted integrations authentication is handled by Fabrick; with API Only the redirect to the customer's bank is the merchant's responsibility.

> **Mandatory notice to the buyer**
>
> The First involves the tokenization of the payment method: the buyer must be informed **before** the transaction is submitted.
>
> - With **hosted integrations** (Checkout Page, Pay By Link, Lightbox, Web Component) the notice is **already handled** by Fabrick and the message is shown automatically.
> - With a **custom payment page** (API Only) the notice is **the merchant's responsibility**.
>
> The messages shown by the hosted integrations are described in the [Tokenization](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/token/) section.

---

### Hosted integration

With hosted integrations the customer is shown the card and the enabled wallets. The `payment/create` call is enough: depending on the method chosen by the customer, the token to be used for the Next transactions is returned at the end of the payment.

#### Step 1 — Creating the request

Call `payment/create` on the server side, including:

- `requestToken` set to `MASKEDPAN`, to request tokenization
- `paymentType` set to `CREDITCARD`, to limit the page to the card and wallets

> **Card and wallets on the same page**
>
> With `paymentType` set to `CREDITCARD`, the page also shows **Apple Pay**, **Google Pay** and **Click to Pay**, if enabled on the shopLogin. The request does not change depending on the method: the customer chooses on the page, and the token returned matches the method used.

> **paymentChannel object**
>
> The examples use **Pay By Link**. With [Lightbox](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/integration-methods/lightbox/) or [Web Component](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/integration-methods/web-component/), remove the `paymentChannel` object from the call.

**Scheduled (01F)**

**Request**

```http
POST /api/v1/payment/create
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
Authorization: apikey ****************
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "amount": "0",
    "currency": "EUR",
    "shopTransactionID": "FBK-C01F_OrderID",
    "paymentChannel": { "channelType": ["LINK"] }, // Pay By Link only
    "paymentType": ["CREDITCARD"],
    "requestToken": "MASKEDPAN",
    "transDetails": {
        "type": "01F",
        "authenticationAmount": "100",
        "recurringTransaction": {
            "expiry": 20261231,
            "frequency": 15
        }
    }
}
```

**Unscheduled (03F)**

**Request**

```http
POST /api/v1/payment/create
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
Authorization: apikey ****************
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "amount": "0",
    "currency": "EUR",
    "shopTransactionID": "FBK-C03F_OrderID",
    "paymentChannel": { "channelType": ["LINK"] }, // Pay By Link only
    "paymentType": ["CREDITCARD"],
    "requestToken": "MASKEDPAN",
    "transDetails": {
        "type": "03F",
        "authenticationAmount": "100"
    }
}
```

#### Step 2 — Presenting the payment page

The `payment/create` response contains `paymentToken` and `paymentID`; with Pay By Link, the redirect link is returned in `payload.userRedirect.href`.

**Pay By Link**

Redirect the customer to the link in `payload.userRedirect.href`.

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "paymentToken": "8a901523-67a5-4aca-bbd2-c7c412934289",
        "paymentID": "1360119538182",
        "userRedirect": {
            "href": "https://sandbox-web.axerve.com/orchestra/checkout/a/dc1e181fe487435c86a09120550327a9/b/925e8ec8839a1baf2da2d49f5ecf87cf..."
        },
        "qrCode": null
    }
}
```

**Lightbox or Web Component**

Use `paymentToken` and `paymentID` in the [Lightbox](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/integration-methods/lightbox/) script or in the [Web Component](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/integration-methods/web-component/) to show the payment page.

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "paymentToken": "8a901523-67a5-4aca-bbd2-c7c412934289",
        "paymentID": "1360119538182",
        "userRedirect": null,
        "qrCode": null
    }
}
```

#### Step 3 — Payment outcome

At the end of the payment, the behaviour depends on the integration:

| Integration       | Behaviour                                                                                                                                                                                                                                                                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Pay By Link**   | The customer is redirected to the positive or negative outcome URL (see [Pay By Link](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/integration-methods/pay-by-link/#transaction-detail-and-payment-notification))                                                                    |
| **Web Component** | The customer is redirected to the positive or negative outcome URL (see [Web Component](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/integration-methods/web-component/#step-4--retrieve-the-outcome))                                                                               |
| **Lightbox**      | Automatic redirect to the positive or negative outcome URL or, if the callback object is used, URL available in the `responseURL` field (see [Lightbox](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/integration-methods/lightbox/#transaction-conclusion-and-payment-notification)) |

Continue with [checking the outcome and retrieving the token](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/recurring-payments/#checking-the-outcome-and-retrieving-the-token).

---

### API Only integration

With the API Only integration the merchant collects the payment details on their own page and sends them to Fabrick with `payment/submit`. Handling the redirect for authentication is the merchant's responsibility.

##### Step 1 — Creating the request

Call `payment/create` on the server side: the request is the same for card, Apple Pay and Google Pay. Click to Pay is not available with this integration.

> **When to use requestToken**
>
> Add `requestToken` set to `MASKEDPAN` only in `payment/create`, and only if in step 2 you send the card data or the Apple Pay or Google Pay payload.
>
> If the First uses an existing token instead, omit the field: the payment method is already tokenized and the same token is used for the Next transactions. If `requestToken` is present, `payment/submit` with the token returns the error:
>
> ```text
> 1107 - Unexpected parameter name. Please double check Fields and Parameters configuration in Back Office
> ```

**Scheduled (01F)**

**Request**

```http
POST /api/v1/payment/create
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
Authorization: apikey ****************
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "amount": "0",
    "currency": "EUR",
    "shopTransactionID": "FBK-C01F_OrderID",
    "requestToken": "MASKEDPAN", // Do not use if a token is used in the submit
    "transDetails": {
        "type": "01F",
        "authenticationAmount": "100",
        "recurringTransaction": {
            "expiry": 20261231,
            "frequency": 15
        }
    }
}
```

**Unscheduled (03F)**

**Request**

```http
POST /api/v1/payment/create
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
Authorization: apikey ****************
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "amount": "0",
    "currency": "EUR",
    "shopTransactionID": "FBK-C03F_OrderID",
    "requestToken": "MASKEDPAN", // Do not use if a token is used in the submit
    "transDetails": {
        "type": "03F",
        "authenticationAmount": "100"
    }
}
```

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "paymentToken": "8a901523-67a5-4aca-bbd2-c7c412934289",
        "paymentID": "1360119538182",
        "userRedirect": null,
        "qrCode": null
    }
}
```

The response contains `paymentToken`, to be used in the header of `payment/submit`, and `paymentID`, to be used to check the outcome and as the reference for the Next transactions.

#### Step 2 — Sending the payment details

Send the payment details with `payment/submit`, setting the `PaymentToken` header to the value received in the previous step. The body depends on the payment method and is the same for `01F` and `03F`.

**Tokenized card or wallet**

If the card or wallet has already been tokenized, send the token in the `paymentTypeDetails.creditcard.token` field: wallets are handled as cards. The call can be made on the server side, because no card data is transmitted.

In this case the `payment/create` in step 1 **must not contain** the `requestToken` field.

**Request**

```http
POST /api/v1/payment/submit
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
PaymentToken: 8a901523-67a5-4aca-bbd2-c7c412934289
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "paymentType": "CREDITCARD",
    "paymentTypeDetails": {
        "creditcard": {
            "token": "40ZUU8NXALR33101"
        }
    }
}
```

**Card data**

Send the card data in the `paymentTypeDetails.creditcard` object.

> **Card data security**
>
> Card data may pass through the merchant's server **only if that server is part of a PCI DSS compliant environment**, with compliance validated through an **AOC** (and, if required by the merchant level, a **ROC**).
>
> Without PCI DSS compliance, the data must be collected through a **form displayed in the buyer's session** and sent to Fabrick with `payment/submit` **on the client side**: in this way the card data never passes through the merchant's systems.

**Request**

```http
POST /api/v1/payment/submit
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
PaymentToken: 8a901523-67a5-4aca-bbd2-c7c412934289
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "paymentType": "CREDITCARD",
    "paymentTypeDetails": {
        "creditcard": {
            "number": "4012000000003101",
            "expMonth": "05",
            "expYear": "27",
            "CVV": "123"
        }
    }
}
```

**Apple Pay**

Send the payload returned by Apple Pay in the `paymentTypeDetails.applePay.PKPaymentToken` object.

**Request**

```http
POST /api/v1/payment/submit
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
PaymentToken: 8a901523-67a5-4aca-bbd2-c7c412934289
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "paymentType": "APPLEPAY",
    "paymentTypeDetails": {
        "applePay": {
            "PKPaymentToken": {
                "paymentData": {
                    "data": "***",
                    "signature": "***",
                    "header": {
                        "publicKeyHash": "***",
                        "ephemeralPublicKey": "***",
                        "transactionId": "***"
                    },
                    "version": "EC_v1"
                },
                "paymentMethod": {
                    "displayName": "Visa 2237",
                    "network": "Visa",
                    "type": "debit"
                },
                "transactionIdentifier": "***"
            }
        }
    }
}
```

**Alternative format: payload as a string**

Instead of the object, the payload can be sent as a serialised JSON string in the `paymentTypeDetails.applePay.applePayPKPaymentToken` field.

```json
{
    "shopLogin": "GESPAY12345",
    "paymentType": "APPLEPAY",
    "paymentTypeDetails": {
        "applePay": {
            "applePayPKPaymentToken": "{\"transactionIdentifier\":\"***\",\"paymentMethod\":{\"displayName\":\"Visa 4915\",\"type\":\"debit\",\"network\":\"visa\"},\"paymentData\":{\"data\":\"***\",\"signature\":\"***\",\"header\":{\"publicKeyHash\":\"***\",\"ephemeralPublicKey\":\"***\",\"transactionId\":\"***\"},\"version\":\"EC_v1\"}}"
        }
    }
}
```

**Google Pay**

Send the payload returned by Google Pay in the `paymentTypeDetails.googlePay.tokenizationData` object.

**Request**

```http
POST /api/v1/payment/submit
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
PaymentToken: 8a901523-67a5-4aca-bbd2-c7c412934289
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "paymentType": "GOOGLEPAY",
    "paymentTypeDetails": {
        "googlePay": {
            "tokenizationData": {
                "token": {
                    "signature": "***",
                    "protocolVersion": "ECv1",
                    "signedMessage": "{\"encryptedMessage\":\"***\",\"ephemeralPublicKey\":\"***\",\"tag\":\"***\"}"
                }
            }
        }
    }
}
```

#### Step 3 — Handling the response

The `payment/submit` response can present three scenarios:

**Authentication required**

The `transactionErrorCode` field returns `8006`: you must redirect the customer to their bank's authentication page, using the link in `payload.userRedirect.href`.

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "transactionErrorCode": "8006",
        "transactionErrorDescription": "Verify By Visa",
        "paymentID": "1360119538182",
        "userRedirect": {
            "href": "https://sandbox.gestpay.net/pagam/pagam3d.aspx?a=GESPAY12345&b=8a901523-67a5-4aca-bbd2-c7c412934289&axerve3D=True&IsLightBox=False"
        }
    }
}
```

**Immediate outcome**

If authentication is not required, the outcome is returned **immediately**, together with the token in the `payload.token` field. The outcome URL defined by the merchant is available in `payload.userRedirect.href`.

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "transactionType": "submit",
        "transactionResult": "OK",
        "transactionErrorCode": "0",
        "transactionErrorDescription": "Transaction correctly processed",
        "bankTransactionID": "492",
        "shopTransactionID": "FBK-C01F_OrderID",
        "authorizationCode": "188190",
        "paymentID": "1360119538182",
        "currency": "EUR",
        "country": "ITALIA",
        "company": "VISA",
        "productType": "Credit",
        "token": "40ZUU8NXALR33101",
        "tokenExpiryMonth": "05",
        "tokenExpiryYear": "27",
        "userRedirect": {
            "href": "https://sandbox.gestpay.net/pagam/AxerveThankYou.aspx"
        }
    }
}
```

**Error**

The response contains the `error` object with the code in `error.code` and the description in `error.description`. See the [full list of errors](https://api.paymentorchestra.fabrick.com/#errors).

**Response**

```json
{
    "error": {
        "code": "1165",
        "description": "Token not found"
    },
    "payload": {}
}
```

---

### Checking the outcome and retrieving the token

At the end of the payment the system sends a **server-to-server (S2S) notification** with the outcome and the `paymentToken` and `paymentID` values, together with any redirect of the customer. The notification lets you update the payment status even if the customer does not return to the website.

```text
https://merchant-url.com?a=GESPAY12345&Status=OK&paymentID=1360119538182&paymentToken=8a901523-67a5-4aca-bbd2-c7c412934289
```

Use `payment/detail` to check the outcome and retrieve the token, of the card or of the wallet, in the **`payload.token`** field. For more information about the token, you can read the `payload.tokenDetails` object, which returns the same value in `TokenValue` together with the expiry date and last digits of the card (`CardDetails`).

**Response details**

**Request**

```http
GET /api/v1/payment/detail/{paymentID}
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
Authorization: apikey ****************
Content-Type: application/json
```

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "transactionType": "detail",
        "transactionResult": "APPROVED",
        "transactionState": "AUT",
        "transactionErrorCode": "0",
        "transactionErrorDescription": "Transaction correctly processed",
        "bankTransactionID": "492",
        "shopTransactionID": "FBK-C01F_OrderID",
        "shopTransactionID_2": "",
        "authorizationCode": "188190",
        "paymentID": "1360119538182",
        "currency": "EUR",
        "country": "ITALIA",
        "company": "VISA",
        "tdLevel": "FULL",
        "threeDS": {
            "authenticationResult": {
                "authenticationLevel": "2C",
                "authenticationStatus": "Y",
                "authStatusReason": "",
                "challengeResultTransStatus": "",
                "XID": "12e6e4ce-8ccc-49f9-b5a4-18b486f1d29d",
                "AV": "MTIzNDU2Nzg5MDA5ODc2NTQzMjE=",
                "ECI": "05",
                "AVAlgorithm": "",
                "threeDsVersion": "2.1.0"
            },
            "transDetails": {
                "authData": "",
                "authMethod": "02",
                "authTimeStamp": "202407111313",
                "acsID": "48a413bf-fe27-4de2-a39e-dc6039e4aef7"
            }
        },
        "events": [
            {
                "event": {
                    "eventtype": "AUT",
                    "eventamount": "0.00",
                    "eventdate": "11/07/24 13:13:56",
                    "eventARN": "",
                    "eventID": "",
                    "eventReferred": ""
                }
            }
        ],
        "buyer": {
            "name": "",
            "email": ""
        },
        "risk": {
            "riskResponseCode": "",
            "riskResponseDescription": ""
        },
        "customInfo": null,
        "alertCode": "",
        "alertDescription": "",
        "cvvPresent": "TRUE",
        "dcc": null,
        "maskedPAN": "",
        "paymentMethod": "VISA",
        "productType": "Credit",
        "token": "40ZUU8NXALR33101",
        "tokenExpiryMonth": "05",
        "tokenExpiryYear": "27",
        "tokenDetails": {
            "TokenValue": "40ZUU8NXALR33101",
            "TokenExpiryMonth": "05",
            "TokenExpiryYear": "27",
            "TokenProvider": "AXERVE",
            "CardDetails": {
                "CardSuffix": "3101",
                "CardExpiryMonth": "05",
                "CardExpiryYear": "27",
                "CardHolderName": null
            },
            "CardAssets": {
                "CardArt": {
                    "Type": null,
                    "MediaContents": null,
                    "Height": null,
                    "Width": null
                },
                "BrandLogo": {
                    "Type": null,
                    "MediaContents": null,
                    "Height": null,
                    "Width": null
                }
            }
        },
        "fraudPrevention": {
            "check": "FALSE",
            "state": "",
            "description": "",
            "order": ""
        },
        "automaticOperation": {
            "type": "CAN",
            "date": "05/08/24 00:00:00",
            "amount": "0"
        }
    }
}
```

#### Data to store for the Next transactions

| Data                   | Where to find it                                                            | Type         | Use in the Next transactions                         |
| ---------------------- | --------------------------------------------------------------------------- | ------------ | ---------------------------------------------------- |
| `paymentID`            | `payment/create` response                                                   | `01F`, `03F` | `transDetails.previousTransDetails.paymentID`        |
| `token`                | `payment/detail` → `payload.token`, or the existing token used in the First | `01F`, `03F` | `paymentTypeDetails.creditcard.token`                |
| `authenticationAmount` | Value sent in the First                                                     | `01F`, `03F` | Maximum amount that can be charged                   |
| `expiry`               | Value sent in the First                                                     | `01F`        | Date after which no Next may be processed            |
| `frequency`            | Value sent in the First                                                     | `01F`        | Minimum number of days between two Next transactions |

> **paymentID**
>
> Fabrick returns the `paymentID` in the response to the `payment/create` call. If the transaction is successful, this value becomes the identifier to use as the reference for the Next transactions. To charge a different payment method, a new First must be processed.

> **Token management**
>
> For more information on managing the token, see the [Tokenization](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/token/) section.

---

### After the First: capture, refund and cancellation

Once the First is completed and the required data stored, you can **capture** or **refund** the authorised amount.

| Case                                                          | Behaviour                                                                                                                                                                    |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **First with a €0.00 amount (ASI)**                           | The system does not allow cancellation: it would break the chain and prevent the Next transactions                                                                           |
| **First with an amount greater than zero and separated MOTO** | Do not cancel the transaction through `payment/cancel` or the Dashboard. To refund the customer, capture the full amount and then process a refund: the chain remains active |

> **Never cancel the First**
>
> Cancelling the First, through the `payment/cancel` API or the Dashboard, makes it impossible to process the Next transactions.

---

## Next flow (MIT)

Next transactions are the **payments that follow** the First and are processed on the basis of the authorisation given during the First. They are processed without the customer being present and do not require the payment page to be shown or any interaction on their part.

Next transactions are not processed automatically by Fabrick: the merchant must **schedule, initiate and manage** each charge, in accordance with the contractual agreements.

> **Same flow for card and wallets**
>
> The Next flow is identical for card, Apple Pay, Google Pay and Click to Pay: wallets are handled as cards, so in all cases the token obtained during the First is used, sent in the `paymentTypeDetails.creditcard.token` field.

### Request fields

| Call             | Field                                         | Description                                |
| ---------------- | --------------------------------------------- | ------------------------------------------ |
| `payment/create` | `transDetails.type`                           | `01N` for scheduled, `03N` for unscheduled |
| `payment/create` | `transDetails.previousTransDetails.paymentID` | `paymentID` of the First                   |
| `payment/submit` | `paymentTypeDetails.creditcard.token`         | Token obtained during the First            |

> **shopLogin of the First**
>
> The `paymentID` of the First is valid **only** on the shopLogin on which it was generated: a Next submitted on another shopLogin cannot be processed.
>
> To collect the recurring payments on another shopLogin, you must **generate a new authenticated First on the new shopLogin** and use its `paymentID` for all the following Next transactions.

### Step 1 — Creating the request

Call `payment/create` on the server side, specifying the reference to the First.

**Scheduled (01N)**

**Request**

```http
POST /api/v1/payment/create
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
Authorization: apikey ****************
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "amount": "100",
    "currency": "EUR",
    "shopTransactionID": "FBK-C01N_OrderID",
    "transDetails": {
        "type": "01N",
        "previousTransDetails": {
            "paymentID": "1360119538182"
        }
    }
}
```

**Unscheduled (03N)**

**Request**

```http
POST /api/v1/payment/create
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
Authorization: apikey ****************
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "amount": "100",
    "currency": "EUR",
    "shopTransactionID": "FBK-C03N_OrderID",
    "transDetails": {
        "type": "03N",
        "previousTransDetails": {
            "paymentID": "1360119538182"
        }
    }
}
```

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "paymentToken": "7ebd948a-c9ad-44c9-ac43-02b0beb55a7a",
        "paymentID": "1541109548247",
        "userRedirect": null,
        "qrCode": null
    }
}
```

### Step 2 — Sending the token

Call `payment/submit` on the server side, sending the token obtained during the First. The request is the same for `01N` and `03N`.

**Request**

```http
POST /api/v1/payment/submit
Host (sandbox): sandbox.gestpay.net
Host (production): ecomms2s.sella.it
PaymentToken: 7ebd948a-c9ad-44c9-ac43-02b0beb55a7a
Content-Type: application/json
```

```json
{
    "shopLogin": "GESPAY12345",
    "paymentType": "CREDITCARD",
    "paymentTypeDetails": {
        "creditcard": {
            "token": "40ZUU8NXALR33101"
        }
    }
}
```

### Step 3 — Handling the response

The outcome of the Next is returned **immediately** in the `payment/submit` response and, at the same time, through the S2S notification. You can optionally query the transaction with `payment/detail`: the response structure is the same as shown for the [First](https://docs.fabrick.com/en/payment-hub-and-orchestra/ecommerce/features/recurring-payments/#checking-the-outcome-and-retrieving-the-token).

**Positive outcome**

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "transactionType": "submit",
        "transactionResult": "OK",
        "transactionErrorCode": "0",
        "transactionErrorDescription": "Transaction correctly processed",
        "bankTransactionID": "569",
        "shopTransactionID": "FBK-C01N_OrderID",
        "authorizationCode": "188190",
        "paymentID": "1541109548247",
        "currency": "EUR",
        "country": "ITALIA",
        "company": "VISA",
        "productType": "Credit",
        "userRedirect": {
            "href": "https://sandbox.gestpay.net/pagam/AxerveThankYou.aspx"
        }
    }
}
```

**New authentication required**

In exceptional cases the customer's bank may require a new authentication: the `transactionErrorCode` field returns `8026` (*Soft Decline*). This scenario can occur with **any payment method**, card or wallet, and must therefore always be handled.

You must **contact the customer** and initialise a **new First**, to obtain a new `paymentID` to use for the following Next transactions.

**Response**

```json
{
    "error": {
        "code": "0",
        "description": "request correctly processed"
    },
    "payload": {
        "transactionType": "submit",
        "transactionResult": "KO",
        "transactionErrorCode": "8026",
        "transactionErrorDescription": "Soft decline - Cardholder authentication required",
        "bankTransactionID": "569",
        "shopTransactionID": "FBK-C01N_OrderID",
        "authorizationCode": "",
        "paymentID": "1541109548247",
        "currency": "EUR",
        "country": "ITALIA",
        "company": "VISA",
        "productType": "Credit",
        "userRedirect": {
            "href": "https://sandbox.gestpay.net/pagam/AxerveThankYou.aspx"
        }
    }
}
```

**Error**

The response contains the `error` object with the code in `error.code` and the description in `error.description`. See the [full list of errors](https://api.paymentorchestra.fabrick.com/#errors).

**Response**

```json
{
    "error": {
        "code": "1165",
        "description": "Token not found"
    },
    "payload": {}
}
```

Once the positive outcome is confirmed, you can **capture** or **refund** the transaction.
