# Financing & installments

> Retrieve installment and pay-later financing options for a payment, then simulate a specific plan to get the per-installment amount, total cost, and fees.

Financing lets a contact pay over time instead of all at once. Qualy supports two financing providers: **PagBank** for Brazilian credit-card installments (_parcelamento_), and **Klarna** for pay-later and pay-over-time options in supported regions.

Working with financing is a two-step flow:

1. **Retrieve options** — find out which financing types are available for an amount or Payment Intent, and the maximum number of installments.
2. **Simulate a plan** — pick a number of installments and get the exact per-installment amount, the total with interest, and the fees.

> **Note — Amounts are in cents**
>
> Every monetary value in these endpoints is an integer in minor currency units (cents). `5000` means `R$ 50.00`. Rates such as `feePercentage` and `interestRate` are decimals — `0.0405` means `4.05%`.

---

## Gateways & methods

Each request must name the `gateway` and its financing `method`. The valid combinations are:

| Gateway | `gateway` | `method` | Region | Financing types | Simulate? |
| --- | --- | --- | --- | --- | --- |
| PagBank | `pagbank` | `PGBNK_CC` | Brazil (BRL only) | `installments` (up to 18x) | Yes |
| Klarna | `klarna` | `KLARNA_PYMT` | Klarna-supported regions | `pay-later`, `installments` (4x) | No |

---

## Retrieving financing options

Call `POST /v1/payment-gateways/financing/options` to see what is available. You can describe the amount in one of two ways:

- Pass a `paymentIntent` ID — Qualy uses the Payment Intent's outstanding `due` amount.
- Pass an `amount` and `currency` directly — useful before a Payment Intent exists (e.g. on a checkout page).

> **Note — Klarna requires a Payment Intent**
>
> The `amount` + `currency` shortcut works only with PagBank. Klarna always needs a `paymentIntent`, since available categories depend on the payer's country and the settlement currency.

### Request fields

| Field | Required | Description |
| --- | --- | --- |
| `gateway` | Yes | `pagbank` or `klarna`. |
| `method` | Yes | `PGBNK_CC` for PagBank, `KLARNA_PYMT` for Klarna. |
| `paymentIntent` | Conditional | A Payment Intent ID. Required when `amount`/`currency` are omitted, and always required for Klarna. |
| `amount` | Conditional | Amount to finance, in cents. Required (with `currency`) when `paymentIntent` is omitted. PagBank only. |
| `currency` | Conditional | ISO 4217 currency code. Must be `BRL` for PagBank. Required when `paymentIntent` is omitted. |

### Example (PagBank)

**cURL**

```bash
curl -X POST https://api.qualyhq.com/v1/payment-gateways/financing/options \
  -H 'Authorization: ApiKey your-api-key-here' \
  -H 'X-TENANT-ID: your-tenant-id-here' \
  -H 'Content-Type: application/json' \
  -d '{
    "gateway": "pagbank",
    "method": "PGBNK_CC",
    "amount": 135000,
    "currency": "BRL"
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  'https://api.qualyhq.com/v1/payment-gateways/financing/options',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'ApiKey your-api-key-here',
      'X-TENANT-ID': 'your-tenant-id-here',
    },
    body: JSON.stringify({
      gateway: 'pagbank',
      method: 'PGBNK_CC',
      amount: 135000, // R$ 1,350.00
      currency: 'BRL',
    }),
  },
);

const { data } = await res.json();
console.log(data.options);
```

**PHP (Laravel)**

```php
use Illuminate\Support\Facades\Http;

$data = Http::withHeaders([
    'Authorization' => 'ApiKey your-api-key-here',
    'X-TENANT-ID' => 'your-tenant-id-here',
])->post('https://api.qualyhq.com/v1/payment-gateways/financing/options', [
    'gateway' => 'pagbank',
    'method' => 'PGBNK_CC',
    'amount' => 135000, // R$ 1,350.00
    'currency' => 'BRL',
])->json('data');

print_r($data['options']);
```

The response lists the available financing types. For PagBank, `nInstallments` is the **maximum** number of installments the buyer can choose from (1 up to this value):

```json
{
  "data": {
    "options": [
      {
        "type": "installments",
        "amount": 135000,
        "currency": "BRL",
        "nInstallments": 12
      }
    ]
  }
}
```

> **Note — Minimum amount**
>
> PagBank only offers multiple installments above `R$ 20.00` (`2000` cents). Below that, the response returns a single option with `nInstallments: 1`.

### Example (Klarna)

**cURL**

```bash
curl -X POST https://api.qualyhq.com/v1/payment-gateways/financing/options \
  -H 'Authorization: ApiKey your-api-key-here' \
  -H 'X-TENANT-ID: your-tenant-id-here' \
  -H 'Content-Type: application/json' \
  -d '{
    "gateway": "klarna",
    "method": "KLARNA_PYMT",
    "paymentIntent": "6634f56c7dbbc16e07b5025e"
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  'https://api.qualyhq.com/v1/payment-gateways/financing/options',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'ApiKey your-api-key-here',
      'X-TENANT-ID': 'your-tenant-id-here',
    },
    body: JSON.stringify({
      gateway: 'klarna',
      method: 'KLARNA_PYMT',
      paymentIntent: '6634f56c7dbbc16e07b5025e',
    }),
  },
);

const { data } = await res.json();
console.log(data.options);
```

**PHP (Laravel)**

```php
use Illuminate\Support\Facades\Http;

$data = Http::withHeaders([
    'Authorization' => 'ApiKey your-api-key-here',
    'X-TENANT-ID' => 'your-tenant-id-here',
])->post('https://api.qualyhq.com/v1/payment-gateways/financing/options', [
    'gateway' => 'klarna',
    'method' => 'KLARNA_PYMT',
    'paymentIntent' => '6634f56c7dbbc16e07b5025e',
])->json('data');

print_r($data['options']);
```

Klarna returns one entry per available category. `pay-later` settles the full amount on a later date; `installments` splits it into four payments:

```json
{
  "data": {
    "options": [
      { "type": "pay-later", "amount": 135000, "currency": "AUD" },
      { "type": "installments", "amount": 135000, "currency": "AUD", "nInstallments": 4 }
    ]
  }
}
```

### Option fields

| Field | Description |
| --- | --- |
| `type` | `installments` (pay in parts) or `pay-later` (pay the full amount later). |
| `amount` | The amount being financed, in cents. |
| `currency` | The settlement currency the contact pays in. |
| `nInstallments` | For PagBank, the maximum number of installments available. For Klarna `installments`, the fixed count (4). Absent for `pay-later`. |

---

## Simulating a plan

Once you know the maximum number of installments, call `POST /v1/payment-gateways/financing/simulate` with a specific `nInstallments` to get the exact cost breakdown.

> **Warning — PagBank only**
>
> Simulation is supported for PagBank (`PGBNK_CC`) only. Klarna calculates and presents its own plans at checkout, so there is no simulate step for Klarna.

Each simulation is **persisted** and returns an `_id`. Keep this ID — it is the reference to the chosen plan and appears on the resulting transaction's financing details.

### Request fields

Same as the options endpoint, plus a required `nInstallments`:

| Field | Required | Description |
| --- | --- | --- |
| `gateway` | Yes | Must be `pagbank`. |
| `method` | Yes | Must be `PGBNK_CC`. |
| `nInstallments` | Yes | The number of installments to simulate (minimum `1`). Must be within the maximum returned by the options endpoint. |
| `paymentIntent` | Conditional | A Payment Intent ID. Required when `amount`/`currency` are omitted. |
| `amount` | Conditional | Amount to finance, in cents. Required (with `currency`) when `paymentIntent` is omitted. |
| `currency` | Conditional | Must be `BRL`. Required when `paymentIntent` is omitted. |

### Example

**cURL**

```bash
curl -X POST https://api.qualyhq.com/v1/payment-gateways/financing/simulate \
  -H 'Authorization: ApiKey your-api-key-here' \
  -H 'X-TENANT-ID: your-tenant-id-here' \
  -H 'Content-Type: application/json' \
  -d '{
    "gateway": "pagbank",
    "method": "PGBNK_CC",
    "amount": 135000,
    "currency": "BRL",
    "nInstallments": 12
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  'https://api.qualyhq.com/v1/payment-gateways/financing/simulate',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'ApiKey your-api-key-here',
      'X-TENANT-ID': 'your-tenant-id-here',
    },
    body: JSON.stringify({
      gateway: 'pagbank',
      method: 'PGBNK_CC',
      amount: 135000, // R$ 1,350.00
      currency: 'BRL',
      nInstallments: 12,
    }),
  },
);

const { data } = await res.json();
console.log(data);
```

**PHP (Laravel)**

```php
use Illuminate\Support\Facades\Http;

$data = Http::withHeaders([
    'Authorization' => 'ApiKey your-api-key-here',
    'X-TENANT-ID' => 'your-tenant-id-here',
])->post('https://api.qualyhq.com/v1/payment-gateways/financing/simulate', [
    'gateway' => 'pagbank',
    'method' => 'PGBNK_CC',
    'amount' => 135000, // R$ 1,350.00
    'currency' => 'BRL',
    'nInstallments' => 12,
])->json('data');

print_r($data);
```

### Response

```json
{
  "data": {
    "_id": "6634f8a17dbbc16e07b50312",
    "total": 153090,
    "currency": "BRL",
    "method": "PGBNK_CC",
    "nInstallments": 12,
    "installmentAmount": 12758,
    "feePercentage": 0.1340,
    "interestRate": 0.1182
  }
}
```

| Field | Description |
| --- | --- |
| `_id` | The persisted simulation ID. Reference this plan when collecting the payment; it also appears on the transaction's financing details. |
| `total` | Total amount the contact pays across all installments, in cents (original amount + interest + fees). |
| `installmentAmount` | The amount of each individual installment, in cents. `total ÷ nInstallments`, with each installment rounded up to the cent. |
| `nInstallments` | The number of installments simulated. |
| `feePercentage` | The **effective uplift** over the original amount: `(total − amount) / amount`. This is the number to show the buyer as the real cost of financing. |
| `interestRate` | The raw provider rate used to build the plan. Usually lower than `feePercentage` (see below). |
| `currency` | The currency of the plan (`BRL`). |
| `paymentIntent` | Echoed back when the simulation was created from a Payment Intent. |
| `operationFee` | An optional fixed operation fee, in cents, when applicable. |

> **Note — feePercentage vs. interestRate**
>
> `interestRate` is the raw, fee-on-total rate PagBank applies internally (`total = (amount + flat fee) / (1 − rate)`). `feePercentage` is the effective increase the buyer actually pays versus the original amount — it is higher because it also includes a flat per-transaction fee and per-installment cent rounding. **Show `feePercentage` to the buyer** as the true cost of paying in installments.

---

## Partial amounts

When financing against a Payment Intent, you can finance less than the full `due` by also passing an `amount` (in cents). Qualy clamps it to the outstanding amount so the contact is never overcharged. Omit `amount` to finance the full balance.

---

## Cross-currency financing

A Payment Intent can be denominated in one currency (say `AUD`) while the contact pays in another. PagBank financing always settles in **BRL**, so when you finance an `AUD` Payment Intent:

- The Payment Intent's settlement currency must resolve to `BRL`.
- A locked FX quote must exist on the Payment Intent — Qualy converts the `due` to BRL at that rate before building the plan.

If the settlement currency is not BRL, or no FX quote is available, the request is rejected. See [Collecting payments](/docs/guides/collecting-payments.md#understanding-currency-vs-settlement-currency) for how settlement currency is determined.

---

## Next steps

After simulating a plan, collect the payment using the chosen financing method. See [Collecting payments](/docs/guides/collecting-payments.md) for the sign flow, and [Setting up webhooks](/docs/webhooks.md) to be notified when each installment is captured.
