---
title: "Pay out to a bank account"
method: POST
path: "/v1/customers/{customerId}/payouts/fiat"
tags: ["Payouts"]
---

# Pay out to a bank account

`POST /v1/customers/{customerId}/payouts/fiat`

## Request

- Base URL: `https://api.sandbox.alfredpay.io`
- URL: `https://api.sandbox.alfredpay.io/v1/customers/{customerId}/payouts/fiat`
- Auth: one of:
  - HTTP bearer
  - API key in header `api-key` and API key in header `api-secret`

Natively cross-currency. Pass a `quoteId` and the FX runs as an `LP_EXECUTION` leg inside this one `PAY_OUT`, alongside the `FIAT_RAIL` leg.

The balance to debit is inferred from the customer and the quote's pair. You never pass it. The linked account has to be `VERIFIED`, and its currency has to equal the quote's `toCurrency`.

**How the rail is resolved.** In order: the quote's `rail` if you passed a quote, then the body's `rail`, then the destination's rail if it only supports one. Whatever resolves has to be in the destination's `supportedRails[]`, or you get `rail_mismatch`. A SPEI quote can't fund a PIX account. If the destination supports several rails and neither the quote nor the body names one, the request fails with `validation_error` on `rail`. The resolved combination of country, currency and rail has to be a `LIVE` route, or it's `route_unsupported`.

**When you need a quote.** Only for a genuine FX pair, which means the funding balance and the destination are different fiat currencies, or the funding balance is a stablecoin and the destination isn't USD.

A same-currency payout is a plain transfer with no FX leg and no quote. USD Corporate Account out to USD over ACH or wire is one. So is an MXNa local balance out to MXN over SPEI.

USDC or USDT going to USD is a par redemption priced from the fee table. A quote is optional there, to lock fees, and never required. No artificial conversion is ever introduced.

**Wait on** `payout.fiat.updated`. See [Webhooks and events](/docs/webhooks-and-events).

## Headers

- `Idempotency-Key` string, uuid, required

## Request body

- FiatPayoutCreate
  - `linkedAccountId` string, required
  - `quoteId` string: Required only for a genuine FX pair (different fiat currencies, or stablecoin → non-USD fiat). Omit for a same-currency payout; optional for a USDC/USDT → USD par redemption.
  - `rail` 'ACH' | 'WIRE' | 'SPEI' | 'PIX' | 'COELSA' | 'FPS' | 'CHATS': The `Rail` values a fiat quote may carry, so every rail except `WALLET`.
  - `amount` Money, required
    - `value` string, required
    - `currency` 'USD' | 'HKD' | 'CNY' | 'MXN' | 'DOP' | 'COP' | 'BRL' | 'ARS' | 'CLP' | 'PEN' | 'BOB' | 'PYG' | 'USDC' | 'USDT', required: Fourteen members, reconciled to the countries a customer can be onboarded in. USDC and USDT are stablecoins and require `chain`.
  - `reference` string
  - `payment_flow_id` string
  - `metadata` Metadata: Client-supplied key–value pairs, echoed on the object and every event about it.

## Response `201`

Created

- FiatPayout: Present on every money object. The four machines move independently.
  - `transaction_id` string, required
  - `transaction_type` 'PAY_IN' | 'PAY_OUT' | 'CONVERSION', required
  - `pay_in_subtype` 'COLLECTION' | 'ON_RAMP' | 'USD_STABLE_DEPOSIT' | 'null', nullable
  - `pay_out_subtype` 'OFF_RAMP' | 'FIAT_WITHDRAWAL' | 'CRYPTO_WITHDRAWAL' | 'CROSS_BORDER_PAYOUT' | 'null', nullable
  - `conversion_subtype` 'OTC_TRADE' | 'BALANCE_CONVERSION' | 'null', nullable
  - `transaction_status` 'CREATED' | 'PENDING_VALIDATION' | 'PENDING_FUNDS' | 'PENDING_COMPLIANCE' | 'PENDING_RFI' | 'APPROVED_FOR_EXECUTION' | 'PROCESSING' | 'COMPLETE' | 'FAILED' | 'CANCELLED' | 'BLOCKED', required: Business lifecycle, customer-facing. Terminal values are COMPLETE, FAILED, CANCELLED, BLOCKED.
  - `compliance_status` 'NOT_REQUIRED' | 'PENDING_SCREENING' | 'PENDING_KYT' | 'CLEARED' | 'ALERTED' | 'RFI_REQUESTED' | 'PAUSED' | 'ESCALATED' | 'RELEASED' | 'BLOCKED', required
  - `settlement_status` 'NOT_STARTED' | 'FUNDS_EXPECTED' | 'FUNDS_RECEIVED' | 'FUNDS_HELD' | 'FUNDS_RELEASED' | 'SETTLED' | 'PARTIALLY_SETTLED' | 'FAILED' | 'RETURNED', required: Leg-level and financial. "Delayed settlement" is a settlement value with the parent still PROCESSING, never a business status.
  - `reconciliation_summary` 'ALL_MATCHED' | 'PARTIAL_MATCH' | 'HAS_BREAK', required: Derived, visibility only. Never blocks transaction_status.
  - `payment_flow_id` string, nullable: Relates independent transactions in one flow. One completing never completes another.
  - `resource_version` integer: Monotonic per resource. Apply events in this order.
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `id` string
  - `customerId` string
  - `linkedAccountId` string
  - `quoteId` string, nullable
  - `rail` 'ACH' | 'WIRE' | 'SPEI' | 'PIX' | 'COELSA' | 'FPS' | 'CHATS' | 'WALLET': The scheme family a payment moves on. Never a country, provider or account identifier. `ACH` is any domestic batch bank transfer (US ACH, and the local clearing houses of COL, CHL, PER, BOL, PRY, DOM, CHN); `WIRE` is RTGS/SWIFT/Fedwire; `SPEI`, `PIX`, `COELSA`, `FPS` and `CHATS` are named instant schemes with their own semantics (COELSA is Argentina's instant transfer, deliberately not folded into ACH); `WALLET` is a stablecoin destination. Cash pickup is not in this release and has no rail value yet. Which rails a destination supports is derived by Alfred and returned as `supportedRails[]`; which `(country, currency, rail)` combinations are live is published by `GET /v1/countries/{country}`.
  - `route` object
    - `country` 'MEX' | 'ARG' | 'BRA' | 'COL' | 'CHL' | 'PER' | 'DOM' | 'USA' | 'CHN' | 'HKG' | 'BOL' | 'PRY': ISO 3166-1 alpha-3, the only form Alfred stores, filters on, reports or emits. Compatibility rule for integrations that can only send alpha-2: any inbound `country` value in alpha-2 (path, query or body) is normalized to alpha-3 at the boundary before validation, storage or routing. Unrecognized in either form → `422 validation_error`.
    - `currency` 'USD' | 'HKD' | 'CNY' | 'MXN' | 'DOP' | 'COP' | 'BRL' | 'ARS' | 'CLP' | 'PEN' | 'BOB' | 'PYG' | 'USDC' | 'USDT': Fourteen members, reconciled to the countries a customer can be onboarded in. USDC and USDT are stablecoins and require `chain`.
    - `rail` 'ACH' | 'WIRE' | 'SPEI' | 'PIX' | 'COELSA' | 'FPS' | 'CHATS' | 'WALLET': The scheme family a payment moves on. Never a country, provider or account identifier. `ACH` is any domestic batch bank transfer (US ACH, and the local clearing houses of COL, CHL, PER, BOL, PRY, DOM, CHN); `WIRE` is RTGS/SWIFT/Fedwire; `SPEI`, `PIX`, `COELSA`, `FPS` and `CHATS` are named instant schemes with their own semantics (COELSA is Argentina's instant transfer, deliberately not folded into ACH); `WALLET` is a stablecoin destination. Cash pickup is not in this release and has no rail value yet. Which rails a destination supports is derived by Alfred and returned as `supportedRails[]`; which `(country, currency, rail)` combinations are live is published by `GET /v1/countries/{country}`.
  - `amount` Money
    - `value` string, required
    - `currency` 'USD' | 'HKD' | 'CNY' | 'MXN' | 'DOP' | 'COP' | 'BRL' | 'ARS' | 'CLP' | 'PEN' | 'BOB' | 'PYG' | 'USDC' | 'USDT', required: Fourteen members, reconciled to the countries a customer can be onboarded in. USDC and USDT are stablecoins and require `chain`.
  - `funding` object: Derived, never passed.
    - `type` string
    - `asset` string
    - `amount` string
  - `fees` Fee[]
    - `type` 'provider' | 'network' | 'alfred' | 'conversion' | 'payout'
    - `amount` string
    - `currency` string
  - `action` object, nullable
    - `type` 'CORRECTION' | 'REPROCESSING'
    - `actionId` string
    - `parentPayoutId` string

## Other responses

- `202`: Accepted but routed to policy review, so `PENDING_COMPLIANCE` with `PAUSED`.
- `403`: `endorsement_not_enabled`, for example `fiat_payout.cross_border`.
- `409`: `recipient_not_linked` (linked account not `VERIFIED`), `quote_expired`, `quote_consumed`, or `rail_mismatch` (the rail is not in the destination's `supportedRails`).
- `422`: `insufficient_balance`, `currency_mismatch`, `route_unsupported` (the resolved route is not LIVE), or `validation_error` on `rail` when the destination supports several and none was named. All of these fail before any balance is locked.

## Changes

- **2026-11-03** `20fef4fd2ab3`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/alfredpay/apis/alfred-penny-api-client-documentation/changes/v1/customers/:customerId/payouts/fiat/post.md)

---

[API](https://skmtc.dev/alfredpay/apis/alfred-penny-api-client-documentation.md) - [All operations](https://skmtc.dev/alfredpay/apis/alfred-penny-api-client-documentation/llms.txt) - [OpenAPI document](https://skmtc.dev/alfredpay/apis/alfred-penny-api-client-documentation/revisions/20fef4fd2ab3?raw)
