> ## 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.

# Entities and relationships

> The core resources in OMS and how they relate to each other.

Every OMS integration is built from a small set of resources. The API-managed resources are Customers, Wallets (custodial), Counterparties, External Accounts, Virtual Accounts, Deposit Addresses, Quotes, Transactions, Cash-ins, and Webhooks. Understanding the relationships between them is the fastest way to design a correct integration.

## The entity model

```
Customer
├── Wallets            (custodial stablecoin balances, created and listed under the customer)
├── Counterparties     (people and businesses the customer transacts with)
├── Virtual Accounts   (persistent bank account numbers)
├── Deposit Addresses  (persistent onchain addresses)
└── External Accounts  (registered bank accounts, debit cards, and external wallets,
                        owned by the customer or one of its counterparties)

Quote  →  Transaction
           └── sourceToDestination inferred from the instruments
               (cryptoToCrypto, cryptoToFiatAccount, cryptoToCash,
                fiatAccountToCrypto, cashToCrypto)

Cash-in  (code-based cash deposit → auto-creates Transaction)

Webhooks  (API-managed subscriptions, full CRUD)
```

All financial operations belong to a `Customer`. A customer has zero or more wallets. Counterparties, virtual accounts, deposit addresses, quotes, and transactions are also scoped to a customer; external accounts belong to a customer or to one of its counterparties. Webhook subscriptions are managed through the API independently of any customer.

## Customers

A customer is an identity record. Before a customer can move money, OMS must grant **endorsements** that unlock specific capabilities.

| Endorsement     | Unlocks                              |
| --------------- | ------------------------------------ |
| `basic`         | Standard operations                  |
| `cryptoCustody` | Crypto custody and advanced features |
| `usd`           | USD stablecoin operations            |

Customers are created via `POST /customers` with a `type` (for example `individual`) and an `endorsements` array. Endorsements are granted after KYC/KYB verification; a webhook fires as they change.

## Wallets

The Payments API `wallet` resource is custodial: OMS manages the keys, and they never leave OMS infrastructure. Wallets hold stablecoin balances (USDC by default) and are the source or destination for all transactions.

Wallets are created and listed under the customer: `POST /customers/{id}/wallets` (body specifies `asset` and `chain`) and `GET /customers/{id}/wallets`. Each wallet holds a single asset on one chain and has an onchain address. `GET /wallets/{id}/balance` returns that wallet's current `balance` for its asset and chain.

For user-controlled keys (onchain consumer apps, agentic flows), use [OMS non-custodial wallets](/wallets/non-custodial-wallets). The two models can be combined.

## Virtual accounts

A dedicated bank account number assigned to a customer. When fiat arrives via a supported bank rail, OMS automatically creates a `fiatAccountToCrypto` transaction and delivers USDC to the customer's wallet.

Create one with `POST /virtual-accounts`; the body specifies the `customerId`, the `source` asset and network, a `destination` (an OMS wallet, or a registered external wallet by ID), the `accountHolder` (always `customer`), and the account `type` (`bankUs`). The response's `bankDetails` is null until the underlying deposit account is provisioned. Virtual accounts support list, get, and update (`GET /virtual-accounts`, `GET`/`PATCH /virtual-accounts/{id}`). Deletion is asynchronous: `DELETE /virtual-accounts/{id}` returns `202`, and the status finalizes to `deleted` once the underlying account closes.

## Deposit addresses

A persistent onchain address. When crypto arrives, OMS automatically creates and executes a transaction that delivers fiat to a registered bank external account.

Create one with `POST /deposit-addresses`; the body specifies the `customerId`, the expected source asset (`usdc` or `usdt`) and network, and a registered bank external account as the `destination`. The response's `depositInstructions` is null until provisioning populates the OMS-owned inlet address. Deposit addresses support list, get, and update (`GET /deposit-addresses`, `GET`/`PATCH /deposit-addresses/{id}`); there is no delete. Deposit addresses must be enabled for your project: contact us to enable them.

## Counterparties

A person or business a customer transacts with, scoped to that customer. Create one with `POST /counterparties`; the body requires `customerId` and `name`, with optional identity fields (`entityType`, `email`, `phone`, `dateOfBirth`, `taxId`, `nationality`, `address`, `metadata`). The `address` object takes `streetAddress`, `city`, `postalCode`, and `country`, plus an optional `countryArea`.

Counterparties support full CRUD. Listing requires the `customerId` query parameter (`GET /counterparties?customerId=...`). A counterparty can own external accounts; `DELETE /counterparties/{id}` returns `409` while the counterparty still owns active external accounts.

## External accounts

A registered bank account, debit card, or external wallet, owned by a customer or by one of the customer's counterparties. External accounts are referenced by ID as the source for on-ramps or the destination for off-ramps.

Register one with `POST /external-accounts`. The body specifies the `owner` (`{ kind: "customer", customerId }` or `{ kind: "counterparty", counterpartyId }`), a `type` (`bankUs`, `bankIban`, `bankCanada`, `card`, or `walletExternal`), and exactly one per-type details object matching the `type`. Debit cards register through this same endpoint. `GET /external-accounts` requires a `customerId` and accepts an optional `counterpartyId` filter; `PATCH` updates `label` and `metadata`; `DELETE` removes the registration.

ID prefixes: `ext_card_` (debit cards), `ext_bankUs_` (US banks), `ext_bankIban_` (IBAN banks), `ext_bankCa_` (Canadian banks), `ext_wlt_` (external wallets).

## Quotes and transactions

The two-step flow for most money movement:

1. `POST /quotes`: lock pricing, return full fee breakdown
2. `POST /transactions`: execute against the locked quote

Quotes expire if not used within the validity window. `pricing.fixedAmountSide` indicates which side of the trade was specified.

## Cash-ins

A code-based deposit flow for in-person cash at retail locations. Creates a deposit code the customer presents at a partner location. OMS converts the deposited cash to USDC and auto-creates a transaction. No upfront amount is required.

## Webhooks

API-managed event subscriptions with full CRUD. Register a subscription with `POST /webhooks` (body `{ url, events }`) and OMS delivers events as state changes occur; each delivery carries the full object so your handler branches on its `status`. Subscribe to specific event types, or pass an empty `events` array (or `["*"]`) to receive all of them. Subscriptions are created, listed, updated, and deleted through the API (`GET`/`PATCH`/`DELETE /webhooks/{id}`) as well as in the dashboard. The create response returns a signing secret once for verifying the `Webhook-Signature` header.

<Note>
  Virtual accounts, deposit addresses, and cash-ins all bypass the quote step. They go directly to `processing` because OMS cannot lock pricing before the funds arrive.
</Note>
