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

# Deposit addresses

> Reusable on-chain addresses that auto-convert incoming crypto and pay out to a bank account.

A deposit address is a reusable on-chain address assigned to a customer. When crypto arrives at the address, OMS automatically creates and executes a transaction that converts it and pays out to a configured fiat destination (`cryptoToFiatAccount`). No developer action is required after the address is provisioned.

Deposit addresses are persistent. OMS keeps them active until they are frozen or closed.

<Note>
  Deposit addresses must be enabled for your project before you can create them, and the customer must be provisioned for them. To get set up, share your use case below.

  <Card title="Contact us" icon="envelope" href="https://polygon.technology/get-access?utm_source=docs&utm_medium=card&utm_campaign=oms_access">
    Tell us about your on-ramp flow and we'll enable deposit addresses for your project.
  </Card>
</Note>

## How it works

Once a deposit address is provisioned, you display its on-chain address to the customer. When a supported stablecoin arrives at that address, OMS:

1. Detects the inbound transfer on the source chain.
2. Creates a transaction whose `precursor` is `{ "type": "depositAddress", "id": "da_..." }`. Dereference the deposit address by that `id` for its inlet address and instructions.
3. Moves the transaction directly to `processing` (there is no quote step, because pricing cannot be locked before the funds arrive).
4. Converts the incoming crypto and delivers it to the configured fiat destination.

The resulting transaction carries `sourceToDestination: "cryptoToFiatAccount"` and follows the standard [transaction lifecycle](/payments/core-concepts/transaction-lifecycle), including webhook events.

## Creating a deposit address

Create a deposit address with `POST /deposit-addresses`:

```json theme={null}
{
  "customerId": "cst_...",
  "expectedSourceAsset": "usdc",
  "expectedSourceNetwork": "ethereum",
  "destination": {
    "type": "bankUs",
    "details": {
      "id": "ext_bankUs_...",
      "asset": "usd",
      "network": "ach",
      "accountHolder": "customer"
    }
  },
  "label": "Inbound USDC deposits"
}
```

| Field                   | Required | Meaning                                                                                                                                                                                                                                                                                                                                                                                      |
| ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `customerId`            | Yes      | The customer the address belongs to.                                                                                                                                                                                                                                                                                                                                                         |
| `expectedSourceAsset`   | Yes      | The inbound stablecoin the address expects: `usdc` or `usdt` (lowercase).                                                                                                                                                                                                                                                                                                                    |
| `expectedSourceNetwork` | Yes      | The chain the address accepts funds on. One of the [supported crypto networks](/payments/core-concepts/currencies-and-rails#crypto-assets-and-networks).                                                                                                                                                                                                                                     |
| `destination`           | Yes      | A registered bank-type [external account](/payments/external-accounts) (`bankUs`, `bankIban`, or `bankCanada`) on the standard side shape. OMS validates the `details` (asset, network, and `accountHolder`) against the resolved external account. Certain destinations accept an optional `details.memo` or, for ACH, `details.companyDiscretionaryData`; see [Payout memo](#payout-memo). |
| `returnDestination`     | No       | Where to return the inbound crypto if the payout cannot be completed: a multi-asset OMS wallet or a registered external wallet, plus the `network` to return on, which must match `expectedSourceNetwork`. When omitted, funds return to the on-chain sender. See [failed transactions and returns](/payments/core-concepts/transaction-lifecycle#failed-transactions-and-returns).          |
| `sponsorGas`            | No       | When `true` (the default), OMS absorbs the on-chain gas cost for the destination delivery. Only `true` is currently supported.                                                                                                                                                                                                                                                               |
| `label`, `metadata`     | No       | A display label and free-form string metadata.                                                                                                                                                                                                                                                                                                                                               |

The `201` response returns the deposit address with `depositInstructions: null`. Provisioning populates the OMS-owned inlet address asynchronously, and the address moves from `pending` to `active` once the instructions are ready.

## Deposit instructions

The `depositInstructions` field carries the details to display in your UI. It is null until provisioning completes:

```json theme={null}
{
  "address": "0xabc123...",
  "asset": "usdc",
  "network": "ethereum",
  "expiresAt": null
}
```

| Field       | Meaning                                                                                    |
| ----------- | ------------------------------------------------------------------------------------------ |
| `address`   | The OMS-owned on-chain inlet address for this deposit address. Give this to your customer. |
| `asset`     | The stablecoin the address accepts (matches `expectedSourceAsset`).                        |
| `network`   | The chain the address accepts funds on (matches `expectedSourceNetwork`).                  |
| `expiresAt` | Reserved for a future provider-imposed inlet expiry. Null today.                           |

Crypto sent to `address` is converted and paid out to the configured fiat destination.

<Note>
  The OMS-managed wallet that backs a deposit address is reserved for that address's auto-conversion flow. Referencing the same custodial wallet on the source or destination of a quote, a cash-in, a cash-out, or a debit-card push is refused with `422 walletBoundToDepositAddress`. The wallet is also filtered out of a project-wide wallet listing so it does not appear as an independent balance. Use a different wallet for those flows.
</Note>

## Payout memo

A deposit address destination can carry an optional customer-supplied payment memo that OMS delivers to the beneficiary's bank in place of the memo OMS would otherwise generate. Set `destination.details.memo` on create or on a `PATCH` that replaces `destination`.

| Rule          | Value                                                                                                                          |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Type          | Optional string or `null`, up to 140 characters.                                                                               |
| Character set | Letters, digits, space, and `/?:().,'+-`.                                                                                      |
| Honored on    | `bankUs` destinations with `network: "wire"`; `bankIban` destinations (SWIFT); `bankCanada` destinations on the USD/SWIFT leg. |
| Edits         | Take effect on future payouts only. In-flight payouts keep the memo they were built with.                                      |
| Clearing      | Set `memo` to `null` (or omit `details.memo` on a `PATCH` that replaces `destination`) to fall back to the generated memo.     |

`memo` is not honored on `bankUs` destinations with `network: "ach"` or `network: "achSameDay"`, on the CAD/local leg of `bankCanada`, on [virtual accounts](/payments/virtual-accounts), or on quote requests. A non-empty value on those surfaces is rejected with `422 memoNotSupported`. A value outside the allowed character set or over 140 characters is rejected with `422 validationError`. An omitted, `null`, or whitespace-only value is accepted everywhere.

```json theme={null}
{
  "destination": {
    "type": "bankUs",
    "details": {
      "id": "ext_bankUs_...",
      "asset": "usd",
      "network": "wire",
      "accountHolder": "customer",
      "memo": "INVOICE 4482 CUSTOMER 991"
    }
  }
}
```

### ACH company discretionary data

For a `bankUs` destination with `network: "ach"` or `network: "achSameDay"`, set an optional `destination.details.companyDiscretionaryData`. OMS carries the value in the NACHA batch header on every outbound ACH payout from the deposit address. This is the originator's internal metadata and never reaches the beneficiary; it is distinct from `memo`, which does.

| Rule          | Value                                                                   |
| ------------- | ----------------------------------------------------------------------- |
| Type          | Optional string or `null`, up to 20 characters.                         |
| Character set | Uppercase NACHA set: `A-Z`, `0-9`, space, and `& - . $ * / # @ %`.      |
| Honored on    | `bankUs` destinations with `network: "ach"` or `network: "achSameDay"`. |
| Rejected on   | `bankUs` with `network: "wire"`; `422 memoNotSupported`.                |

## Customer summary

Deposit addresses carry a `customer` summary resolving the owning customer in one hop:

```json theme={null}
"customer": { "id": "cst_...", "name": "Jane Doe" }
```

The field is present on `GET /deposit-addresses/{depositAddressId}`, on every entry of `GET /deposit-addresses`, on `POST /deposit-addresses` and `PATCH /deposit-addresses/{depositAddressId}` responses, and on the deposit-address webhook payloads. The `destination` instrument also carries an opaque `displayName` you can render as-is. See [Customer summary on a transaction](/payments/transactions#customer-summary-on-a-transaction) and [Instrument display name](/payments/transactions#instrument-display-name) for the shared model.

## Listing and retrieving

`GET /deposit-addresses` lists deposit addresses across every customer in your organization. Both filters are optional: `customerId` scopes the list to one customer, and `status` to one lifecycle state. Paginate with `limit`, `startingAfter`, and `endingBefore`; each page returns `nextCursor`, `previousCursor`, and `hasMore`.

`GET /deposit-addresses/{depositAddressId}` fetches a single deposit address by ID.

## Updating

`PATCH /deposit-addresses/{depositAddressId}` accepts `destination` (re-point to a different bank-type external account), `returnDestination`, `label`, `metadata`, and `sponsorGas`; any other key in the body is rejected with `400`.

Re-pointing `destination` to a healthy bank external account recovers a deposit address from `inactiveActionRequired` back to `active`. A re-point on an already `active` address updates the target without a status transition.

There is no delete endpoint for deposit addresses.

## Statuses

| Status                   | Meaning                                                                                                                   |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| `pending`                | Created; OMS is provisioning the on-chain inlet address. `depositInstructions` is null.                                   |
| `active`                 | Provisioned and accepting deposits.                                                                                       |
| `frozen`                 | Temporarily suspended; inbound deposits are not processed.                                                                |
| `closed`                 | Permanently closed.                                                                                                       |
| `failed`                 | Provisioning failed; `failureReason` identifies the cause.                                                                |
| `inactiveActionRequired` | The destination external account is no longer usable. Re-point `destination` to a healthy account to recover to `active`. |

## Simulating inbound deposits

Sandbox deposit addresses accept real testnet transfers. Fund the address's on-chain inlet from a testnet faucet (for example, [Circle's testnet USDC faucet](https://faucet.circle.com/) on Sepolia), and OMS reacts to the on-chain confirmation just as it would to a mainnet deposit: the standard `cryptoToFiatAccount` transaction is auto-created and progresses through the [transaction lifecycle](/payments/core-concepts/transaction-lifecycle), firing the same webhook events.

There is no sandbox-only simulation endpoint for a deposit-address inbound. The fiat sibling on virtual accounts (see [Simulating inbound deposits](/payments/virtual-accounts#simulating-inbound-deposits)) still exists because bank rails have no public testnet.

## Deposit address vs. virtual account

Both are persistent auto-route configurations. The difference is which side is fiat:

|                 | Deposit address        | Virtual account                 |
| --------------- | ---------------------- | ------------------------------- |
| Incoming funds  | Crypto (on-chain)      | Fiat (bank rail)                |
| Deposit details | On-chain inlet address | Bank account number and routing |
| Direction       | `cryptoToFiatAccount`  | `fiatAccountToCrypto`           |
| Destination     | Fiat account           | Crypto wallet                   |

## Related

* [Deposit addresses guide](/payments/guides/deposit-addresses): walkthrough of the inbound flow and webhook handling
* [Virtual accounts](/payments/virtual-accounts): the fiat equivalent, a bank account number that auto-converts to crypto
* [External accounts](/payments/external-accounts): registering the bank account a deposit address pays out to
* [Transaction lifecycle](/payments/core-concepts/transaction-lifecycle): statuses, sub-statuses, and webhook events for the auto-created transaction
* [Failed transactions and returns](/payments/core-concepts/transaction-lifecycle#failed-transactions-and-returns): where inbound crypto goes when the payout cannot complete, and how to configure it
