Skip to main content
Place a single fill-or-kill limit order for one of your participants with CreateVendorOrder.
Before this page:

It is fill-or-kill limit orders, and nothing else

CreateVendorOrder accepts limit orders with TIME_IN_FORCE_FILL_OR_KILL and nothing else. Any other time-in-force is rejected outright with
It is not silently downgraded. There is no market order, no day order, no GTC and no GTD on this surface. The reason: each order is prefunded with an exact atomic transfer, so the maximum cost has to be known before the order reaches the book. The consequence is commercial, not just technical — you are structurally always the taker. Read You are always the taker before you price your product.

Three request facts that are not in the reflected schema

order.clord_id is required by the runtime. PreviewOrder ignores it and CreateVendorOrder requires it. Reflection advertised the older schema without it for a period, so a client generated from that build compiles, sends no clord_id, and fails at runtime. Send it on every order and keep it unique per order — it is the identifier you will match execution reports on. The participant is named only by order.account. There is no separate customer-account field on this request, and x-participant-id is not used here. The header is required on account-scoped reads such as positions and reports, and it does nothing on this RPC. The value you put in order.account is the provisionedAccount you captured at onboarding — see External IDs, participants and accounts. It is opaque: copy it verbatim and never build it.
[VERIFY] — which call returns provisionedAccount is not published. The kyc.approved webhook is documented as carrying participantId, and nothing states where provisionedAccount comes back.Record whatever account string we hand you at onboarding against your user row, and confirm the source call with your integration lead.
funding_request_ids are values we return, not values you send. The dedupe key is idempotency_key. See Recover a lost order.

The call

[VERIFY] — five things in the snippets below are not published, and one of them sits inside a runnable command. Only order.account, order.clord_id, order.time_in_force, order.symbol, order_qty, cash_order_qty, idempotency_key, funding_request_ids and failure_reason are confirmed. Unconfirmed, and to be checked against your own generated code and proto copy before you send anything:
  • the fully-qualified service name polymarket.v1.VendorOrderAPI/CreateVendorOrder, which the grpcurl tab passes as the method argument;
  • the request, order and enum type names, and the generated stub names;
  • the field name carrying the limit price, shown below as order.price;
  • the side enum values, shown below as SIDE_BUY and SIDE_SELL;
  • your own protoc package layout — the bundle is unversioned, with no checksum or changelog.
The response, with the fields you branch on:
status is the only field that decides what you do next, and ACCEPTED is not a fill. All three values are specified under Order outcomes.

Four worked order shapes

All four use priceScale: 100 and fractionalQtyScale: 100 and a YES price of **0.32.Winningcontractssettleat0.32**. Winning contracts settle at 1.00 and losing contracts at $0.00. The [VERIFY] cells below are the field name carrying the limit price and the two side enum values. The scaling, the quantities and the money are confirmed; those three spellings are not.
The fee figures below are illustrative, not current. They are computed at a taker Θ of 0.06. The taker coefficient changed on 2026-09-14 and every partner had to hand-edit their systems, because there is no fee-schedule endpoint to read it from. VERIFY — confirm the coefficient in force with your integration lead before you invoice anyone from these numbers, and derive the fee from the formula on Money on the wire, never from a figure in a table.

1. Buy YES — quantity-denominated

Maximum cost **1.60(5×1.60** (5 × 0.32), which is what gets prefunded. Maximum return **5.00ifYESsettlesat5.00** if YES settles at 1.00. Fee on a full fill: 0.06 × 5 × 0.32 × 0.68 = $0.0653$0.07 after banker’s rounding, which at that coefficient arrives as commission_notional_collected: "700" (700 / 10,000). At a different coefficient both the cent figure and the wire figure change — recompute, do not copy.

2. Take the NO side — quantity-denominated

A SELL does not pay you cash. It spends complementary NO collateral, and the resulting short carries an obligation of **up to 1.00percontractso5contractsisa1.00 per contract** — so 5 contracts is a 5.00 maximum obligation. Maximum return **5.00ifYESsettlesat5.00** if YES settles at 0.00.
how much collateral a quantity-denominated SELL locks is not settled. Whether an open short carries a standing collateral requirement, and where that requirement is exposed, is unanswered: balance_reservation and margin_requirement came back empty on the balance-ledger entries for a real open short.Until it is resolved, hold back $1.00 per short contract in your own ledger and do not let a user withdraw funds backing an open short on the strength of a balance field. A partner following the balance fields alone could release collateral that is still obligated. The withdrawal rule built on this reserve is on Which number is spendable.

3. Cash-denominated buy

cash_order_qty is scaled by priceScale, so 2000 at priceScale: 100 is 20.00not20.00 — not 2,000 and not 0.20.Maximumcostis0.20. Maximum cost is 20.00 exactly, which is the point of denominating in cash: the prefund equals the field. At 0.32thatisupto62.5contracts,returningupto0.32 that is up to 62.5 contracts, returning up to 62.50 if YES settles at $1.00. Send order_qty or cash_order_qty, not both.

4. Cash-denominated sell

This is the shape partners get backwards. On a SELL, cash_order_qty = 2000 means **spend 20.00ofcomplementaryNOcollateral.Youarenotbeingpaid20.00 of complementary NO collateral**. You are not being paid 20.00; you are committing $20.00. A partner who reads it the other way debits the user’s balance and credits it again, and their ledger diverges by twice the order size on every short.
Not yet published. We have not published how the exchange converts a cash_order_qty into a contract quantity, or how it rounds to the quantity increment. Do not compute the resulting contract count yourself for a customer-facing number — take it from the execution report.

Rate limits on this call

Not yet published. CreateVendorOrder has no published rate limit at any scope. The general institutional REST limit is 100 req/sec firm-wide on a one-minute average, and there is a 5-second latency stopgap on orders, but neither is stated as this RPC’s budget. Get the number and its scope from your integration lead before you size a burst.
When you do exceed a limit, Global Rate Limit Exceeded arrives as an execution-report rejection, not as an HTTP or gRPC error — so an order-placement path that only inspects the RPC result will record it as accepted. See Order outcomes.
API reference: Trading. Opens on the public documentation site in a new tab. Where it disagrees with this page, this page is authoritative for the partner surface.

You are always the taker

If you are an IB, this differs. State two things explicitly to a regulatory reviewer, because neither is reachable here. There is no modify or replace on the partner surface at all, so an order-handling procedure you file cannot include one. And day orders cancel at the traded-day roll, with GTD as the alternative — neither applies on a fill-or-kill-only surface.
Price your product against the one fee coefficient you can actually be charged.

The structural consequence of fill-or-kill

CreateVendorOrder accepts TIME_IN_FORCE_FILL_OR_KILL and nothing else, so your orders never rest. An order that never rests can never be the passive side of a trade. You can only consume resting depth, and you can never earn the maker rebate. This is a property of the order surface, not a tier you can be upgraded into or a volume threshold you can trade through. No configuration changes it.

Both coefficients, and the one you pay

rounded to the cent with banker’s rounding, where C is the de-scaled contract count and p is the de-scaled YES price. Θ is a coefficient, not a percentage of principal. p × (1 − p) peaks at p = 0.50, so the fee is largest mid-book and smallest at the extremes: Two numbers worth carrying into a pricing conversation:
  • Your worst case is $0.015 per contract, at p = 0.50.
  • A market maker on the other side of that same trade receives 0.003125percontract,sothepercontractgapbetweenyoureconomicsandtheirsis0.003125 per contract, so the per-contract gap between your economics and theirs is **0.018125** at p = 0.50 — the full 0.06 − (−0.0125) = 0.0725 spread, scaled by p × (1 − p).
Price the taker coefficient into your own fee to the end user. A model built on a blended maker/taker rate does not apply to this surface, and there is no path to the maker side later.
The taker coefficient changed from 0.06 to 0.0695 on 2026-09-14, and [GAP] there is no fee-schedule endpoint. Every partner had to hand-edit their systems, because Θ cannot be read from the API at all — not on the instrument, not on the execution report, not anywhere.Confirm today’s value with your integration lead before you commit to a published price, keep Θ in exactly one place in your code, and reconcile every fill’s commission_notional_collected against your own expectation so a coefficient change surfaces on the first fill rather than in a monthly report.

Why a thin preprod book blocks you and not a market maker

Taker-only order entry and a shallow book combine badly. A market maker posts resting depth, so it can trade in preprod regardless of how thin the book is. You can only cross depth somebody else posted, so when the book is empty you cannot transact at all. The same environment is fully functional for one partner type and completely blocked for yours. The numbers behind that:
  • pmsim is the live liquidity provider, and symbol coverage is thin and uneven: astatc- about 48%, aec- about 3.7%, aec-atp about 0.1%. A second liquidity source is configured but not running.
  • Books are shallow and intermittent — “straight 0 for a few minutes” is normal, not an incident.
  • Of 121 open ATP instruments, only a small minority showed any resting depth, and that depth sat at the edges: a 0.98offeranda0.98 offer** and a **0.06 bid. A fill-or-kill order at a realistic price crosses nothing.
  • Preprod markets do not resolve. Instruments reach INSTRUMENT_STATE_EXPIRED in large batches — 363, 455, 544 and 549 in a single session — with none resolving. One partner asked six times over 40 days to be able to test a settlement flow and never could.
So: expect EXPIRED on nearly every preprod order, and treat a preprod fill as a lucky event rather than a test you can rely on repeating. EXPIRED is not a defect — Order outcomes explains why it carries no reason. The only known way to manufacture a preprod fill contradicts the UAT attestation you are asked to sign. That contradiction is on Cancelling; escalate it rather than choosing a side.

Will a resting time-in-force be available?

Not yet published. Whether a resting time-in-force — and therefore maker eligibility — is on the roadmap for the partner surface is not published, and no timeframe has been committed. Ask your integration lead before you build a pricing model that assumes it arrives, and do not represent a maker rebate to your own customers as forthcoming.

What can go wrong

Next

Outcomes and recovery