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

# Execute a payout

> Lock a quote and start the payout in one call.

Lock + start a payout in one call. Pick the matching tab — shapes differ by corridor.

Response: `{ "success": true, "data": { … } }`.

<Info>**Scope** `payouts:write` · rate-limited</Info>

## Headers

<ParamField header="Authorization" type="string" required>
  API key.
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  Optional. 8–255 url-safe characters. 24h replay window; mismatched bodies on the same key return `409 IDEMPOTENCY_KEY_REUSED`.
</ParamField>

## Common fields

<ParamField body="fromCurrency" type="string" required>Source currency. ISO 4217 for fiat, ticker for stablecoin.</ParamField>
<ParamField body="toCurrency" type="string" required>Destination currency.</ParamField>
<ParamField body="amount" type="number" required>Source amount. Must be `> 0`.</ParamField>
<ParamField body="recipientId" type="string" required>UUID from [`POST /recipients`](/api-reference/recipients/create).</ParamField>
<ParamField body="targetAmount" type="number">Exact-output target. When set, sizes `amount` upstream so the recipient receives exactly this much.</ParamField>
<ParamField body="recipientPaymentMethodId" type="string">UUID of the recipient PM, when more than one exists.</ParamField>
<ParamField body="routeProtocol" type="string">Opaque route token (`rt_…`) from a `/quotes/*` call. Pins the route.</ParamField>
<ParamField body="paymentPurpose" type="string">Partner-side classification (e.g. `salary`).</ParamField>
<ParamField body="reference" type="string">Free-text reference echoed back on reads.</ParamField>
<ParamField body="supportingDocumentKey" type="string">S3 key for an attached supporting document. Required by some compliance-bearing onramp flows.</ParamField>

## Request body

Switch tabs for the type-specific fields and response shape.

<Tabs>
  <Tab title="Fiat-to-fiat">
    Send fiat from your stored payment method; recipient receives fiat.

    <ParamField body="userPaymentMethodId" type="string" required>UUID of your funding source.</ParamField>

    ### Response

    <ResponseField name="payoutId" type="string">UUID of the new payout. Use with [`GET /payouts/{id}`](/api-reference/payouts/get).</ResponseField>
    <ResponseField name="quoteId" type="string">UUID of the locked quote. Use with [`GET /rfq/status/{quoteId}`](/api-reference/payouts/status).</ResponseField>
    <ResponseField name="status" type="string">Hard-coded `accepted` on success.</ResponseField>
    <ResponseField name="toAmount" type="number">Destination amount the recipient will receive.</ResponseField>
    <ResponseField name="partnerFxRate" type="number">Quoted FX rate, pre-fees.</ResponseField>
    <ResponseField name="effectiveRate" type="number">Effective rate net of fees.</ResponseField>
    <ResponseField name="fees" type="object">Per-payout fee breakdown — see [Fees](#fees).</ResponseField>
    <ResponseField name="bankingInstructions" type="object">Map of `string` → `string` describing where to send the source fiat. Keys vary by rail (`accountNumber`, `bankName`, `swiftCode`, etc.).</ResponseField>

    <ResponseExample>
      ```json 200 theme={null}
      {
        "success": true,
        "data": {
          "payoutId": "8b1a4c1d-7a3c-4a08-94ad-9f1ef1e0c3a2",
          "quoteId":  "4c2b7e8f-3a3c-4a08-94ad-1234567890ab",
          "status": "accepted",
          "toAmount": 4425.00,
          "partnerFxRate": 4.4250,
          "effectiveRate": 4.4070,
          "fees": { "teelFee": 4.05, "teelFeeBps": 40, "partnerFee": 0, "gasFee": 0 },
          "bankingInstructions": {
            "accountNumber": "1234567890",
            "bankName": "Maybank",
            "swiftCode": "MBBEMYKL"
          }
        }
      }
      ```
    </ResponseExample>
  </Tab>

  <Tab title="Stablecoin-to-fiat">
    Send stablecoin from your wallet; recipient receives fiat. The response carries escrow deposit instructions — your wallet must send the source stablecoin to `escrowAddress`.

    <ParamField body="walletAddress" type="string" required>Source wallet address.</ParamField>

    ### Response

    <ResponseField name="payoutId" type="string">UUID of the new payout.</ResponseField>
    <ResponseField name="quoteId" type="string">UUID of the locked quote.</ResponseField>
    <ResponseField name="status" type="string">Always `awaiting_escrow_deposit` until the deposit lands.</ResponseField>
    <ResponseField name="toAmount" type="number">Destination fiat amount.</ResponseField>
    <ResponseField name="partnerFxRate" type="number">Quoted FX rate, pre-fees.</ResponseField>
    <ResponseField name="effectiveRate" type="number">Effective rate net of fees.</ResponseField>
    <ResponseField name="fees" type="object">Per-payout fee breakdown — see [Fees](#fees).</ResponseField>
    <ResponseField name="escrowAddress" type="string">On-chain address your wallet must send the source stablecoin to.</ResponseField>
    <ResponseField name="depositAmountAtomic" type="string">Atomic-units integer string — parse with `BigInt`. JSON numbers lose precision for 18-decimal tokens. Example: `"300000"` = 0.3 USDC at 6 decimals.</ResponseField>
    <ResponseField name="tokenAddress" type="string">ERC-20 contract address of the source stablecoin.</ResponseField>
    <ResponseField name="chainId" type="integer">EVM chain id of the deposit address.</ResponseField>

    <ResponseExample>
      ```json 200 theme={null}
      {
        "success": true,
        "data": {
          "payoutId": "8b1a4c1d-7a3c-4a08-94ad-9f1ef1e0c3a2",
          "quoteId":  "4c2b7e8f-3a3c-4a08-94ad-1234567890ab",
          "status": "awaiting_escrow_deposit",
          "toAmount": 4425.00,
          "partnerFxRate": 4.4250,
          "effectiveRate": 4.4070,
          "fees": { "teelFee": 0.91, "teelFeeBps": 40, "partnerFee": 0, "gasFee": 0.05 },
          "escrowAddress": "0xAbcDef0123456789AbcDef0123456789AbcDef01",
          "depositAmountAtomic": "227250000",
          "tokenAddress": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
          "chainId": 137
        }
      }
      ```
    </ResponseExample>

    After the response: your wallet sends `depositAmountAtomic` of `tokenAddress` to `escrowAddress` on `chainId`. The engine auto-detects the transfer; if it misses, fall back to [`POST /rfq/confirm-escrow-deposit`](/api-reference/payouts/confirm-escrow-deposit) with the tx hash.
  </Tab>

  <Tab title="Onramp (fiat → stablecoin)">
    Send fiat from your stored PM; recipient receives stablecoin on-chain.

    <ParamField body="userPaymentMethodId" type="string" required>UUID of your funding source.</ParamField>

    ### Response

    <ResponseField name="payoutId" type="string">UUID of the new payout.</ResponseField>
    <ResponseField name="quoteId" type="string">UUID of the locked quote.</ResponseField>
    <ResponseField name="status" type="string">Passed through from the onramp route.</ResponseField>
    <ResponseField name="toAmount" type="number">Destination stablecoin amount.</ResponseField>
    <ResponseField name="partnerFxRate" type="number">Quoted FX rate, pre-fees.</ResponseField>
    <ResponseField name="effectiveRate" type="number">Effective rate net of fees.</ResponseField>
    <ResponseField name="fees" type="object">Per-payout fee breakdown — see [Fees](#fees).</ResponseField>
    <ResponseField name="paymentUrl" type="string">Hosted payment page — redirect the user here to complete the onramp.</ResponseField>
    <ResponseField name="bankingInstructions" type="object">When the rail settles by bank transfer instead of hosted page. Mutually exclusive with `paymentUrl`.</ResponseField>

    <ResponseExample>
      ```json 200 theme={null}
      {
        "success": true,
        "data": {
          "payoutId": "8b1a4c1d-7a3c-4a08-94ad-9f1ef1e0c3a2",
          "quoteId":  "4c2b7e8f-3a3c-4a08-94ad-1234567890ab",
          "status": "pending",
          "toAmount": 990.50,
          "partnerFxRate": 1.0,
          "effectiveRate": 0.9905,
          "fees": { "teelFee": 9.50, "teelFeeBps": 95, "partnerFee": 0, "gasFee": 0 },
          "paymentUrl": "https://pay.example.com/sess_abc123"
        }
      }
      ```
    </ResponseExample>
  </Tab>
</Tabs>

## Fees

<ResponseField name="fees.teelFee" type="number">Teel's fee, in `fromCurrency`.</ResponseField>
<ResponseField name="fees.teelFeeBps" type="integer">Teel's fee in basis points (1 bp = 0.01%).</ResponseField>
<ResponseField name="fees.partnerFee" type="number">Your markup. `0` unless configured.</ResponseField>
<ResponseField name="fees.gasFee" type="number">On-chain gas (S2F / stablecoin flows).</ResponseField>

## Errors

| Status | Code                                                       | When                                                                              |
| ------ | ---------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `400`  | `INVALID_JSON` / `INVALID_PARAMETER`                       | Body malformed, required field missing, or a UUID doesn't belong to your account. |
| `401`  | `UNAUTHORIZED`                                             | Missing or invalid key.                                                           |
| `403`  | `FORBIDDEN`                                                | Key lacks `payouts:write`.                                                        |
| `409`  | `IDEMPOTENCY_KEY_REUSED` / `IDEMPOTENCY_REQUEST_IN_FLIGHT` | Idempotency conflict — back off per `Retry-After` for in-flight.                  |
| `429`  | `RATE_LIMITED`                                             | Per-key rate limit.                                                               |

## Next steps

Poll [`GET /rfq/status/{quoteId}`](/api-reference/payouts/status) or — preferred — subscribe to `payout.status.updated` and `payout.delivered` via [Webhooks](/guides/webhooks).
