> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meterlane.app/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Get a Quote and Initiate a USDC Corridor Payout

> Create a corridor, lock a live FX quote, and submit a USDC payout to a beneficiary bank account across five supported fiat currencies.

Before you can send money, you need an active corridor for your target currency. A corridor is a persistent configuration object that ties your organization to a destination currency and its KYC verification. Once the corridor is active, you can request a live quote and submit a payout against it as many times as you need.

<Steps>
  <Step title="Create a corridor">
    Send a `POST /corridors` request with the destination currency you want to pay out in. You only need to do this once per currency—reuse the same corridor ID for every subsequent quote and pay.

    ```bash theme={null}
    curl -X POST https://corridor.meterlane.app/corridors \
      -H "Authorization: Bearer bp_live_YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "destCurrency": "BRL"
      }'
    ```

    A successful request returns `201 Created` with the new corridor object:

    ```json theme={null}
    {
      "id": "crd_01HZ9K2XJQMV3NYFP8WTBR4E6D",
      "orgId": "org_01HZ9J7YQPNW2MXFK8VTCA3R5S",
      "destCurrency": "BRL",
      "status": "PENDING_KYC",
      "createdAt": "2025-01-15T10:22:34.000Z"
    }
    ```

    <Note>
      The corridor starts in `PENDING_KYC` status. It transitions to `ACTIVE` only after your organization completes KYC verification in the Meterlane dashboard under **Settings → Corridors**. You cannot request quotes or initiate payouts until the corridor is `ACTIVE`.
    </Note>

    Save the `id` from this response—you will use it in every subsequent call for this currency.
  </Step>

  <Step title="Get a quote">
    Request a live FX quote by calling `GET /corridors/:id/quote` with the amount of USDC you want to send. The `amount` query parameter is denominated in USDC.

    ```bash theme={null}
    curl https://corridor.meterlane.app/corridors/crd_01HZ9K2XJQMV3NYFP8WTBR4E6D/quote?amount=100 \
      -H "Authorization: Bearer bp_live_YOUR_API_KEY"
    ```

    The response contains everything you need to confirm the payout:

    ```json theme={null}
    {
      "quoteId": "qt_01HZ9M4KPQXR7NYVWC5TBF2E8A",
      "fxRate": "5.1823",
      "destAmount": "518.23",
      "destCurrency": "BRL",
      "expiresAt": "2025-01-15T10:24:34.000Z"
    }
    ```

    | Field        | Description                                                                                  |
    | ------------ | -------------------------------------------------------------------------------------------- |
    | `quoteId`    | Opaque ID that locks the quoted rate. Pass this to `/pay`.                                   |
    | `fxRate`     | Units of destination currency per 1 USDC at the time of the quote.                           |
    | `destAmount` | Amount the beneficiary will receive in `destCurrency`, after all fees.                       |
    | `expiresAt`  | ISO 8601 timestamp. The quote expires at this time—request a new one if you miss the window. |

    <Tip>
      The dashboard quote UI shows a full all-in fee breakdown—platform fee plus Circle CPN rail fees—before you commit to a payout. Check it when you want a transparent view of costs without writing code.
    </Tip>
  </Step>

  <Step title="Initiate the payout">
    Submit the payout by calling `POST /corridors/:id/pay`. You must include an `Idempotency-Key` header on every pay request. If you retry a failed network call using the same key, the API returns the original cached response instead of creating a duplicate payment.

    ```bash theme={null}
    curl -X POST https://corridor.meterlane.app/corridors/crd_01HZ9K2XJQMV3NYFP8WTBR4E6D/pay \
      -H "Authorization: Bearer bp_live_YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: payout-2025-01-15-acme-001" \
      -d '{
        "quoteId": "qt_01HZ9M4KPQXR7NYVWC5TBF2E8A",
        "fromAddress": "0xYourWalletAddressHere",
        "amountUSDC": "100",
        "beneficiary": {
          "name": "Acme Fornecedores Ltda",
          "bankName": "Banco do Brasil",
          "accountNumber": "123456789",
          "country": "BR",
          "currency": "BRL"
        }
      }'
    ```

    A successful request returns `202 Accepted`:

    ```json theme={null}
    {
      "paymentId": "pay_01HZ9N6LPQXV8MYWC4TBF3E9D7",
      "cpnPaymentId": "cpn_7f3a2b1e-4c5d-4e6f-8a9b-0c1d2e3f4a5b",
      "status": "PENDING"
    }
    ```

    The payment starts as `PENDING`. Circle processes the fiat leg asynchronously. When Circle confirms or fails the transfer, it posts a webhook event to Meterlane, which updates the payment status to `SETTLED`, `FAILED`, or `COMPLIANCE_HOLD`. See [Webhooks](/corridor/webhooks) for how to receive those updates.

    <Warning>
      The `Idempotency-Key` header is required. Omitting it returns a `400 MISSING_IDEMPOTENCY_KEY` error immediately. Use a unique, stable key per logical payout—such as your internal order ID—so retries are safe.
    </Warning>
  </Step>
</Steps>

## Beneficiary validation rules

The `beneficiary` object is validated on every pay request. Fields that are always required: `name`, `bankName`, `accountNumber`, `country`, and `currency`. Three countries have additional account-number format rules enforced at the API level.

<Accordion title="Country-specific account number rules">
  | Country      | ISO-2 code | Rule         | Format              |
  | ------------ | ---------- | ------------ | ------------------- |
  | Nigeria      | `NG`       | NUBAN format | Exactly 10 digits   |
  | Kenya        | `KE`       | —            | 8–14 digits         |
  | South Africa | `ZA`       | —            | 7–11 digits         |
  | Brazil       | `BR`       | —            | No extra constraint |
  | Mexico       | `MX`       | —            | No extra constraint |

  Digits are extracted from the `accountNumber` string before length validation, so hyphens and spaces in the input do not cause false failures. However, it is good practice to send a clean numeric string.
</Accordion>

## Error reference

| Code                      | HTTP status | Cause                                                                                                       |
| ------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------- |
| `CORRIDOR_NOT_ACTIVE`     | 409         | The corridor exists but its status is not `ACTIVE`. Complete KYC in the dashboard first.                    |
| `INVALID_CURRENCY`        | 400         | The `destCurrency` value is not one of the supported currencies (`BRL`, `MXN`, `NGN`, `KES`, `ZAR`).        |
| `INVALID_AMOUNT`          | 400         | `amountUSDC` (pay) or `amount` (quote) is zero, negative, or not a valid number.                            |
| `INVALID_BENEFICIARY`     | 400         | A required beneficiary field is missing or the account number does not meet country-specific length rules.  |
| `MISSING_IDEMPOTENCY_KEY` | 400         | The `Idempotency-Key` header was not included on `POST /corridors/:id/pay`.                                 |
| `DUPLICATE_REQUEST`       | 409         | A pay request with this `Idempotency-Key` was already processed. The response contains the original result. |
