# Manage omnibus with the API

Use this page for Omnibus operations with the API. For console procedures, see
[Manage an omnibus account in the UI](/products/custody/accounts-and-assets/omnibus/manage-omnibus-ui). For the
conceptual model, see [Omnibus](/products/custody/accounts-and-assets/omnibus/overview). For domain, system-signed
policy, and Gas Station setup, see
[Setup and governance](/products/custody/accounts-and-assets/omnibus/setup-and-governance).

API naming
The API uses `tenantId` and `/tenants` for Omnibus virtual account resources.
In these docs, a virtual account is the Omnibus object that holds an off-chain
position, and a tenant is the person or customer associated with that virtual
account.

## Omnibus actions

| Action | API procedure |
|  --- | --- |
| Create an omnibus structure | [Create an omnibus structure](#create-an-omnibus-structure) |
| View omnibus details | [View omnibus details](#view-omnibus-details) |
| Update the sponsoring Gas Station account | [Update the sponsoring Gas Station account](#update-the-sponsoring-gas-station-account) |
| Create a virtual account | [Create a virtual account](#create-a-virtual-account) |
| List or view virtual accounts | [List or view virtual accounts](#list-or-view-virtual-accounts) |
| Update a virtual account | [Update a virtual account](#update-a-virtual-account) |
| Lock or unlock a virtual account | [Lock or unlock a virtual account](#lock-or-unlock-a-virtual-account) |
| Create or view a deposit wallet | [Create a deposit wallet](#create-a-deposit-wallet) |
| List deposit wallets | [List deposit wallets](#list-deposit-wallets) |
| Initiate a withdrawal | [Initiate a withdrawal](#initiate-a-withdrawal) |
| Create or track internal transfers | [Create and track internal transfers](#create-and-track-internal-transfers) |
| Set sweep thresholds | [Manage sweep thresholds](#manage-sweep-thresholds) |
| Release quarantined deposits | [Release quarantined transfers](#release-quarantined-transfers) |
| Review balances | [Balances](/products/custody/accounts-and-assets/omnibus/balances-and-reconciliation) |


## API reference and shared process

| Task | Reference |
|  --- | --- |
| Check the endpoint schema | [Omnibus](/products/custody/reference/api/openapi/omnibus), [tenants](/products/custody/reference/api/openapi/tenants), [deposits](/products/custody/reference/api/openapi/deposits), [withdrawals](/products/custody/reference/api/openapi/withdrawals), and [internal transfers](/products/custody/reference/api/openapi/internal-transfers) in the API reference |
| Submit a returned unsigned intent | [Manage intents and approvals](/products/custody/governance/intents/manage-intents-and-approvals) |
| Sign an API request payload | [Sign intents](/products/custody/identity-and-access/authentication/authenticate-api-requests#signing-intents-state-mutation-operations) |
| Configure Gas Station sponsorship | [Manage a gas station with the API](/products/custody/accounts-and-assets/gas-station/manage-gas-station-api) |


Omnibus create and withdrawal requests return an unsigned Custody `Propose`
intent. Sign the returned intent and submit it to `POST /v1/intents` in the
`request` field.

Deposit-wallet creation, deposit sweeps, and ledger propagation use Omnibus
system-signed automation after the required `SystemSigned` policy is in place.
Other Omnibus management calls are direct Omnibus API calls and do not use the
standard intent proposal endpoint.

Omnibus supports one omnibus structure per domain. If
`GET /v1/domains/{domainId}/omnibus` returns an existing structure, use its
`id` field for management calls instead of creating another structure.

## Create an omnibus structure

Before creating an omnibus structure, complete the planning steps in
[Setup and governance](/products/custody/accounts-and-assets/omnibus/setup-and-governance). Then call
`POST /v1/domains/{domainId}/omnibus`:

```sh
curl -X POST "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "alias": "primary-omnibus",
    "vaultId": "vault-uuid",
    "keyStrategy": "Random",
    "lockStatus": "Unlocked",
    "ledgerIds": ["ledger-id"],
    "description": "Primary omnibus structure",
    "customProperties": {
      "externalReference": "omnibus-001"
    },
    "ignoredAccountIds": ["gas-station-account-uuid"],
    "sponsoringGasStationId": "gas-station-account-uuid"
  }'
```

| Field | Required | Description |
|  --- | --- | --- |
| `alias` | Yes | Alias for the omnibus account. |
| `vaultId` | Yes | Vault that stores the omnibus account keys. |
| `keyStrategy` | Yes | Key strategy: `VaultHard`, `VaultSoft`, or `Random`. |
| `lockStatus` | No | Initial lock status: `Unlocked` or `Locked`. To lock or unlock the structure after creation, lock or unlock the omnibus wallet account with the core account operations. See [Lock or unlock an account](/products/custody/accounts-and-assets/accounts/manage-accounts-api#lock-or-unlock-an-account). |
| `ledgerIds` | No | Ledgers to activate on the omnibus account. If omitted, Omnibus activates compatible enabled ledgers. |
| `description` | No | Optional account description. |
| `customProperties` | No | Custom key-value properties for the omnibus account. |
| `ignoredAccountIds` | No | Custody account IDs to ignore during event processing, such as a Gas Station account. |
| `sponsoringGasStationId` | No | Gas Station account used for supported non-native sweep gas funding. |


Before you set `sponsoringGasStationId`, confirm that the account has an active
Gas Station sponsor configuration. A Gas Station configuration with
`type: "none"` disables sponsorship and does not make the account an active
sponsor.

Successful create requests return `201 Created` with the created `omnibus`
object and an `unsignedIntent`. Sign the returned Custody `Propose` intent and
submit it to `POST /v1/intents` in the `request` field. If an omnibus structure
already exists for the domain, the API returns `409 Conflict`.

## View omnibus details

Call `GET /v1/domains/{domainId}/omnibus` to get the omnibus structure for a
domain:

```sh
curl -X GET "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus" \
  -H "Authorization: Bearer ${JWT_TOKEN}"
```

Call `GET /v1/domains/{domainId}/omnibus/{omnibusId}` when you already know the
omnibus ID:

```sh
curl -X GET "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}" \
  -H "Authorization: Bearer ${JWT_TOKEN}"
```

Omnibus structure status values are `CREATING`, `PENDING_SPONSORSHIP`,
`ACTIVE`, and `FAILED`. Responses also include a separate `lockStatus` field
with values `UNLOCKED` or `LOCKED`.
Responses can include host virtual account balances. For balance behavior, see
[Balances](/products/custody/accounts-and-assets/omnibus/balances-and-reconciliation).

## Update the sponsoring Gas Station account

Use `PUT /v1/domains/{domainId}/omnibus/{omnibusId}` to update the Gas Station
account used for supported non-native sweep gas funding.

The current update request accepts `sponsoringGasStationId`. It does not accept
`ignoredAccountIds`; set `ignoredAccountIds` when creating the omnibus structure
and verify returned omnibus details after changing the sponsor account.

Before updating `sponsoringGasStationId`, confirm that the account has an active
Gas Station sponsor configuration. Use `GET /v1/domains/{domainId}/sponsors` to
list sponsor accounts and
`GET /v1/domains/{domainId}/account/{accountId}/sponsor` to inspect the sponsor
account's configuration. A Gas Station configuration with `type: "none"`
disables sponsorship and does not make the account an active sponsor.

```sh
curl -X PUT "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "sponsoringGasStationId": "gas-station-account-uuid"
  }'
```

## Create a virtual account

Use `POST /v1/domains/{domainId}/omnibus/{omnibusId}/tenants` to create a
virtual account for a tenant in an omnibus structure.

```sh
curl -X POST "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/tenants" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "alias": "tenant-a-virtual-account",
    "description": "Virtual account for Tenant A",
    "status": "UNLOCKED"
  }'
```

| Field | Required | Description |
|  --- | --- | --- |
| `alias` | Yes | Alias for the virtual account. |
| `description` | No | Optional description. |
| `status` | No | Virtual account status: `LOCKED` or `UNLOCKED`. |
| `customProperties` | No | Optional custom key-value properties. |


Successful create requests return `201 Created`.

## List or view virtual accounts

Use `GET /v1/domains/{domainId}/omnibus/{omnibusId}/tenants` to list
virtual accounts:

```sh
curl -X GET "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/tenants?page=0&size=20&status=UNLOCKED" \
  -H "Authorization: Bearer ${JWT_TOKEN}"
```

The list endpoint supports `page`, `size`, `search`, and `status` query
parameters. Use `status` to filter by `LOCKED` or `UNLOCKED`. The `search`
parameter performs a case-insensitive alias substring match. Search terms shorter
than three characters return an empty page.

List responses contain `content` and `page`.

Use `GET /v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}` to view
one virtual account:

```sh
curl -X GET "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}" \
  -H "Authorization: Bearer ${JWT_TOKEN}"
```

Virtual account responses include `id`, `omnibusId`, `alias`, `isHost`, `status`,
`createdAt`, and `updatedAt`. They can also include `balances`, `description`,
and `customProperties`.

## Update a virtual account

Use `PUT /v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}` to
replace mutable virtual account metadata.

```sh
curl -X PUT "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "alias": "tenant-a-virtual-account-updated",
    "description": "Updated virtual account description",
    "status": "UNLOCKED"
  }'
```

The request accepts the same fields as virtual account creation. Successful update
requests return `200 OK`.

## Lock or unlock a virtual account

Use `POST /v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/lock` to
lock a virtual account.

Lock a virtual account to block new operations for the associated tenant:

```sh
curl -X POST "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/lock" \
  -H "Authorization: Bearer ${JWT_TOKEN}"
```

Use `POST /v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/unlock`
to unlock a virtual account.

Unlock the virtual account when the associated tenant can resume normal operations:

```sh
curl -X POST "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/unlock" \
  -H "Authorization: Bearer ${JWT_TOKEN}"
```

Virtual account lock and unlock endpoints do not take a request body. Successful
requests return `200 OK`.

## List deposit wallets

Use `GET /v1/domains/{domainId}/omnibus/{omnibusId}/deposit-wallets` to list
deposit wallets for an omnibus structure:

```sh
curl -X GET "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/deposit-wallets?page=0&size=20&search=tenant-a" \
  -H "Authorization: Bearer ${JWT_TOKEN}"
```

The list endpoint supports `page`, `size`, `search`, and `custodyAccountIds`
query parameters. Use `custodyAccountIds` to filter by one or more custody
account IDs. List responses contain `content` and `page`.

## Create a deposit wallet

Use [POST `/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/deposit-wallet`](/products/custody/reference/api/openapi/deposits/createdepositwallet) to create the deposit wallet for a virtual account on its first deposit request:

```sh
curl -X POST "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/deposit-wallet" \
  -H "Authorization: Bearer ${JWT_TOKEN}"
```

This is a direct Omnibus API call — it does not return an unsigned intent. Behind it, Omnibus submits a system-signed `v0_CreateAccount` intent, so the required `SystemSigned` policy must be in place. A `201 Created` response contains the wallet `status` and `addresses`.

Use `GET` on the same path to retrieve the deposit wallet's status and addresses later. Deposit-wallet creation has no console procedure: tenants trigger it through your integration. For the deposit lifecycle, see [Deposits](/products/custody/accounts-and-assets/omnibus/deposits).

## Initiate a withdrawal

Use [POST `/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/withdrawals`](/products/custody/reference/api/openapi/withdrawals/createwithdrawal) to move funds from a virtual account to an external destination:

```sh
curl -X POST "${CUSTODY_API_URL}/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/withdrawals" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: {client-chosen-key}" \
  -d '{
    "amount": "1000000",
    "tickerId": "ticker-uuid",
    "ledgerId": "ledger-id",
    "destAddress": "destination-address"
  }'
```

| Field | Required | Description |
|  --- | --- | --- |
| `amount` | Yes | Positive integer string in the ticker's smallest unit. |
| `tickerId` | Yes | Ticker to withdraw. |
| `ledgerId` | Yes | Blockchain ledger to broadcast on. |
| `destAddress` | Yes | Destination address outside this omnibus. |


The required `Idempotency-Key` header carries a client-chosen key that makes the withdrawal idempotent. Reuse the exact same value on every retry of the same withdrawal, and use a new value for each new withdrawal. Requests with a missing or blank key return `400`. Omnibus derives the `operationId` deterministically from the key, so a retried request resolves to the original operation instead of creating a duplicate withdrawal.

Successful requests return `201 Created`:

- **Fresh create**: the reservation is taken, and the response contains the `withdrawal` object and an `unsignedIntent`. Sign the returned Custody `Propose` intent and submit it to `POST /v1/intents` in the `request` field.
- **Pending replay** (same key, still in progress): the response contains the original operation and its `unsignedIntent`; no new reservation is taken.
- **Terminal replay** (the operation already reached `COMPLETED`, `FAILED`, or `CANCELLED`): the response contains the operation status only, with no `unsignedIntent` and no reservation.


The withdrawal object contains `operationId`, `transferId`, `status`, `amount`, `tickerId`, `ledgerId`, `destAddress`, `createdAt`, and `updatedAt`. It can also include `estimatedFee` and `custodyTransactionOrderId`. Withdrawal status values are `PENDING`, `IN_PROGRESS`, `COMPLETED`, `FAILED`, and `CANCELLED`.

For the withdrawal lifecycle, balance reservation, fee handling, and failure behavior, see [Withdrawals](/products/custody/accounts-and-assets/omnibus/withdrawals).

## Create and track internal transfers

Internal transfers are asynchronous: Omnibus accepts the request, durably persists the operation, and returns `202 Accepted` with `status: "PENDING"` immediately. Poll the operation for the terminal status.

[POST `/v1/domains/{domainId}/omnibus/{omnibusId}/tenants/{tenantId}/internal-transfers`](/products/custody/reference/api/openapi/internal-transfers/createinternaltransfer) requires an `Idempotency-Key` header and accepts:

| Field | Required | Description |
|  --- | --- | --- |
| `destTenantId` | Yes | Destination virtual account ID. |
| `amount` | Yes | Positive integer string in the ticker's smallest unit. |
| `tickerId` | Yes | Ticker to transfer. |
| `ledgerId` | Yes | Ledger for the transfer. |


The `Idempotency-Key` header carries a client-chosen, per-transfer token, unique within the source tenant. Reuse the exact same value on every retry of the same transfer, and use a new value for each new transfer. Requests with a missing or blank key return `400`. Reusing a key with a different payload returns `409`. Omnibus derives the `operationId` deterministically from the key, so a retried request resolves to the same operation instead of creating a duplicate transfer.

Successful requests return `202 Accepted` with `operationId`, `transferId`, `status: "PENDING"`, `sourceTenantId`, `destTenantId`, `amount`, `tickerId`, and `ledgerId`. When the workflow completes, the Accounting Service has recorded both sides of the movement in one double-entry operation.

[GET `/v1/domains/{domainId}/omnibus/{omnibusId}/internal-transfers/{operationId}`](/products/custody/reference/api/openapi/internal-transfers/getinternaltransfer) returns the current state of a transfer. Poll it after the `202` until the status is terminal (`COMPLETED` or `FAILED`) or `PENDING_VERIFICATION`. Reads are eventually consistent.

[GET `/v1/domains/{domainId}/omnibus/{omnibusId}/internal-transfers`](/products/custody/reference/api/openapi/internal-transfers/getinternaltransfers) lists internal transfers for an omnibus structure. The list endpoint supports:

| Query parameter | Description |
|  --- | --- |
| `page` | Page number. |
| `size` | Page size. |
| `tenantId` | Filter by source or destination virtual account. |
| `role` | Use with `tenantId` to restrict the tenant filter to `SOURCE` or `DEST`. |
| `status` | Filter by one or more transfer statuses: `PENDING`, `IN_PROGRESS`, `COMPLETED`, `FAILED`, `CANCELLED`, or `PENDING_VERIFICATION`. |
| `tickerId` | Filter by ticker. |
| `ledgerIds` | Filter by one or more ledgers. |
| `createdAfter` | Include transfers created after this timestamp. |
| `createdBefore` | Include transfers created before this timestamp. |
| `sort` | Sort expression. |


List responses contain `content` and `page`.

For validation rules and the settlement model, see [Internal transfers](/products/custody/accounts-and-assets/omnibus/internal-transfers).

## Manage sweep thresholds

Sweep thresholds are keyed by ticker and ledger pair, expressed in the ticker's smallest unit. Assets without a configured threshold default to `"0"`, which sweeps immediately. For the threshold model, see [Dust thresholds](/products/custody/accounts-and-assets/omnibus/deposits#dust-thresholds).

[GET `/v1/domains/{domainId}/sweep-thresholds`](/products/custody/reference/api/openapi/sweep-thresholds/getsweepthresholds) lists the threshold for every asset in the Ripple Custody catalog, optionally filtered by `ledgerId`. Each configured row carries a `version` value for optimistic locking.

[PUT `/v1/domains/{domainId}/sweep-thresholds`](/products/custody/reference/api/openapi/sweep-thresholds/updatesweepthresholds) upserts multiple thresholds in one transaction:

```sh
curl -X PUT "${CUSTODY_API_URL}/v1/domains/{domainId}/sweep-thresholds" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "updates": [
      {
        "tickerId": "ticker-uuid",
        "ledgerId": "ledger-id",
        "minSweepAmount": "1000000",
        "version": 3
      }
    ]
  }'
```

Updates apply atomically: if any update fails, the API rolls back the entire request. To change an already-configured asset, send the `version` from the corresponding GET row; omit it when configuring an asset for the first time. If any submitted `version` no longer matches the stored row, the whole request returns `409` and nothing is written.

## Release quarantined transfers

Omnibus does not sweep quarantined deposits. Release held transfers with a `v0_ReleaseQuarantinedTransfers` intent, or configure an [automatic quarantine release policy](/products/custody/compliance/transaction-screening/automatic-quarantine-release-policy). See [Receive assets with the API](/products/custody/transactions/send-and-receive/receive-assets-api).

## Operational notes

Omnibus workflows use stable identifiers for idempotency:

- Custody event IDs for event-driven deposit and sweep operations.
- Omnibus operation IDs for internal transfers.
- Custody transaction order IDs for withdrawals.


The current Omnibus API exposes balances as fields on omnibus and virtual account
responses rather than as standalone balance endpoints.

## Related topics

| Topic | Documentation |
|  --- | --- |
| UI procedures | [Manage an omnibus account in the UI](/products/custody/accounts-and-assets/omnibus/manage-omnibus-ui) |
| Setup and creation | [Setup and governance](/products/custody/accounts-and-assets/omnibus/setup-and-governance) |
| Deposit processing | [Deposits](/products/custody/accounts-and-assets/omnibus/deposits) |
| Withdrawal processing | [Withdrawals](/products/custody/accounts-and-assets/omnibus/withdrawals) |
| Intra-omnibus movement | [Internal transfers](/products/custody/accounts-and-assets/omnibus/internal-transfers) |
| Balance behavior | [Balances](/products/custody/accounts-and-assets/omnibus/balances-and-reconciliation) |