By default DimeTrades is the system of record for a user’s balance: they deposit/withdraw through /wallet/deposit and /wallet/withdraw, and DimeTrades holds the money. External wallet integration flips that: your platform holds and manages your customers’ balances, and reserves funds against them yourself — atomically, on your own side — before you ever call DimeTrades.
The five-minute summary. Your backend reserves the required amount against the customer’s balance, then calls POST /orders with a clientOrderId. Before accepting a BUY limit order (or a cost-increasing modification), DimeTrades calls you — a synchronous API, not a webhook — to confirm that reservation exists. When a trade actually moves money, DimeTrades sends a signed wallet.debit/ wallet.credit webhook, the same delivery mechanism documented in the Partner webhooks guide. You release your own reservation on order.cancelled/order.expired/order.rejected — all generic, already-documented webhooks, nothing wallet-specific. Your own /wallet/deposit//wallet/withdraw calls are blocked for these users, since DimeTrades no longer holds their balance.

1. Setup

External wallet integration is configured per brand by your DimeTrades account contact, alongside (and independently of) webhook delivery:
  1. A partnerApiBaseUrl is set on your brand — the base URL DimeTrades calls for the reservation check.
  2. An API key id and signing secret are issued — the secret is shown to you exactly once, the same way the webhook signing secret is. It cannot be retrieved again, only rotated (which invalidates the old one).
  3. externalWalletEnabled gates the whole feature — while it’s on, a BUY limit order or cost-increasing modification triggers the check below, and your users’ own deposit/withdraw calls to DimeTrades are rejected.
There is no self-serve registration endpoint yet — the check only activates once a URL, key, and secret are all configured on your brand.

2. The API you expose

Full field-by-field reference is on the Confirm a wallet reservation page — this section covers the same contract as a narrative walkthrough.
This is a synchronous API endpoint, not a webhook. DimeTrades calls it and blocks on the response, in the same request/response cycle as order placement — nothing here goes through the outbox/retry mechanism section 3 below describes. It needs to be reachable from DimeTrades’s network and respond quickly: order placement and modification are waiting on this call.
DimeTrades calls one endpoint on your side — a confirmation, not an instruction. Since your own backend already reserves funds atomically before it ever calls POST /orders, DimeTrades is only asking “did you actually reserve at least this much?”:
  • clientOrderId is the idempotency key you supplied on POST /orders — the correlation key for this check, since you generated it and already know it.
  • amountCents is the minimum you should already have reserved — price × quantity plus the worst-case (taker-rate) fee. Nothing more needs to be added on top. See “Reservation sizing is yours” below.
  • externalCustomerId is the same id you supplied when registering the customer through the partner provisioning API — present in both the URL and the body.
Respond with a boolean — never your customer’s actual balance:
Only BUY limit orders trigger this call. SELL orders lock contracts, not cash, so they never call you. Market orders carry no limit price to size the check against — DimeTrades no longer substitutes an estimate, so a market BUY order for an external-wallet customer proceeds with no call at all.

Reservation sizing is yours

amountCents already includes the worst-case fee: it’s the order’s cost (price × quantity) plus the taker-rate fee, the higher of the two rates DimeTrades ever charges. DimeTrades debits cost + fee on fill (see wallet.debit below), and the actual fee applied on fill is always this taker rate or the lower maker rate — never higher. So converting amountCents straight into a settled debit never under-covers the fee; no additional buffer is needed on your side. DimeTrades still has no visibility into your actual reservation and can’t validate or enforce your sizing from its side — this section just documents what amountCents itself already accounts for.

Authenticating the request

The X-DimeTrades-Signature header uses the same scheme as webhook deliveries (see Verifying a delivery), but with your external wallet secret, not your webhook secret — the two are issued and rotated independently, and must never be confused:
Compute the signature over the raw request body bytes — the exact JSON DimeTrades sent, before any parsing or re-serialization on your end — the same way you would for a webhook delivery. Verify it the same constant-time way before trusting the call actually came from DimeTrades.

Timeout and retries

DimeTrades retries the check up to 3 times with a short backoff (100ms, 500ms, 2s) before giving up — this happens within the lifetime of your customer’s order-placement request, so keep your response time well under your brand’s configured timeout (partnerApiTimeoutMs, 2000ms by default). If all retries fail, the order is rejected — a partner outage blocks that brand’s BUY flow rather than silently letting orders through unchecked.

Rejection mapping

If your POST /orders call itself fails or times out, retry it with the same clientOrderId — DimeTrades’s idempotency guarantee (see Conventions) means a retried submission is safe and won’t double-place the order.

3. Wallet events (delivered as webhooks)

When a trade actually moves money, DimeTrades sends the acknowledgement as a webhook — same envelope, same signing, same retry/backoff schedule as every other event in the Partner webhooks guide, and structurally nothing like the synchronous check above. Only two event types are wallet-specific: Every wallet event carries externalCustomerId — the id you supplied when you registered the customer — so you can route the movement to the right balance, plus clientOrderId (the key you supplied on POST /orders) marketId and eventId, so you can match it to your reservation without a lookup. amountCents is always a positive integer in US cents; reason is trade_fill on a debit and settlement on a trade credit. Trade debits and trade credits (not market-settlement credits) also split the amount, so you don’t have to join to trade.executed: costCents, feeCents, quantity, priceCents and role (maker or taker).
  • wallet.debit: costCents + feeCents = amountCents.
  • wallet.credit for a SELL fill: the fee is netted inside the credit, so costCents - feeCents = amountCents, where costCents is the gross sale proceeds.
  • wallet.credit for an auto-merge payout after a BUY: feeCents is 0, costCents = amountCents, quantity is the number of merged pairs (which can be fewer than the trade quantity) and priceCents is null.
Unlike the other webhook events, these two are not FYI notifications — they are the authoritative instruction to move money. DimeTrades holds no balance of its own for these users, so there is no other record to reconcile against. Dedupe on id is not optional the way it’s a good practice elsewhere: applying the same wallet.debit twice double-charges your customer, and a missed wallet.credit underpays them.
Releasing your own reservation is not signaled by a dedicated event. Every event below carries your clientOrderId (and marketId), so you can find the reservation to release directly — you never need to map orderId yourself. DimeTrades never tracks or instructs a release — you already know when to release, from the same webhooks you’d watch anyway: These are the same generic, brand-agnostic webhooks documented in the Partner webhooks event catalog — nothing wallet-specific was added for release.
Reservation-vs-actual-cost excess has no dedicated release event. amountCents sizes the reservation off the order’s limit price plus the worst-case fee; a BUY limit order that fills at a better price than its limit settles for less than that reservation, and wallet.debit reports only the actual charge (cost at fill price + the fee actually applied) — not the original reservation amount, and no event signals the leftover delta. If you need to release that excess, compute it yourself from the reservation you sized against amountCents versus quantityFilled × avgFillPrice (plus fee) on order.filled/order.partially_filled — the same fields wallet.debit is itself derived from.
Full request/response shapes are on the wallet.debit and wallet.credit reference pages.

4. What doesn’t change

Everything else about placing, modifying, cancelling, and tracking orders is identical for external-wallet users — order placement, cancellation, bulk cancel, positions, and portfolio endpoints all work exactly as documented elsewhere in this API. Only the reservation-confirmation check at placement/ modification time and the two wallet webhook events are specific to this integration.