Skip to main content
Orders are how you acquire and release compute time. A buy order increases your pool’s allocation schedule. A sell order decreases it and returns credits to your balance.

Buy orders

Place a buy order to get compute time on a pool. --max-rate is the most you’ll pay in dollars per node-hour; 1 node is 8 GPUs. You can also use --max-price to set a maximum total for the order instead.
If the orderbook has availability at your rate, the order fills immediately. Otherwise, SF Compute cancels the order by default (immediate-or-cancel). To keep the order on the orderbook until it fills or you cancel it, use --allow-standing.
A buy order fills completely or not at all by default. Pass --allow-partial to let it fill part of the requested nodes or time window instead, which leaves the order partially_filled. A sell order allows partial fills by default, since a seller usually wants any buyer for any part of the offered supply. Pass --allow-partial=false to require an all-or-nothing fill on a sell.

Pin to a SKU

You pin every order to a single SKU; the order fills only on that SKU. Pass --sku <id> to pick one directly.
Running sf orders create without --sku opens an interactive picker that shows every registered SKU’s name, ID, and properties. In non-interactive mode (--no-input), --sku is required. Run sf skus list to browse them beforehand. See SKUs for the full model.

Sell orders

Sell back compute time you own.
When a sell order fills, you receive credits and your pool’s allocation decreases. Instances on that pool that no longer have allocated time will terminate.
Sell orders are not guaranteed to fill. Use --allow-standing to keep the order on the orderbook until a buyer matches.

Sell fees

When a sell order executes, SF Compute deducts a variable platform fee from the fill price. You receive the fill price minus the fee as credits. The CLI shows the estimated fee before you confirm an order. Buy orders have no fees.

Interruptible buy orders

Interruptible buy orders are in public preview.
When an interruptible buy order fills, SF Compute lists the compute it bought for sale at a multiple of your max rate that you set. These listings are sell orders on the same pool that allow partial fills. The order doesn’t count toward your compute limit. If someone buys a listing, you lose that time. Instances left without allocated time terminate, lowest priority first. Set the multiple with --interrupt-multiple. It must be above 1.0 and at most 1.5. This order lists its compute at $25.00/node-hour:
sf pools extend takes the same flag. If an interactive buy would go over your compute limit, the CLI offers to make it interruptible, then checks your compute limit again with the interrupt multiple you pick. See your listings with sf orders list --side sell. When a listing fills, you get the fill price minus sell fees. Cancelling the buy order doesn’t cancel its listings. Cancel a listing with sf orders cancel. SF Compute refuses the cancellation if it would put you over your compute limit.

Holds

Placing an order reserves what a fill would need, so a match can always settle. A buy order holds credits equal to its worst case, the limit price across the full requested window and node count. Your available balance is what remains after open holds. Placement fails with an insufficient-balance error when your available balance can’t cover the hold. A sell order instead reserves the pool allocation it offers, so the same compute can’t be sold twice. When a fill executes, you pay the fill price and SF Compute releases the unused part of the hold. Cancelling the order or letting its remaining window elapse releases the rest.

Order statuses

A standing order (buy or sell) rests until it fills, you cancel it, or its window fully elapses. As the current time passes the order’s start, it keeps matching only over the un-elapsed remainder of its window. It matches at its original per-node-hour limit price. The order’s total value shrinks as time elapses. Once the whole window has elapsed the order stops matching and moves to cancelled; there is no separate expiry or time-to-live field. This lapse timing is current behavior, not a guarantee.

Check an order

Look up a single order by ID.

List orders

List orders in the active workspace.
To list orders across your organization, use --all.
Filter by side or status.
Filter by time range.
--created-after and --created-before accept a datetime, Unix timestamp, or a duration like 24h or 7d. A duration means that long ago (24 hours or 7 days, respectively). You can also use --since and --until as aliases.

Cancel an order

Cancel an order that hasn’t fully filled yet.
Cancellation is asynchronous. The request returns right away (204 No Content on the API). A matching batch already in progress can still land a fill before the state flips to cancelled. Poll GET /v2/orders/{id} until it does. Cancellation removes only the unfilled remainder from the orderbook and keeps the fills that executed before it. Once the order is cancelled, its fills and filled_allocation_schedule_delta are final and remain readable on the order in both get and list responses.

Start and end times

Order start and end times must be on the allocation schedule grid. An order can also start at the current time.

Allocation schedule deltas

allocation_schedule_delta describes how many nodes an order requests or offers during one or more time intervals. An allocation_schedule_delta JSON entry mapped to eight nodes over a time interval. start_at supplies the time for vertices A and B, end_at supplies the time for C and D, and node_count supplies the value for B and C. Each object in the array is one schedule segment. start_at and end_at set the segment’s time bounds, while node_count specifies how many nodes apply during that interval. Multiple entries can describe different node counts over adjacent intervals. Schedule entries describe half-open intervals [start_at, end_at): the node count applies at start_at, but not at end_at. Adjacent entries therefore meet without overlapping. All segments on an order refer to that order’s single instance_sku. In responses, a non-empty array always ends with a terminator entry whose end_at is null and node_count is 0, marking the schedule as open-ended and empty after the last segment. A schedule with no capacity is returned as an empty array. Requests carry only the closed [start_at, end_at) segments you submit and omit this terminator. Orders are submitted with one node count over one delivery window, so allocation_schedule_delta normally contains one segment. filled_allocation_schedule_delta describes the portion that has executed so far and may contain multiple segments when different parts of the order fill over different intervals. Subtract the filled node count from the requested or offered node count at each instant to get the capacity that remains on the book. For a buy, every filled segment adds to the destination pool’s allocation schedule; for a sell, it removes that segment. An orderbook fill reports the exact schedule segment that traded. To calculate the compute represented by a schedule, sum node_count × duration_hours across its entries.

API examples

These worked examples use the /v2 order endpoints; see the Orders API reference for the full request and response schemas. Timestamps are Unix epoch seconds, and prices are strings in dollars per node-hour. Create a buy order with POST /v2/orders. The request body includes the following fields.
  • side is buy or sell.
  • pool accepts a pool ID or resource path.
  • sku takes a SKU ID.
  • allocation_schedule_delta is a single time range.
The response returns the order in pending state; poll GET /v2/orders/{id} for the resolved state. The trailing zero entry marks the end of the schedule.
A sell order takes the same body with side set to sell, and its response has the same shape.
Fetch one order with GET /v2/orders/{id}. Once filled, state is filled, filled_at is set, and filled_allocation_schedule_delta covers the filled portion. fills lists each execution with the price actually paid (here below the buy’s limit).
List orders with GET /v2/orders. Each entry in data is a full order object; pass the returned cursor as starting_after to page forward.
Cancel with POST /v2/orders/{id}/cancel, which returns 204 No Content.