Price lock
Off by default. A request without it rests at the price you set and pays the level it executes at, up to that price, which is unknown when you send. With the lock on, the request bids the published quote instead, so the most it can cost is known before it leaves your machine. Turn it on only for a request whose price has to be known before it is sent: the lock buys that one thing, and pays for it in admission.
When to turn it on
The lock buys one thing: a ceiling you know before the request leaves your machine. Turn it on for a request that has to be priced in advance, and for a job that has to be budgeted before it runs.
Leave it off for everything else. A locked request bids the quote rather than your price limit, so when your limit is above the quote it gives up book priority, and when the fleet is short it can cancel unstarted where the same request unlocked would have waited and run. It never pays more than the same request unlocked, so a request whose price you did not need to know gains nothing from the lock and can lose its slot to the window.
The setting on the bidding page makes it the default for every interactive request to a market model. Send price_lock on a request to lock one call, or to leave one call unlocked on an account that locks by default.
A fixed-price model ignores the lock, on the request and on the account, because its price is published before any request is sent. A request to one waits for a free slot, and for enough balance at its prices, up to its order timeout or max_wait, and one that does not start in time ends with 429 capacity_unavailable and no charge.
The quote
The quote is the clearing level plus a margin, latched once per interval on the exact UTC boundary and held for every request sent inside that interval. It is published at GET /v1/market/price-lock, with how long the current one has left. The gateway uses the quote standing when it accepts the request. To cap spending at a quote already read, send that value as price_limit too.
A locked request bids the quote, or your price limit if that is lower. It starts within its execute window or is cancelled with 429 and no charge. The three cases are drawn on the front page: no lock, locked while the level falls, and locked while it jumps.
Two clocks
They are independent.
| Clock | Length | Whose |
|---|---|---|
| Quote | 1 minute | Everyone's. Latched on exact UTC boundaries and held for every request sent inside the window. |
| Execute window | 10 seconds | Yours. Timed from your submission, so a request sent a second before a boundary keeps its quote and still gets the full window. |
Miss the execute window and the request is cancelled with 429 and never charged. The window bounds the wait: a request that has started generating runs to completion however long that takes. Any max_wait on a locked request is ignored; the window is its timeout. A locked request with image URLs spends the time their fetch takes inside its window, since the window starts at submission.
What a locked request does
| Case | Outcome | Charged |
|---|---|---|
| The level is at or under the quote and the fleet has room. | It starts, ranked at the quote. The charge is fixed the moment it starts: the level then, at most the quote. | The level, up to the quote. |
| The level rises above the quote inside the window, before the request starts, and the fleet still has room for it. | It starts and is charged the quote it holds rather than the higher level. This is what the margin buys. | The quote. |
| Capacity does not reach the request before its window ends. | The request cancels with 429 capacity_unavailable. | Nothing. |
| Your price limit is at or below the quote. | The request bids your price limit instead, exactly as it would unlocked, and expires if it has not started before its window ends. | The level, up to your price limit. |
| The market is free (level 0). | The request runs free, since the charge is the level. The quote can retain a margin while the level is 0. | Nothing. |
What the lock costs
The quote is the clearing level plus a margin, and the charge is min(level, bid). Raising a bid above the level changes nothing you pay, so the margin is a ceiling rather than a fee and a locked request can never cost more than the same request unlocked.
The quote can stand well above the level when the fleet is short. What limits it is the evidence a raise needs: the margin rises only while locked requests with a price limit above the quote are missing their window, or clearing under a level that has passed the quote they hold, and every rise takes requests out of that set. Once a feedback window has finished, the quote stands no higher than the dearest price limit any locked request stated inside it.
A locked request bids the lower of the quote and your price limit. It can start while the level is above that bid if capacity reaches it, and pays at most the bid. It expires if it has not started before its window ends. The margin raises its rank in the book. When your price limit is above the quote, locking lowers the bid to the quote and can reduce its admission priority. The margin raises that bid again.
The market moves that margin to target 95% for locked requests with a price limit above the quote starting inside their execute window. clear_rate on the quote endpoint is what it managed. It is null while too few of them have finished for a share to mean anything, and a quote standing above every live price limit is one way that happens.
Under scarcity clear_rate comes in below the target. The margin buys book position and cannot buy capacity, so a saturated fleet cancels locked requests at their window. Raising it further would lift the quote past more price limits, which takes requests out of the count rather than starting them.
Using it
Per request, or for the account
Send price_lock: true on one request, or switch it on for the account on Bidding and send price_lock: false on a request that should wait instead. Setting a price limit does not lock it; a price limit is a cap either way.
# know the price in advancecurl "https://api.openfill.ai/v1/market/price-lock?model=market-preview"{"price": 0.021, "previous_price": 0.02, "usd_per_million": {"cached": 0.009130435, "uncached": 0.091304348, "output": 0.182608696}, "valid_until": "...", "valid_for_ms": 30000, "execute_window_seconds": 10, "interval_ms": 60000, "clear_rate": null, "clear_rate_window_ms": 600000, "target_start_rate": 0.95}import osfrom openai import OpenAIclient = OpenAI(base_url="https://api.openfill.ai/v1", api_key=os.environ["OPENFILL_API_KEY"]) # default: a limit order at $0.05 that waits for the level, and pays the levelr = client.chat.completions.create( model="market-preview", messages=[{"role": "user", "content": "hello"}], extra_body={"price_limit": 0.05, "price_lock": False},) # locked: bids the quote above, capped at $0.05, pays the level up to that, or cancels in the windowr = client.chat.completions.create( model="market-preview", messages=[{"role": "user", "content": "hello"}], extra_body={"price_lock": True, "price_limit": 0.05},)When to leave it off
A request that should wait for a low level leaves the lock off: locked, it has 10 seconds to start and then cancels. A detached request can lock, and still cancels at its window. Batch lines never lock, since they wait far longer than a quote stands.
The quote stream, GET /v1/market/price-lock/stream, sends the standing quote on connect, a fresh one at every boundary, and the same one again as a keepalive while nothing changes, so a client that locks holds the current quote before it sends.
A blocking locked request that misses its window answers 429 with code: capacity_unavailable and a Retry-After of one second, which the OpenAI SDKs retry on their own, each retry under the quote of its moment. A streaming one has already opened at 200, so the same error arrives inside the stream.