Skip to main content
GET /offers is the endpoint you will spend most of your requests on. It returns what is rentable right now, filtered however you like.
Requires catalog:read. Cursor-paginated — see Pagination, and note in particular that a short page is not the last page.

Filters

All are optional and combine with AND.

By GPU

string
Exact SKU code, e.g. h100-sxm-80gb. The narrowest filter — one specific card in one specific form factor. Values come from /gpu-models.
string
Family id, e.g. h100-80gb. Broader than gpu_model: covers every variant of a card, so h100-80gb matches both SXM and PCIe. This is usually the filter you want — most workloads care about “an H100”, not about the interconnect. Values come from /gpu-families.
integer
Minimum VRAM per GPU, in gibibytes. Filter by what your model needs (min_vram_gb=48) rather than by name, and you will match cards you had not thought to ask for.
string
Free-text over GPU name and code. For a human-typed search box. Prefer the structured filters in code — q=h100 also matches things you did not mean.

By location

string
Exact region code, e.g. us-east-1. From /regions.
string
Coarse bucket: us, eu, asia, other. Use it when the requirement is “keep the data on this continent” rather than a specific datacentre.

By price and shape

integer
Ceiling on the hourly price, in cents, per GPU. max_price_per_hour_cents=300 is “no more than $3.00/hr”.
'standard' | 'dedicated'
standard — the shared-host pool, cheapest and most plentiful. dedicated — the whole host is yours, for workloads that cannot tolerate a neighbour.
'on_demand' | 'spot'
Only offers rentable under this tier. spot is cheaper and interruptible — see Spot rentals.

By availability

'true' | 'false'
true returns only offers with capacity right now.This is a snapshot, not a reservation. An offer can be taken between your read and your POST /rentals, which is why creation can still answer offer_unavailable. Handle that; do not assume available=true guarantees a machine.

Sorting

string
default:"price_asc"
price_asc · price_desc · vram_asc · vram_desc · availability_desc
availability_desc puts the deepest capacity first — the right sort when you need eight GPUs and would rather not discover the shortage at creation time.

Paging

string
Opaque; from meta.next_cursor. Valid only for the exact query that produced it.
integer
default:"50"
1–200.

What an offer looks like

string
required
Opaque, and stable for as long as the offer exists — but offers are transient. Do not store one and expect it to be rentable tomorrow; re-read the catalog.
integer
required
Per GPU, per hour, in cents. A two-GPU rental of this offer costs twice this. (Note that the quote reports the price for the whole rental — the two are different numbers on purpose, and the quote is the one to show a user.)
integer | null
The interruptible price, when this offer sells one. null means it does not.
integer | null
The largest gpu_count this offer can serve. null when the upstream does not say.
string | null
Join key to /gpu-families and /prices. null for models outside a known family.
string[]
required
Which tiers this offer can be rented under right now. This array is the authority on what you can buy; the price fields only say how much.It cuts both ways. An offer with a spot_price_per_hour_cents but no spot here cannot currently be taken as spot. An offer with no on_demand here cannot be taken on-demand either, even though price_per_hour_cents is still populated — some machines are sold at their spot rate only, and the on-demand figure is then the reference that rate undercuts rather than an offer.Send the tier you want on POST /rentals. Omitting it means on-demand, so an integration that never sets it will be refused on a spot-only offer rather than quietly charged a different rate.

Reading availability

This field is a discriminated union. Check kind before reading anything else:
Some upstreams report an exact number of free units; others only report a rough level. Rather than invent a number for the second case — which would be a fabricated integer indistinguishable from a real one — we tell you which kind of answer you are holding.
{"kind": "count", "count": 0} and available=false mean the same thing. Do not write if offer["availability"]["count"]: without handling the signal case — a KeyError on a perfectly valid response is the most common first-integration bug on this endpoint.

One offer by id

Returns the offer object directly, not wrapped in data. 404 offer_not_found covers both “no such offer” and “no longer visible” — reported identically on purpose.

Worked examples

Filtering by VRAM rather than by model is what makes this useful: it will surface an L40S or an A6000 you would not have thought to name.
Then check max_gpus >= 8 and, where availability.kind == "count", count >= 8. Neither field alone is sufficient: max_gpus is what the offer can serve, count is what is free.
Only for work that can be killed and resumed — see Spot and preemption.