Skip to main content
An Orchestration Address is the inverse of a Virtual Account:
Virtual AccountOrchestration Address
DirectionFiat → StablecoinStablecoin → Fiat
Deposit methodBank transfer (wire / ACH)On-chain stablecoin transfer
DestinationA crypto walletA bank account
Each Orchestration Address is bound to one user, one chain, one source token (USDC or USDT), and one destination payout account. The address is persistent — once created it lives forever and keeps accepting deposits, even after deactivation.

Common Use Cases

Merchant settlement

Give customers a stable on-chain address to pay into. Auto-settle to your bank daily with SCHEDULED mode.

Payment processing

Issue per-customer addresses and settle each payment independently for clean reconciliation. Best paired with PER_DEPOSIT mode.

Treasury sweeps

Accumulate stablecoin revenue across wallets and sweep to fiat on a fixed cadence. SCHEDULED mode (DAILY / WEEKLY) keeps your bank balance predictable.

Payouts collection

Collect stablecoin from multiple senders and convert to USD once a meaningful balance accrues. THRESHOLD mode minimizes per-offramp fees.

OTC desks & exchanges

Automate fiat off-ramping without a manual quote-accept on every trade. PER_DEPOSIT gives each trade its own offramp record.

Subscription billing

Charge customers in stablecoin and convert to fiat on your billing cycle with SCHEDULED mode.

How Orchestration Addresses Work

1

Create the address

Configure a source (currency, chain), a USD destination payout account, and an orchestration mode. HIFI provisions a dedicated on-chain wallet and returns its address.
2

Receive stablecoin deposits

Senders transfer USDC or USDT on-chain to the address. HIFI detects each deposit via on-chain webhooks.
3

Automatic offramp

Based on the configured mode, HIFI batches eligible deposits and runs them through the standard offramp pipeline. USD lands in the destination account — no manual quote-accept step required.

Orchestration Modes

Choose one of three modes at create time. The mode is changeable later via the update endpoint.

PER_DEPOSIT

Every detected deposit becomes its own batch and offramp, immediately.Best for clients who want each customer payment to settle independently with full traceability.

SCHEDULED

Deposits accumulate until the next scheduled tick (HOURLY, DAILY, or WEEKLY), then roll up into a single batch.Best for predictable cadence or end-of-day sweeps.

THRESHOLD

Deposits accumulate until their aggregate amount reaches thresholdAmount, then roll up into a single batch.Best for minimizing offramp fees by waiting for a meaningful balance.
Every active address also supports a manual trigger that batches whatever is currently pending — regardless of mode — without advancing the SCHEDULED clock.

Supported Source Pairs

ChainUSDCUSDT
Ethereum, Polygon, Base, Solana
Tron
Unsupported pairs (for example, USDC on Tron) are rejected at create time.

Minimum Amounts

Every destination rail enforces a minimum amount. A batch is only created once the eligible PENDING deposits sum to at least that minimum.
RailMinimum
Wire, ACH, RTP1 USDC
SWIFT5 USDC
USDT (any rail)10 USDT
Mode-specific behavior:
  • PER_DEPOSIT — a deposit at or above the minimum is batched immediately; a sub-minimum deposit is held PENDING and swept into the next qualifying batch.
  • SCHEDULED — a tick whose PENDING total is below the minimum batches nothing; the deposits roll into the next tick.
  • THRESHOLDthresholdAmount is validated to be ≥ the rail minimum at create/update time, so a crossed threshold always clears it.
  • Manual trigger — returns triggered: false, reason: "below_offramp_minimum" if the pending total is below the minimum.

Creating an Orchestration Address

Create an address using the Create Orchestration Address endpoint.
curl -X POST "https://sandbox.hifibridge.com/v2/users/usr_abc123/orchestration-addresses" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "550e8400-e29b-41d4-a716-446655440000",
    "source": {
      "currency": "usdc",
      "chain": "BASE"
    },
    "destination": {
      "currency": "usd",
      "accountId": "acc_xyz789"
    },
    "mode": "PER_DEPOSIT"
  }'

Request Fields

requestId
string
required
Your idempotency key (UUID v4). Repeating the same requestId with the same payload returns the existing record; repeating it with a different payload returns 409 RESOURCE_CONFLICT identifying the first mismatched field (one of source.currency, source.chain, destination.currency, destination.accountId, mode, schedule.interval, or thresholdAmount).
source
object
required
The stablecoin and chain the address will accept.
destination
object
required
The USD payout account that will receive the offramped funds.
mode
string
required
Orchestration mode. One of PER_DEPOSIT, SCHEDULED, or THRESHOLD.
schedule
object
Required when mode = SCHEDULED. Must be omitted otherwise.
thresholdAmount
string
Required when mode = THRESHOLD. Must be omitted otherwise. Must be at least the destination rail’s offramp minimum.

Response

{
  "id": "oa_abc123",
  "userId": "usr_abc123",
  "address": "0xAbc...123",
  "source": { "currency": "usdc", "chain": "BASE" },
  "destination": { "currency": "usd", "accountId": "acc_xyz789" },
  "mode": "PER_DEPOSIT",
  "schedule": null,
  "thresholdAmount": null,
  "status": "ACTIVE",
  "createdAt": "2026-06-22T12:00:00.000Z",
  "updatedAt": "2026-06-22T12:00:00.000Z",
  "deactivatedAt": null
}
status may briefly be PENDING_WALLET while the on-chain wallet is being provisioned. The Create endpoint waits for provisioning to complete, so the typical response is already ACTIVE with address populated.

Managing the Address Lifecycle

Update

Update the mode, schedule, threshold, or destination account at any time while the address is ACTIVE. Updates do not affect offramps already in flight — only future deposits use the new configuration.

Deactivate

Deactivate the address with a walletAddress to receive any in-kind refunds. Deactivation:
  • Refunds all PENDING (not-yet-batched) deposits in-kind to walletAddress.
  • Lets in-flight PROCESSING batches continue to completion.
  • Stops offramping any new deposits — they are recorded as IGNORED with no automatic refund.
The on-chain address keeps receiving deposits even after deactivation, since the underlying wallet cannot be taken offline.

Manually trigger an orchestration

Call Trigger Orchestration to batch all currently-PENDING deposits immediately, regardless of mode. Idempotent — returns triggered: false with a reason when there is nothing to orchestrate.

Tracking Deposits and Batches

Each on-chain deposit is recorded as a deposit row; each produced offramp is recorded as a batch row.
ResourceStatusesUse
DepositPENDING, BATCHED, IGNOREDTrack individual on-chain transfers.
BatchPENDING, PROCESSING, COMPLETED, FAILEDTrack the offramp produced from a group of deposits.
Use List Deposits and List Batches to query history.
Get Orchestration Address (the single-address endpoint) also returns a live balance field — the on-chain balance of the source token held by the address — so you don’t need a separate provider call to check funds in flight.

Reconciling with offramps

Orchestration offramps flow through the same pipeline as direct offramps, so the existing offramp endpoints and webhooks work without changes:
  • Webhook events: the standard offramp progress events fire for orchestration offramps. Each event payload includes an orchestrationAddressId field — non-null when the offramp was produced by an orchestration address, null for direct offramps.
  • Cross-reference: Get Offramp includes orchestrationAddressId in its response, and a batch’s offrampTransactionId links to the full offramp record. You can pivot in either direction without an extra round-trip.

Ignored deposits

A deposit is recorded with status = IGNORED (and not offramped) in two cases:
  • ADDRESS_DEACTIVATED — the deposit arrived after the address was deactivated.
  • UNSUPPORTED_TOKEN — the sender used the wrong stablecoin (for example, sending USDT to a USDC-only address).
In both cases the funds remain in the on-chain wallet. Contact support to arrange a manual refund.

Failed batches

A batch can land in FAILED for one of two reasons, surfaced as failureReason:
  • ADDRESS_NOT_ACTIVE — the address was deactivated between batch creation and processing.
  • A terminal offramp status (NOT_INITIATED, QUOTE_FAILED, CRYPTO_FAILED, FIAT_FAILED, EXPIRED, REJECTED, CANCELLED) — the underlying offramp terminated. Compliance issues (lost product access, KYC rejection) surface here.
The deposits in a failed batch remain in BATCHED status and are not automatically retried. Contact support to re-batch them once any underlying issue is resolved.

Getting Help

  • 📧 Email: support@hifi.com
  • 💬 Slack: Message us in our shared Slack channel