Direction is fixed by the reason. You name only the participant account; the platform resolves your funding account from your firm’s configured funding relationship and derives the source and destination from the reason. There is no way to express any other movement — transfers to your firm, between participants, or to an external destination are structurally impossible.
Service
Service:polymarket.us.cashmovement.v1.CashMovementService
Transfers are firm-scoped — do not send x-participant-id. Your firm submits transfers on behalf of your funding entity under the three-party agreement; the platform verifies your firm is authorized for the funding account on every call.
CreateCashMovement
GetCashMovement
reason and derived source and destination accounts, but it does not echo participant_account_id, external_reference, or memo. Persist those request fields in your own ledger alongside workflow_id. There are no order, execution, or market correlation fields on a transfer. Both sides of a confirmed transfer appear on the balance ledger of the affected accounts, so your projection and your funding entity’s records see the same event.
Insufficient funds
A transfer is rejected if the source account cannot cover the amount:
This is enforced across the system regardless of reason — no transfer can drive an account negative. Managing the risk is on you and your funding entity: gate spendable balance so accrued fees stay covered (Vendor Fees), and check free cash before initiating withdrawals (Deposits & Withdrawals).
Frequency rules
Transfers are a limited, shared resource — see the transfer budget:DEPOSIT/WITHDRAWAL— event-driven: typically one transfer per wallet deposit/withdrawal event per participant. Mirroring wallet events 1:1 is the intended pattern; batch micro-events into fewer, larger transfers where your product allows.VENDOR_FEES— at most once per day per participant account. Collecting weekly or monthly is fine; collecting more often than daily is not permitted.
Rate limits and smoothing
Budget for a maximum of 5 transfer calls per second across your whole integration. Requests over the limit are rejected with gRPCRESOURCE_EXHAUSTED (HTTP 429 on any REST mapping) — the transfer was not created, and it is always safe to retry with the same idempotency_key.
Design for the budget rather than reacting to rejections:
- Single dispatcher, client-side queue. Route every transfer through one queue per environment drained at a fixed rate below the cap (e.g. 4/s, leaving headroom for retries). Never fan transfers out from concurrent workers straight to the API.
- Spread scheduled runs. An end-of-day vendor fee collection across 2,000 participant accounts at 4/s takes ~8–9 minutes — schedule the run as a paced drain, not 2,000 simultaneous calls at the stroke of EOD.
- Retry with backoff and the same key. On
RESOURCE_EXHAUSTED, re-enqueue with jittered exponential backoff (e.g. 1s → 2s → 4s, ±20% jitter) and the sameidempotency_key. The rejection happened before creation, so the retry is a fresh, safe attempt. - Deposits preempt fee collections. If a participant is waiting to trade, their deposit is latency-sensitive; a fee collection is not. Give
DEPOSITtransfers priority in your queue and let batch runs yield.
Idempotency and recovery
- Use a distinct, durable idempotency key per logical transfer, persisted before the call.
- A transport timeout or an
AMBIGUOUSstatus is not permission to create a second workflow — replay the same create request with the same key, or read the original workflow byworkflow_id. - A replay must be identical: the request is hashed under the key, so retrying with a changed amount, account, reason, or reference is rejected as key reuse with a different request.
- Use bounded recovery for
PENDINGworkflows rather than a permanent polling scheduler. - Persist
workflow_id, the reason, andexternal_referencethrough a terminal result — they are your join keys across your books, the balance ledger, and support requests.
Errors
An insufficient-funds outcome is not a gRPC error at create time: the workflow resolves to
status = REJECTED with a rejection_reason — see Insufficient funds.
Related pages
Partner Funding Overview
The model — parties, money flows, and directional guarantees.
Deposits & Withdrawals
Mirroring wallet allocations into buying power.
Vendor Fees
Accrual, the daily report, and collection.
Reconciliation
Keeping your books in sync with the ledger.