magic

How ACH payouts work through Bridge

Bridge (bridge.xyz) is the payout rail of Magic's dollar mode. Its liquidation addresses turn a USDC transfer into a bank payment with no manual step: USDC arrives at an address, Bridge converts it to dollars and pays a bank account by ACH. Creator fees are held in the MagicTreasury on BNB Chain until each payout cycle; this page covers everything from the moment a creator's share leaves the treasury to the moment it lands in their X Money balance, exactly as Bridge documents it. Every Bridge endpoint, field, state and timing below is taken from Bridge's API documentation at apidocs.bridge.xyz, and each part lists the pages it relies on.

Paths are relative to https://api.bridge.xyz/v0. Every request authenticates with an Api-Key header, and every POST Magic makes carries an Idempotency-Key header.

Who is who

Bridge objectIn MagicHow many
DeveloperMagic: holds the API key and receives the webhooksOne
CustomerMagic's operating company, onboarded as a business customerOne
External accountA creator's X Money account: account and routing number, the creator's name and addressOne per creator (a new one if the creator changes details)
Liquidation addressThe creator's personal payout address on Base, bound to that external account, paying out in USD by ACHOne per creator
DrainOne payout: a USDC deposit to the address, converted and paid by ACHOne per payout
Magic  (Bridge developer: API key, webhook endpoint)
└── Customer: Magic's operating company  (type "business")
    ├── External account ── creator A's X Money  (individual, checking)
    │     └── Liquidation address ── 0x…A on Base: USDC in, USD out by ACH
    │           └── Drains ── one per payout: deposit tx hash → ACH trace number
    ├── External account ── creator B's X Money
    │     └── Liquidation address ── 0x…B on Base
    └── …

Bridge has two kinds of customer, individuals and businesses. Magic's company is onboarded once, through Bridge's hosted onboarding (POST /kyc_links, with "type": "business") or the Customers API (POST /customers). Creators are not Bridge customers and never see a Bridge screen: each creator's X Money account is registered as an external account under Magic's customer — the pattern Bridge's cross-border payments guide uses for a business that pays its suppliers, with "an external account that stores a supplier's bank details".

A liquidation address is, in Bridge's words, "a permanent payment route which ties a blockchain address to either a fiat or blockchain address". Bridge refuses to create a second liquidation address for the same customer with the same source chain, source currency and destination. Every Magic address has a different destination — the creator's own external account — so the rule also works as a guard: one creator, one address.

Sources: Create your first customer · Customers overview · Cross-border payments · Liquidation address · Authentication · Idempotence

Registering the creator's X Money account

A creator signs in with X once on the Magic site and enters their X Money account and routing number once. Until then, their share accumulates in the MagicTreasury under their handle, and it never expires. Magic registers the details with Bridge:

POST /customers/{customerID}/external_accounts, where {customerID} is Magic's customer.

The account belongs to the creator, not to Magic's company, so every owner field names the creator: it is a third-party individual account held under Magic's customer. The documented request has no separate third-party switch; the owner fields carry it.

{
  "currency": "usd",
  "account_type": "us",
  "bank_name": "Cross River Bank",
  "account_name": "X Money",
  "first_name": "<creator's first name>",
  "last_name": "<creator's last name>",
  "account_owner_type": "individual",
  "account_owner_name": "<creator's full legal name>",
  "account": {
    "routing_number": "<X Money routing number>",
    "account_number": "<X Money account number>",
    "checking_or_savings": "checking"
  },
  "address": {
    "street_line_1": "<street number and name>",
    "city": "<city>",
    "state": "<state>",
    "postal_code": "<ZIP code>",
    "country": "USA"
  }
}
FieldValue for an X Money account
currencyusd
account_typeus — a US bank account
bank_nameCross River Bank, the bank that holds X Money accounts
account_nameA label for the account
account_owner_typeindividual
account_owner_name, first_name, last_nameThe creator's legal name, as on their X Money account
account.routing_number, account.account_numberFrom the account details in X Money
account.checking_or_savingschecking
addressThe creator's address: street_line_1, city, state, postal_code, country

Bridge's response returns the external account's id, only the last four digits of the account number (account.last_4), beneficiary_address_valid, and a payment_rails object: supported lists the USD rails the account can receive (for example ach, ach_same_day, fednow) and unsupported_reasons says why any other rail is excluded. Magic stores the id and the last four digits; the full numbers go to Bridge and are never shown back.

Bridge validates US beneficiary addresses: street line 1, city, postal code and country are required, and state as well for the United States; street line 1 must contain a street number and be 3 to 35 characters long; PO boxes and PMBs are refused. Magic's form applies the same rules before it submits, so a mistake is corrected on the spot instead of surfacing later at the bank.

When a creator changes their X Money details, Magic registers the new account, points the existing liquidation address at it (PUT /customers/{customerID}/liquidation_addresses/{liquidationAddressID} with the new external_account_id, a field Bridge lets you update on its own) and deactivates the old account (POST /customers/{customerID}/external_accounts/{externalAccountID}/deactivate). The creator's payout address never changes.

Sources: External accounts · External account validations · USD integration guide · Create an external account · Deactivate an external account · Update a liquidation address

Creating the creator's liquidation address

POST /customers/{customerID}/liquidation_addresses

{
  "chain": "base",
  "currency": "usdc",
  "external_account_id": "<the creator's external account id>",
  "destination_payment_rail": "ach",
  "destination_currency": "usd",
  "destination_ach_reference": "CREATORFEE",
  "custom_developer_fee_percent": "0.0",
  "return_instructions": { "address": "<Magic's settlement address on Base>" }
}
FieldWhat it does
chain, currencyWhat the address accepts, and where: USDC on Base. base is Bridge's identifier for Base, as a payment_rail value and as a key of supported_currencies.
external_account_idThe creator's X Money account, registered in the step above.
destination_payment_railach. The alternative is wire, with an optional destination_wire_message.
destination_currencyusd.
destination_ach_referenceA reference carried with each ACH payment. Bridge documents ACH references as at most 10 characters (letters, digits and spaces) that may appear on the recipient's statement; CREATORFEE fits.
custom_developer_fee_percentBridge can withhold a developer fee from every drain. Magic sets none: its 10% stays in the MagicTreasury, and only the creator's share is ever sent.
return_instructionsWhere Bridge sends funds if a payment fails or is returned: an address and an optional memo. It replaces the deprecated return_address.

The response carries the new address's id, its blockchain address — which becomes the creator's personal payout address — its state (active) and supported_currencies, a map from each chain to the currencies the address accepts.

Bridge warns that funds sent in a currency not listed in supported_currencies may be unrecoverable, and that the list can change over time and should be re-read rather than cached. The settlement service therefore re-reads the address (GET /customers/{customerID}/liquidation_addresses/{liquidationAddressID}) before every payout and sends only when it is active and lists usdc on base.

Bridge also offers a multichain option: "chain": "evm" generates one address usable across every supported EVM chain (Bridge names Ethereum, Polygon, Base and Tempo), and "currency": "all_supported" accepts every currency Bridge supports there. Bridge marks this option as beta, and for such addresses it supports only its crypto return policy, not return_instructions. Magic's design works with either form; it sends USDC on Base in both.

Sources: Liquidation address · Offramp with a liquidation address · Multichain and multicurrency liquidation addresses · Tempo integration guide (a liquidation address with destination_ach_reference) · USD integration guide · Supported blockchains · Developer fees · Changelog · Get a liquidation address

The settlement leg before Bridge

Creator fees arrive in BNB, in the MagicTreasury on BNB Chain. Neither BNB nor BNB Chain appears anywhere in Bridge's documentation. Bridge's liquidation addresses take stablecoins on the chains it supports: its multichain guide names Ethereum, Polygon, Base and Tempo, and shows USDC accepted on Base. So before Bridge is involved, each payout cycle runs three public, on-chain steps:

  1. The creator's share leaves the treasury in a Payout whose ref is the keccak256 hash of the creator's lowercase handle, so anyone can tie it to them.
  2. BNB → USDC on BNB Chain, with a quoted minimum output.
  3. USDC from BNB Chain to Base.

It then sends each creator's share to that creator's liquidation address as one USDC transfer per creator per cycle, so that every drain on Bridge's side matches exactly one transaction on Magic's.

Four details of Bridge's rules shape that transfer:

  • USDC, not USDT. Bridge's cutoff table notes that USDT, unlike its other supported stablecoins, "does not convert at a 1:1 peg with USD, and must be traded". Magic settles in USDC.
  • Whole cents. Bridge processes only amounts expressible in whole US cents and discards any fractional cent. The settlement service sends amounts already cut to the cent and carries the remainder forward in the creator's balance.
  • Minimums. Bridge enforces a minimum per route, after developer fees; deposits below it are neither credited nor returned, and a drain that falls below the route minimum is canceled. Magic's payout minimum sits above Bridge's minimum for the route, so no payout is ever dust.
  • Charges. Bridge's pricing is agreed with Bridge directly. Its precision guide shows how to work back from the amount that should arrive to the amount to send; the settlement service does exactly that, so the dollars that land equal the creator's share, and the difference is paid from Magic's 10%.

Sources: Multichain and multicurrency liquidation addresses · Payment routes · Processing windows and cutoff times · Precision and rounding · Minimums · Drains · Pricing

What happens when the USDC arrives

Each deposit to a liquidation address creates a drain: Bridge converts the USDC and pays the bound bank account. Bridge's liquidation guide separates two kinds of rail: on real-time rails (such as wire) funds are sent at once; on batch rails (such as ACH) they are queued and processed daily.

Drain states. These are Bridge's exact state names; the right-hand column is what Magic's ledger does with each.

StateBridge's meaningMagic's ledger
in_reviewA temporary, rarely triggered state that typically resolves within seconds; if it is unconfirmed after 24 hours, Bridge contacts the developerPayout shown as processing
funds_receivedBridge has received the funds and is processing themDrain matched to the Base transfer
payment_submittedBridge has submitted the paymentACH in flight
payment_processedThe payment is complete and the funds have reached the destination; for ACH, the drain's destination then includes the trace_numberPayout marked paid; trace number published
undeliverableBridge could not send the funds, for example because of an invalid routing or account numberAmount returned to the creator's balance; creator asked to check their details
returnedThe payment was sent but failed, and the funds came back to BridgeAs above
refund_in_flightA refund has been initiated and is in progressAwaiting the returned USDC
refundedReturned funds have been delivered to the configured return addressReturned USDC matched back at Magic's settlement address and held for the creator
refund_failedA refund attempt failedHeld and resolved with Bridge
missing_return_policyBridge needs a crypto return policy to return the depositPrevented by configuration: every address has return_instructions, and the account has a static-address return policy
errorA problem prevented processing; manual intervention may be requiredHeld; never re-sent blind
canceledCanceled and queued for return, for example below the route minimumHeld until refunded, then returned to the creator's balance

A drain only moves forward: funds_received → payment_submitted → payment_processed.

Timing. Bridge uses fiat rails on banking days and during banking hours:

RailCutoff (ET)SettlementBridge's notes
Next-day ACH4:45 PM8:30 AM the next business dayBatches go out each banking-day evening; ACH funds typically land in 1–2 banking days
Wire4:45 PMUp to 2 hours after sendingAfter the cutoff, sent the next banking day; receiving banks process wires at their own speed
FedNowNoneSeconds24/7/365; the recipient bank must support FedNow

Payments that miss a cutoff go out the next day, and ACH and wire payments initiated on a Federal Reserve holiday are queued for the next business day (for the rest of 2026: 12 October, 11 November, 26 November and 25 December). Each payout cycle therefore finishes its Base transfers well before 4:45 PM ET, so each payout can join that evening's ACH batch.

Webhooks. Magic registers one HTTPS endpoint (POST /webhooks). New endpoints start disabled; Magic tests delivery with POST /webhooks/{webhookID}/send and then enables the endpoint with PUT /webhooks/{webhookID}. It subscribes to the liquidation_address.drain category, whose events are created, updated and updated.status_transitioned. The event_object of each event is the drain exactly as the API returns it. Every delivery carries an X-Webhook-Signature header of the form t=,v0=; Magic joins the timestamp and the raw request body with a dot, takes the SHA-256 digest and verifies the signature with the endpoint's public key. It refuses events older than ten minutes with a 400, as Bridge advises against replays (a retry arrives with a fresh timestamp), and answers everything else with a 200 at once. An unreachable endpoint is retried with exponential backoff for up to two days.

Backstops. Webhooks are not the only source. The reconciler also reads each address's drains (GET /customers/{customerID}/liquidation_addresses/{liquidationAddressID}/drains), the drains of every address at once (GET /liquidation_addresses/drains), and the account's webhook events (GET /webhook_events, the last 90 days in event_sequence order) to replay any gap.

Idempotency. Bridge requires an Idempotency-Key on every POST and honours it for 24 hours: a retry with the same key returns the original response and creates nothing new. A reused key with a changed body is an error, and a key reused after 24 hours returns 422. Magic generates a UUID for each intended operation — registering an account, creating an address — writes it to its write-ahead ledger before calling Bridge, and reuses it on every retry. On the receiving side, each webhook's event_id is globally unique, and Bridge notes it is useful as an idempotency key: the ledger applies each event_id once and ignores repeats. Registrations are paced under Bridge's global rate limit of 10 API calls per second.

Sources: Drains · Offramp with a liquidation address · Processing windows and cutoff times · Holidays · Returns · Webhooks overview · Webhook signature · Webhook event structure · Create a webhook endpoint · List webhook events · Drain history · Activity across all customers · Idempotence · Fiat payout configuration

Reconciliation: one payout, four records

Every dollar payout is tied together by identifiers that each side publishes:

RecordIdentifierSource
TreasuryThe BNB Chain transaction of the Payout, whose ref is the hash of the creator's handleThe MagicTreasury's Payout event
BaseThe Base transaction hash of the USDC transferMagic's settlement service
BridgeThe drain's id, deposit_tx_hash, amount, state and destination.external_account_idThe drain webhook and drain history
Bankdestination.trace_number — a unique 15-digit number for each ACH payment (destination.imad for a wire)The drain, once payment_processed

A payout is marked paid only when the drain's deposit_tx_hash equals the Base transfer's hash, the drain belongs to that creator's liquidation address, its external_account_id is the creator's current X Money account, its amount agrees with the ledger entry, and its state is payment_processed; the trace number Bridge then adds is recorded and published. Because each cycle sends exactly one transfer per creator, every drain matches exactly one ledger entry. A drain that does not match is held and investigated, never re-sent blind.

The proof page shows, for every payout, the X account, the coins and fee payments behind it, the treasury Payout, the BNB-to-USDC swap, the Base transfer, the drain's state and the ACH trace number.

Sources: Drains · Payment tracking identifiers · USD integration guide

Landing in X Money

X Money accounts have their own account and routing numbers at Cross River Bank. X's own Money FAQ says of those details: "Use these details for deposits and wire transfers from U.S. banks", and "You can set up your Money account to receive direct deposits." A Bridge ACH payout to those numbers is an ordinary incoming ACH credit to the creator's own account: no X Money send, request or claim is involved.

For USD ACH, Bridge originates payouts under the name of the relevant Bridge entity; its payout configuration for usd.ach is bridge. Wires are originated by default under the developer's name — here, Magic's company. The CREATORFEE reference travels with each ACH payment and may appear on the creator's statement.

Bridge's cutoff table says next-day ACH funds typically land in 1–2 banking days, and the FAQ Bridge provides for developers' users puts next-day ACH at 1–3 days. A creator can expect a payout in their X Money balance within 1–3 business days of the cycle that sent it, and the proof page shows the trace number from the moment Bridge reports it.

Sources: Fiat payout configuration · Processing windows and cutoff times · Bridge FAQ · USD integration guide

FedNow, the faster rail

Bridge offers FedNow offramps: USD payouts that run 24/7/365 and settle in seconds, with liquidation addresses among the products that can use them. Bridge currently opens FedNow offramps by invitation, as a beta with a waitlist. Only an account whose payment_rails.supported includes fednow can receive them, and Bridge asks for refund handling to be configured first, since a receiving bank can still reject an individual payment.

Where Bridge enables FedNow for Magic's account and reports a creator's X Money routing number as FedNow-eligible, Magic switches that creator's liquidation address from ach to fednow through the same PUT used for account changes. Those payouts reach X Money in seconds, at any hour, and carry an end_to_end_id where an ACH payment carries a trace number.

Sources: USD integration guide · Processing windows and cutoff times · Payment tracking identifiers · Changelog · Update a liquidation address


Magic is independent. It is not affiliated with, endorsed by or sponsored by Bridge, X Corp. or X Payments LLC. Bridge is Magic's payout rail for dollars, described here from its public API documentation. X Money is a destination for payouts, not a partner.

Magic is not affiliated with X Corp. Magic is not affiliated with, endorsed by or sponsored by Bridge or UsePaid.