> For the complete documentation index, see [llms.txt](https://docs.fonbnk.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fonbnk.com/server-to-server/api-endpoints/create-quote.md).

# Create quote

## <mark style="color:$warning;">\[POST]</mark> /api/v2/quote

Generates a quote you can create an order from. A quote locks the exchange rate and the fees, and — just as important — tells you exactly which fields to collect from the user before you can create the order.

### Request

```typescript
type RequestBody = {
  deposit: {
    paymentChannel: PaymentChannel;
    currencyType: CurrencyType;
    currencyCode: string;
    countryIsoCode?: string;      // required if currencyType is fiat
    carrierCode?: string;         // mobile money / airtime
    amount?: number;
    transferType?: TransferType;  // pin the transfer type when a channel offers several
  };
  payout: {
    paymentChannel: PaymentChannel;
    currencyType: CurrencyType;
    currencyCode: string;
    countryIsoCode?: string;      // required if currencyType is fiat
    carrierCode?: string;
    amount?: number;
  };
};
```

{% hint style="warning" %}
**Set exactly one amount.** Provide either `deposit.amount` or `payout.amount`, never both and never neither — the other leg is what the quote computes for you. Sending both, or none, is rejected with `400`.

Both objects are strict — an unknown key is rejected rather than ignored.
{% endhint %}

`deposit.transferType` is optional and most integrations never set it: as things stand, every live production channel exposes exactly one deposit transfer type, so leaving it out gives you that one. It matters in two cases — when a channel does have offers of more than one live type and you want a particular one, and to reach an offer that is only available through a quote. `otp_stk_push` on Kenyan mobile money is the second case: it sits on a single offer that is hidden from ordinary offer search, so a quote pinning the transfer type is the only way to it.

{% hint style="warning" %}
**Pinning a transfer type narrows the search and can leave nothing.** A channel's `transferTypes` on [Get available currencies](/server-to-server/api-endpoints/get-available-currencies.md) is collected from every offer, switched-off ones included, so a type listed there is not necessarily one you can buy. South African bank is the trap: its `transferTypes` mentions `manual`, but the only live South African bank offer is a `redirect` one, so pinning `manual` finds no offer. Read `transferTypes` for what to show, and let the quote confirm — or leave `transferType` out and let us choose.
{% endhint %}

Request body example:

```json
{
    "deposit": {
        "paymentChannel": "bank",
        "currencyType": "fiat",
        "currencyCode": "NGN",
        "countryIsoCode": "NG",
        "amount": 10000
    },
    "payout": {
        "paymentChannel": "crypto",
        "currencyType": "crypto",
        "currencyCode": "POLYGON_USDT"
    }
}
```

{% hint style="info" %}
This endpoint is open to every account. The create-users permission that [Create order](/server-to-server/api-endpoints/create-order.md) needs is not checked here, so a quote succeeding does not prove you can create the order — see the warning on that page.
{% endhint %}

### Response

{% code overflow="wrap" expandable="true" %}

```typescript
type Response = {
  quoteId: string;
  quoteExpiresAt: Date;
  deposit: {
    paymentChannel: PaymentChannel;
    currencyType: CurrencyType;
    currencyCode: string;
    currencyDetails: OrderCurrencyDetails;
    cashout: Cashout;
    fieldsToCreateOrder: RequiredField[];
    transferType: TransferType;
  },
  payout: {
    paymentChannel: PaymentChannel;
    currencyType: CurrencyType;
    currencyCode: string;
    currencyDetails: OrderCurrencyDetails;
    cashout: Cashout;
    fieldsToCreateOrder: RequiredField[];
  }
}
```

{% endcode %}

How to read it:

* `deposit.cashout.amountBeforeFees` is what the user pays in; `payout.cashout.amountAfterFees` is what they get out. `Cashout` also breaks out every fee and its recipient — see [Types](/server-to-server/types.md).
* `fieldsToCreateOrder` on **both** legs is the source of truth for your form. Collect every field marked `required`, then send them as one flat `fieldsToCreateOrder` object to [Create order](/server-to-server/api-endpoints/create-order.md).
* `deposit.transferType` tells you what the payment step will look like before the order exists.
* Pass `quoteId` to [Create order](/server-to-server/api-endpoints/create-order.md) before `quoteExpiresAt` to hold this price. After it expires, request a new quote. A `quoteId` can also be handed to the Pay Widget — see [URL params](/widget-integration/url-params.md).

{% hint style="info" %}
In sandbox, `fieldsToCreateOrder` also carries the optional `depositSandboxForcedFlow` and `payoutSandboxForcedFlow` fields. Set them to force a success, a failure, an underpayment or an overpayment without moving real funds. Which values a given offer accepts is in the field's own `options` array — read it rather than assuming, because it differs by offer and by side. Neither field appears in production.
{% endhint %}

Response example:

{% code overflow="wrap" expandable="true" %}

```json
{
    "quoteId": "6928130ca263ba8d44fad2cf",
    "quoteExpiresAt": "2025-11-27T09:29:56.167Z",
    "deposit": {
        "paymentChannel": "bank",
        "currencyType": "fiat",
        "currencyCode": "NGN",
        "currencyDetails": {
            "countryIsoCode": "NG"
        },
        "cashout": {
            "amountBeforeFees": 10000,
            "amountAfterFees": 9650,
            "chargedFees": [
                {
                    "id": "service_fee",
                    "type": "percentage",
                    "recipient": "platform",
                    "amount": 250
                },
                {
                    "id": "merchant_fee",
                    "type": "percentage",
                    "recipient": "merchant",
                    "amount": 100
                }
            ],
            "totalChargedFees": 350,
            "chargedFeesPerRecipient": {
                "platform": 250,
                "merchant": 100
            },
            "amountBeforeFeesUsd": 6.821794,
            "amountAfterFeesUsd": 6.583031,
            "chargedFeesUsd": [
                {
                    "id": "service_fee",
                    "type": "percentage",
                    "recipient": "platform",
                    "amount": 0.170545
                },
                {
                    "id": "merchant_fee",
                    "type": "percentage",
                    "recipient": "merchant",
                    "amount": 0.068218
                }
            ],
            "totalChargedFeesUsd": 0.238763,
            "exchangeRate": 1465.89,
            "exchangeRateAfterFees": 1519.0571,
            "chargedFeesPerRecipientUsd": {
                "platform": 0.170545,
                "merchant": 0.068218
            },
            "feeSettings": [
                {
                    "id": "service_fee",
                    "recipient": "platform",
                    "type": "percentage",
                    "value": 2.5,
                    "min": 0,
                    "max": "Infinity"
                },
                {
                    "id": "merchant_fee",
                    "recipient": "merchant",
                    "type": "percentage",
                    "value": 1,
                    "min": 0,
                    "max": "Infinity"
                }
            ]
        },
        "fieldsToCreateOrder": [
            {
                "key": "phoneNumber",
                "label": "Phone Number",
                "required": true,
                "type": "phone"
            },
            {
                "key": "bankCode",
                "label": "Bank name",
                "required": true,
                "type": "enum",
                "options": [
                    {
                        "label": "Sandbox Bank",
                        "value": "1"
                    },
                    {
                        "label": "Sandbox Bank 2",
                        "value": "2"
                    },
                    {
                        "label": "Sandbox Bank 3",
                        "value": "3"
                    }
                ]
            },
            {
                "key": "bankAccountNumber",
                "label": "Bank Account Number",
                "required": true,
                "type": "string"
            },
            {
                "key": "depositSandboxForcedFlow",
                "type": "enum",
                "label": "Sandbox deposit forced flow",
                "required": false,
                "defaultValue": "deposit_success",
                "options": [
                    {
                        "label": "Deposit success",
                        "value": "deposit_success"
                    },
                    {
                        "label": "Deposit invalid",
                        "value": "deposit_invalid"
                    },
                    {
                        "label": "Deposit underpayment (50%)",
                        "value": "deposit_underpayment"
                    },
                    {
                        "label": "Deposit overpayment (200%)",
                        "value": "deposit_overpayment"
                    }
                ]
            }
        ],
        "transferType": "manual"
    },
    "payout": {
        "paymentChannel": "crypto",
        "currencyType": "crypto",
        "currencyCode": "POLYGON_USDT",
        "currencyDetails": {
            "network": "POLYGON",
            "asset": "USDT",
            "contractAddress": "0x3b3a06b48119c035a2e86afdb69d9ad930643b3d"
        },
        "cashout": {
            "amountBeforeFees": 6.583031,
            "amountAfterFees": 6.582386,
            "chargedFees": [
                {
                    "id": "gas",
                    "type": "flat_amount",
                    "recipient": "blockchain",
                    "amount": 0.000645
                }
            ],
            "totalChargedFees": 0.000645,
            "chargedFeesPerRecipient": {
                "blockchain": 0.000645
            },
            "amountBeforeFeesUsd": 6.583031,
            "amountAfterFeesUsd": 6.582386,
            "chargedFeesUsd": [
                {
                    "id": "gas",
                    "type": "flat_amount",
                    "recipient": "blockchain",
                    "amount": 0.000645
                }
            ],
            "totalChargedFeesUsd": 0.000645,
            "exchangeRate": 1,
            "exchangeRateAfterFees": 1.0001,
            "chargedFeesPerRecipientUsd": {
                "blockchain": 0.000645
            },
            "feeSettings": [
                {
                    "id": "gas",
                    "recipient": "blockchain",
                    "type": "flat_amount",
                    "value": 0.000645,
                    "min": 0,
                    "max": "Infinity"
                }
            ]
        },
        "fieldsToCreateOrder": [
            {
                "key": "blockchainWalletAddress",
                "type": "string",
                "label": "Your wallet address",
                "required": true
            },
            {
                "key": "blockchainMemo",
                "type": "string",
                "label": "Memo",
                "required": false
            },
            {
                "key": "payoutSandboxForcedFlow",
                "type": "enum",
                "label": "Sandbox payout forced flow",
                "required": false,
                "defaultValue": "payout_success",
                "options": [
                    {
                        "label": "Payout success",
                        "value": "payout_success"
                    },
                    {
                        "label": "Payout failed",
                        "value": "payout_failed"
                    }
                ]
            }
        ]
    }
}
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.fonbnk.com/server-to-server/api-endpoints/create-quote.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
