---
url: /docs/fiat/payin-quotes.md
description: >-
  Lock the fiat amount, fee split, and stablecoin destination for a bank deposit
  before creating a payin.
---

A payin quote locks in the numbers for a bank deposit before you commit to it: how much fiat the sender pays, how much the customer receives, the fee split, and the destination that settles the funds. You create a payin quote first, then create the [payin](/fiat/payins) itself by referencing the quote's id. The quote is what actually enforces amount limits, currency rules, and payer requirements, so most of the validation work happens here rather than at payin creation.

## How it works

A payin quote is a single call: pass the amount, the payment method, the fee setting, and the destination. BlindPay returns the locked-in fiat and stablecoin amounts plus the payment instructions for that method. The quote expires in 5 minutes, so create the payin shortly after.

```
payin quote -> payin (create within 5 minutes)
```

### Destination

The destination is a stablecoin delivery target, not a bank account. Pass exactly one of:

| Field | Points to | Prefix |
| --- | --- | --- |
| `blockchain_wallet_id` | An external blockchain wallet the customer controls | `bw_` |
| `wallet_id` | A BlindPay-managed wallet | `bl_` |

You cannot pass both, and you cannot pass neither. The stablecoin mechanics behind this destination are covered in [on-ramp](/stablecoin/receive); as a bank-rails integration you can treat it as an implementation detail.

### currency\_type

`currency_type` tells BlindPay which side `request_amount` is denominated in. On a payin quote, this is the opposite convention from a payout quote, so read it carefully:

| `currency_type` | `request_amount` is denominated in |
| --- | --- |
| `sender` | The fiat currency the sender sends (determined by `payment_method`) |
| `receiver` | The stablecoin the customer receives |

### cover\_fees

Fees can be paid by either party:

| `cover_fees` | Who pays | Fee is deducted from |
| --- | --- | --- |
| `false` | The customer | The stablecoin amount the customer receives (most common) |
| `true` | The sender | Added on top of the fiat amount the sender sends |

### request\_amount

`request_amount` is an integer in minor units and does not accept floats. To send `$123.45`, pass `12345`.

Minimum and maximum amounts vary by currency, and the quote enforces them for you: if `request_amount` is outside the allowed range for that currency, the quote request fails with a dynamic error naming the min and max. Most currencies allow amounts as low as roughly $10 equivalent, but some (for example COP) require a much higher minimum in raw minor units because of the currency's smaller nominal value. Don't hardcode a single minimum across currencies; read the error if you hit the floor.

## Prerequisites

You also need a customer with a blockchain wallet or a virtual account.

## Create a payin quote

```bash [🇺🇸 ACH]
curl https://api.blindpay.com/v1/instances/in_000000000000/payin-quotes \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "blockchain_wallet_id": "bw_000000000000",
  "currency_type": "sender",
  "cover_fees": true,
  "request_amount": 10000,
  "payment_method": "ach",
  "token": "USDB"
}'
```

```bash [🇺🇸 Wire]
curl https://api.blindpay.com/v1/instances/in_000000000000/payin-quotes \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "blockchain_wallet_id": "bw_000000000000",
  "currency_type": "sender",
  "cover_fees": true,
  "request_amount": 10000,
  "payment_method": "wire",
  "token": "USDB"
}'
```

```bash [🇧🇷 Pix]
curl https://api.blindpay.com/v1/instances/in_000000000000/payin-quotes \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "blockchain_wallet_id": "bw_000000000000",
  "currency_type": "sender",
  "cover_fees": false,
  "request_amount": 10000,
  "payment_method": "pix",
  "token": "USDB",
  "payer_rules": {
    "pix_allowed_tax_ids": [
      "14747677786"
    ]
  }
}'
```

```bash [🇲🇽 SPEI]
curl https://api.blindpay.com/v1/instances/in_000000000000/payin-quotes \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "blockchain_wallet_id": "bw_000000000000",
  "currency_type": "sender",
  "cover_fees": false,
  "request_amount": 100000,
  "payment_method": "spei",
  "token": "USDB"
}'
```

```bash [🇦🇷 Transfers]
curl https://api.blindpay.com/v1/instances/in_000000000000/payin-quotes \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "blockchain_wallet_id": "bw_000000000000",
  "currency_type": "sender",
  "cover_fees": false,
  "request_amount": 2000000,
  "payment_method": "transfers",
  "token": "USDB",
  "payer_rules": {
    "transfers_allowed_tax_id": "30-27383762-7"
  }
}'
```

```bash [🇨🇴 PSE]
curl https://api.blindpay.com/v1/instances/in_000000000000/payin-quotes \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "blockchain_wallet_id": "bw_000000000000",
  "currency_type": "sender",
  "cover_fees": false,
  "request_amount": 20000000,
  "payment_method": "pse",
  "token": "USDB",
  "payer_rules": {
    "pse_full_name": "<Replace with payer full name>",
    "pse_document_type": "NIT",
    "pse_document_number": "<Replace with payer document number>",
    "pse_email": "<Replace with payer email>",
    "pse_phone": "<Replace with payer phone number>",
    "pse_bank_code": "<Replace with payer bank code>"
  }
}'
```

### payer\_rules

Some payment methods require payer identity fields so BlindPay can match and screen the incoming deposit:

| `payment_method` | `payer_rules` field | Notes |
| --- | --- | --- |
| `pix` | `pix_allowed_tax_ids` | Array of CPF/CNPJ tax ids allowed to send this Pix |
| `transfers` | `transfers_allowed_tax_id` | CUIT/CUIL tax id, required for `transfers` |
| `pse` | `pse_full_name`, `pse_document_type`, `pse_document_number`, `pse_email`, `pse_phone`, `pse_bank_code` | Full payer details, required for `pse` |

## Response

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string (`qu_`) | Pass this as `payin_quote_id` when creating the payin |
| `expires_at` | number | Epoch milliseconds. The quote is valid for 5 minutes |
| `sender_amount` | number | Fiat amount, in minor units, the sender must pay |
| `receiver_amount` | number | Stablecoin amount the destination wallet receives |
| `commercial_quotation` | number | Raw market exchange rate |
| `blindpay_quotation` | number | Exchange rate including BlindPay's fee |
| `flat_fee` | number | Flat-fee component of the quote |
| `partner_fee_amount` | number | Nonzero only when `partner_fee_id` is set |

Show the payer whichever field is relevant to their payment method once you create the payin: `memo_code` and `blindpay_bank_details` for `ach`/`wire`, `pix_code` for `pix`, a CLABE for `spei`, a CBU for `transfers`, or a payment link for `pse`. Those fields live on the [payin](/fiat/payins) response, not the quote.

## Expiry

A payin quote expires **5 minutes** after creation. Create the payin before then; an expired quote is rejected when you try to use it. Generate a new quote if the window has passed.

## Partner fees

Pass `partner_fee_id` (prefix `pf_`) to attribute a payin to a partner fee configured in the dashboard. The fee is snapshotted at quote time and reflected in `partner_fee_amount` on the response. See [partner fees](/learn/partner-fees) for how the fee is calculated and collected.

## Testing

On development instances, the amount you request determines the outcome once the resulting payin is created:

| Amount | Result |
| --- | --- |
| 666.00 | Failed |
| 777.00 | Refunded |
| Any other amount | Completes automatically, about 30 seconds after initiation |

## Related

* [Payins](/fiat/payins): create the payin from a quote and track it to completion
* [Virtual accounts](/fiat/virtual-accounts): an alternative destination that skips the memo-code flow
* [On-ramp](/stablecoin/receive): the stablecoin-delivery mechanics behind a payin quote
* [Partner fees](/learn/partner-fees): how `partner_fee_id` is calculated and paid out
* [Cut-off times](/kb/cut-off-times): settlement windows by payment method
