> ## Documentation Index
> Fetch the complete documentation index at: https://developer.me-cash.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Quote API

Use this endpoint to generate a guaranteed exchange rate for a specific corridor. The quote response includes a `quoteId` that you must supply when you create the payout.

## Endpoint

**POST** `{{baseURL}}/v1/quote`

<Callout type="info" emoji="⏱️">
  Quotes expire after the duration returned in `expiresInSeconds`. Create the payout before it expires or request a fresh quote.
</Callout>

## Request body

```json copy theme={null}
{
  "paymentChannel": "BANK_TRANSFER",
  "source": {
    "amount": 150000,
    "country": "NG",
    "currency": "NGN"
  },
  "target": {
    "country": "US",
    "currency": "USD"
  }
}
```

### Body fields

| **Field**         | **Type** | **Description**                                                                   | **Required** | **Example**     |
| ----------------- | -------- | --------------------------------------------------------------------------------- | ------------ | --------------- |
| `paymentChannel`  | String   | Payment channel used to settle the payout (e.g. `BANK_TRANSFER`, `MOBILE_MONEY`). | ✅ Yes        | `BANK_TRANSFER` |
| `source.amount`   | Number   | Amount you want to convert in the source currency.                                | ✅ Yes        | `150000`        |
| `source.country`  | String   | ISO 3166-1 alpha-2 code for the sender country.                                   | ✅ Yes        | `NG`            |
| `source.currency` | String   | ISO 4217 code for the sender currency.                                            | ✅ Yes        | `NGN`           |
| `target.country`  | String   | ISO 3166-1 alpha-2 code for the recipient country.                                | ✅ Yes        | `US`            |
| `target.currency` | String   | ISO 4217 code for the recipient currency.                                         | ✅ Yes        | `USD`           |

### Request headers

| **Header**     | **Type** | **Description**                         | **Required** | **Example**        |
| -------------- | -------- | --------------------------------------- | ------------ | ------------------ |
| `x-api-key`    | String   | API key associated with your workspace. | ✅ Yes        | `YOUR_API_KEY`     |
| `Content-Type` | String   | Media type of the request body.         | ✅ Yes        | `application/json` |

## Request examples

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST '{{baseURL}}/v1/quote' \
    --header 'x-api-key: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "paymentChannel": "BANK_TRANSFER",
      "source": {
        "amount": 150000,
        "country": "NG",
        "currency": "NGN"
      },
      "target": {
        "country": "US",
        "currency": "USD"
      }
    }'
  ```

  ```js JavaScript (fetch) theme={null}
  const payload = {
    paymentChannel: 'BANK_TRANSFER',
    source: {
      amount: 150000,
      country: 'NG',
      currency: 'NGN'
    },
    target: {
      country: 'US',
      currency: 'USD'
    }
  };

  fetch('{{baseURL}}/v1/quote', {
    method: 'POST',
    headers: {
      'x-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  })
    .then((res) => {
      if (!res.ok) {
        throw new Error(`Request failed with status ${res.status}`);
      }
      return res.json();
    })
    .then((body) => console.log(body))
    .catch((error) => console.error('Failed to create quote', error));
  ```

  ```python Python (requests) theme={null}
  import requests

  url = "{{baseURL}}/v1/quote"
  headers = {
      "x-api-key": "YOUR_API_KEY",
      "Content-Type": "application/json",
  }
  payload = {
      "paymentChannel": "BANK_TRANSFER",
      "source": {
          "amount": 150000,
          "country": "NG",
          "currency": "NGN",
      },
      "target": {
          "country": "US",
          "currency": "USD",
      },
  }

  response = requests.post(url, json=payload, headers=headers, timeout=30)
  response.raise_for_status()
  print(response.json())
  ```

  ```js Node.js (axios) theme={null}
  const axios = require('axios');

  axios.post('{{baseURL}}/v1/quote', {
    paymentChannel: 'BANK_TRANSFER',
    source: {
      amount: 150000,
      country: 'NG',
      currency: 'NGN'
    },
    target: {
      country: 'US',
      currency: 'USD'
    }
  }, {
    headers: {
      'x-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    timeout: 30000
  })
    .then((response) => {
      console.log(response.data);
    })
    .catch((error) => {
      if (error.response) {
        console.error('API error:', error.response.data);
      } else {
        console.error('Request error:', error.message);
      }
    });
  ```
</CodeGroup>

## Successful response

```json copy theme={null}
{
  "message": "quote successfully created",
  "status": "success",
  "data": {
    "id": "e5eec724-38f9-40e2-9i86-xxxxxxxxxxxxx",
    "source": {
      "currency": "NGN",
      "country": "NG",
      "amount": 150000
    },
    "target": {
      "currency": "USD",
      "country": "US",
      "amount": 81.97
    },
    "rate": 1830,
    "fee": {
      "amount": 0
    },
    "summary": {
      "total": 150000
    },
    "rules": [
      {
        "category": "LIMIT",
        "appliedCurrency": "USD",
        "transaction": {
          "minimum": 1,
          "maximum": 200000
        }
      }
    ],
    "expiresInSeconds": 600,
    "settlementTime": "1 hr"
  }
}
```

### Field reference

| **Field**          | **Type** | **Description**                                                |
| ------------------ | -------- | -------------------------------------------------------------- |
| `id`               | String   | Quote identifier to reuse in payout requests.                  |
| `rate`             | Number   | Exchange rate applied to the conversion.                       |
| `summary.total`    | Number   | Amount to debit in the source currency.                        |
| `fee.amount`       | Number   | Total fees charged for the quote.                              |
| `expiresInSeconds` | Number   | Time remaining before the quote becomes invalid.               |
| `rules`            | Array    | Corridor rules that were evaluated (limits, compliance, etc.). |

## Error responses

| **Status** | **Message**                                                             | **Cause**                                                           | **How to handle**                                                           |
| ---------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| 400        | `Invalid country or currency ISO code`                                  | The source/target country or currency combination is not supported. | Use valid ISO codes for corridors enabled on your workspace.                |
| 400        | `Invalid Payment Channel, check docs or contact support`                | `paymentChannel` is not valid for the selected corridor.            | Choose a supported channel for the corridor and amount.                     |
| 400        | `Required field missing or invalid request`                             | Mandatory fields are missing or have invalid formats.               | Validate `source`, `target`, `paymentChannel`, and metadata before sending. |
| 400        | `Minimum target amount for transaction is {minimum_transaction_amount}` | Requested target amount is below the corridor's minimum.            | Increase the target amount to at least the stated minimum.                  |
| 400        | `Maximum target amount for transaction is {maximum_transaction_amount}` | Requested target amount exceeds the corridor's limit.               | Reduce the target amount below the maximum threshold.                       |
| 400        | `Transaction target amount {transaction_amount} requires invoice`       | Amount surpasses invoice thresholds that require documentation.     | Collect and attach the required invoice before retrying.                    |
| 401        | `API key missing or incorrect`                                          | `x-api-key` header missing, invalid, or expired.                    | Include the correct API key for sandbox/production.                         |
| 403        | `Quote route not available, contact support`                            | Endpoint disabled for your workspace or environment.                | Reach out to support to enable quotes for the corridor.                     |
| 403        | `Access denied: IP address not whitelisted`                             | Request originated from an IP that isn’t on your allowlist.         | Add your server IP in the dashboard.                                        |
| 429        | `API rate limit exceeded`                                               | Too many quote requests in a short window.                          | Apply exponential backoff and distribute requests.                          |
| 500        | `Service temporarily unavailable`                                       | Temporary outage or maintenance event.                              | Retry after a delay; contact support if persistent.                         |

## Best practices

* Cache quotes temporarily so the user can confirm without re-requesting.
* Surface the quote expiry countdown in your UI to encourage timely confirmation.
* Use the [`Get Quote API`](/quote-docs/get-quote) if you need to display the quote again before payout.
* Pass the `quoteId` to [`POST /v2/payout`](/payout-docs/create-payout) to execute the transfer.
