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

# Pay a third party

> Register a counterparty and their bank account, then pay them from a customer's wallet with the quote and transaction flow.

<Note>
  **Before you start:** the OMS API is in early access. Every endpoint, including the ones in this guide, requires an early-access API key. [Request access](https://info.polygon.technology/get-early-access?utm_source=docs\&utm_medium=card\&utm_campaign=oms_access) before you begin.

  Authenticate by exchanging your API key and secret for a bearer token at `POST /auth/token`, then send it as `Authorization: Bearer {accessToken}` on every request. Every `POST` and `PATCH` also requires an `Idempotency-Key` header. See [Get started](/payments/get-started) for the full flow.
</Note>

This guide shows you how to pay someone who is not your customer: a vendor, a payee, or any other third party. In OMS, that recipient is a **counterparty**, an entry in the customer's address book that can own registered external accounts. Beneficiaries never need an OMS account of their own. The flow has four steps: create the counterparty, register their bank account, create a quote, and execute the transaction.

## Prerequisites

1. **A customer** with a `cst_` ID and the `usd` endorsement: the payout is funded from this customer's wallet.
2. **A funded OMS wallet** with a `wlt_` ID holding enough USDC to cover the payout.
3. **The recipient's details**: their legal name, and their bank account information.

## Step 1: Create the counterparty

`POST /counterparties` requires only the owning `customerId` and the recipient's `name`. The identity fields are optional but improve compliance screening: `entityType` (`individual` or `business`), `email`, `phone`, `dateOfBirth`, `taxId`, `nationality`, and an `address`.

### Request

```
POST /counterparties
Authorization: Bearer {accessToken}
Idempotency-Key: ctp-acme-001
Content-Type: application/json
```

```json theme={null}
{
  "customerId": "cst_01H9Xa...",
  "name": "Acme Supplies LLC",
  "entityType": "business",
  "email": "billing@acme.example",
  "taxId": "98-7654321",
  "address": {
    "streetAddress": "500 Market St",
    "city": "San Francisco",
    "countryArea": "CA",
    "postalCode": "94105",
    "country": "US"
  }
}
```

The `address` shape is `streetAddress`, `city`, `postalCode`, and `country` (required when an address is supplied), plus an optional `countryArea` for the state or region.

### Response, `201 Created`

```json theme={null}
{
  "id": "ctp_01H9Xc...",
  "object": "counterparty",
  "customerId": "cst_01H9Xa...",
  "name": "Acme Supplies LLC",
  "entityType": "business",
  "email": "billing@acme.example",
  "taxId": "98-7654321",
  "address": {
    "streetAddress": "500 Market St",
    "city": "San Francisco",
    "countryArea": "CA",
    "postalCode": "94105",
    "country": "US"
  },
  "status": "active",
  "rejectionReason": null,
  "createdAt": "2026-07-07T10:00:00Z",
  "updatedAt": "2026-07-07T10:00:00Z"
}
```

Store the `ctp_` ID. A counterparty that fails compliance screening comes back `rejected` with a `rejectionReason`; only `active` counterparties can own external accounts.

## Step 2: Register the counterparty's bank account

Register the recipient's bank with `POST /external-accounts`, setting the `owner` to the counterparty. The per-type detail object must match the `type`: `bankUs` for US accounts, `bankIban` for international IBAN accounts, or `bankCanada` for Canadian accounts.

### Request

```
POST /external-accounts
Authorization: Bearer {accessToken}
Idempotency-Key: ext-acme-bank-001
Content-Type: application/json
```

```json theme={null}
{
  "owner": { "kind": "counterparty", "counterpartyId": "ctp_01H9Xc..." },
  "type": "bankUs",
  "bankUs": {
    "accountNumber": "987654321012",
    "routingNumber": "021000021",
    "accountType": "checking",
    "bankName": "Chase"
  },
  "label": "Acme payouts"
}
```

### Response, `201 Created`

```json theme={null}
{
  "id": "ext_bankUs_01H9Xm...",
  "object": "externalAccount",
  "owner": { "kind": "counterparty", "counterpartyId": "ctp_01H9Xc..." },
  "type": "bankUs",
  "category": "fiatAccount",
  "status": "pending",
  "bankUs": {
    "accountNumberLast4": "1012",
    "routingNumber": "021000021",
    "accountType": "checking",
    "bankName": "Chase"
  },
  "label": "Acme payouts",
  "createdAt": "2026-07-07T10:01:00Z",
  "updatedAt": "2026-07-07T10:01:00Z"
}
```

The full account number is write-only; reads return `accountNumberLast4`. The account starts `pending` and flips to `active` (usable on quotes) or `failed`. Wait for `active` before quoting against it.

## Step 3: Create the quote

The quote is identical to any other bank payout: the `source` is the customer's OMS wallet, and the `destination` is the counterparty's registered bank account referenced by its `ext_bankUs_` ID.

```
POST /quotes
Authorization: Bearer {accessToken}
Idempotency-Key: qt-acme-payout-001
Content-Type: application/json
```

```json theme={null}
{
  "customerId": "cst_01H9Xa...",
  "source": {
    "type": "walletOms",
    "details": { "id": "wlt_01H9Xb...", "asset": "usdc", "network": "polygon" },
    "amount": "2500.00"
  },
  "destination": {
    "type": "bankUs",
    "details": {
      "id": "ext_bankUs_01H9Xm...",
      "asset": "usd",
      "network": "ach",
      "accountHolder": "customer"
    }
  }
}
```

On the response, OMS resolves the recipient's identity onto the destination's `party` block, so you can render who is being paid without extra reads:

```json theme={null}
"destination": {
  "party": {
    "relationship": "externalRegistered",
    "counterpartyId": "ctp_01H9Xc...",
    "entityType": "business",
    "name": "Acme Supplies LLC"
  },
  "type": "bankUs",
  "category": "fiatAccount",
  "details": { "id": "ext_bankUs_01H9Xm...", "asset": "usd", "network": "ach" }
}
```

All amounts, fees, and rates live in the top-level `pricing` object. The direction is inferred as `cryptoToFiatAccount`.

## Step 4: Execute and track

Accept the quote with `POST /transactions` and the `quoteId`:

```json theme={null}
{ "quoteId": "qt_01H9Xq..." }
```

The transaction starts at `processing` and moves to `completed` when the bank payout settles, or `failed` with an `error` object. The payout leg surfaces granular progress in `subStatus`: `processing.awaitingFiatOut` while the payout is queued, then `processing.fiatOut` once it is in flight. Poll `GET /transactions/{transactionId}` or subscribe to `transaction.cryptoToFiat.completed` (and `transaction.cryptoToFiat.failed`); see the [webhook events catalog](/api-reference/webhook-events) for the full list.

To reconcile a payout run, filter `GET /transactions?customerId=...`: each transaction's destination `party` carries the `counterpartyId` it paid.

Payouts are sent from named accounts: the recipient's bank statement shows the paying customer's own legal-entity name as the sender, not Polygon and not your platform.

## Managing counterparties

* `GET /counterparties?customerId=...` lists a customer's counterparties (`customerId` is required). Paginate with `limit`, `startingAfter`, and `endingBefore`.
* `GET /counterparties/{counterpartyId}` fetches one by ID.
* `PATCH /counterparties/{counterpartyId}` partially updates identity fields; omitted fields are unchanged.
* `DELETE /counterparties/{counterpartyId}` soft-deletes. It returns `409` while the counterparty still owns active external accounts: delete those accounts first, then delete the counterparty.

## Related

* [B2B payouts](/api-reference/guide-b2b-payouts): running payouts to many recipients
* [Bank transfers](/api-reference/guide-bank-transfers): rails, per-type bank fields, and registration details
* [External accounts](/payments/external-accounts): the full registration and lifecycle model
* [Crypto to fiat](/payments/guides/crypto-to-fiat): the underlying quote and transaction flow
