AccessAPI Private Preview
One client for the whole platform.
One Python package and one key reach every product on the platform. The same objects answer over REST, a CLI and an MCP server for your agents.
fx = fantasti.Client() import fantasti
# one key, one client
fx = fantasti.Client()
node = fx.instances.create(
gpu="H100:8",
capacity=fantasti.Reserved("rsv_7d2k"))
sb = fx.sandboxes.create(
image="python:3.12", ttl="15m")
run = fx.batch.create(
image="ghcr.io/acme/scorer:2026.10",
input="s3://acme/in/*.jsonl",
output="s3://acme/out/")
for o in (node, sb, run):
print(o.id, o.status, o.placement) Output · illustrative
ins_8f2a… ready us-east · fabric a · reserved
sb_7q2m… ready us-east · on-demand
bat_2kq8… queued None $ fantasti instance create ft-01 --gpu H100:1 --on-demand
$ fantasti instance list
$ fantasti cluster create sft-01 --gpu H200:8 \
--nodes 2 --spot --max-price 3.10 Output · illustrative
request H200:8 × 2 · one InfiniBand fabric · spot ≤ 3.10
pools 4 considered
placed cl_8f2k… · us-east · fabric a
state running · kubeconfig saved {
"mcpServers": {
"fantasti": {
"type": "http",
"url": "https://mcp.fantasti.ai/mcp"
}
}
} Tools · early access
catalog gpus_list
sandboxes sandboxes_create · sandboxes_exec · sandboxes_read_file
sandboxes_write_file · sandboxes_delete
workspaces workspaces_list · workspaces_start · workspaces_stop
jobs jobs_create · jobs_logs
usage usage_get curl -X POST https://api.fantasti.ai/v1/instances \
-H "Authorization: Bearer $FANTASTI_API_KEY" \
-H "Idempotency-Key: ft-01-create" \
-H "Content-Type: application/json" \
-d '{
"name": "ft-01",
"gpu": "H100:1",
"capacity": { "mode": "on_demand" }
}'
# 202 → { "id": "ins_8f2a…", "status": "placing" } # policy.yaml · applies to every request from team "research"
team: research
placement:
gpus: [H100, H200, B200]
fabric: infiniband # multi-node jobs stay on one fabric
regions: ["us-*"]
capacity:
allow: [on_demand, spot, reserved]
spot:
max_price: { H100: 2.40, H200: 3.10 } # your ceilings
limits:
gpus: { H200: 32 }
sandboxes: { concurrent: 200, max_ttl: 60m }
spend: { monthly_usd: 40000 }
cost_center: research-llm - Base URL
- api.fantasti.ai/v1answers with the first cohort
- Authentication
- Bearer $FANTASTI_API_KEY
- Interfaces
- Python · CLI · REST · MCP
- Stage
- Preview API · subject to change
Install, authenticate, place.
One Python package and one API key reach every product on the platform. Three lines take you from an empty environment to a placed instance.
- 01 Install The SDK and the CLI are published when the first cohort opens.
- 02 Authenticate The client reads
FANTASTI_API_KEY. - 03 Place The call returns an id while the request is placed.
Three steps. One: a terminal sets FANTASTI_API_KEY, and one package serves every product. Two: Python imports fantasti and makes one client, which reads that key. Three: the client asks for one H100 and gets an id back at once, while the Fantasti Orchestrator places the request. The instance that comes back reports its status, region, capacity mode and rate. Connections: Install to Authenticate; Authenticate to Place; Place to ins_8f2a…: placed.
$ export FANTASTI_API_KEY=…- package
- one, for every product
- published
- with the first cohort
import fantastifx = fantasti.Client()- reads
- FANTASTI_API_KEY
ins = fx.instances.create(gpu="H100:1")- returns
- ins_8f2a… placing
ins.wait("ready")- status
- ready
- region
- us-east
- capacity
- on_demand
- rate
- catalog rate
$ export FANTASTI_API_KEY=…- package
- one, for every product
- published
- with the first cohort
import fantastifx = fantasti.Client()- reads
- FANTASTI_API_KEY
ins = fx.instances.create(gpu="H100:1")- returns
- ins_8f2a… placing
ins.wait("ready")- status
- ready
- region
- us-east
- capacity
- on_demand
- rate
- catalog rate
- What the call returns
- In order
Every object reports where it was placed.
Region, fabric and rate. The Fantasti Orchestrator checks each request against your policy and places it on one fabric. The record lists every pool it considered and the constraint each one failed.
A request (64 × H100 SXM5, InfiniBand · us-*, On-demand) enters the Fantasti Orchestrator and passes five policy gates: GPU, interconnect, region, capacity and price ceiling. Four pools are considered. us-east, fabric a: placed, 96 GPUs free. us-east, fabric b: passed over, only 32 free < 64. us-west: passed over, no infiniband. eu-west, fabric a: passed over, region not allowed. The request runs as a node. Connections: Orchestrator to us-east · fabric b; Orchestrator to us-west; Orchestrator to eu-west · fabric a; us-east · fabric a to Sandbox; us-east · fabric a to Batch worker; fx.clusters.create to Orchestrator; Orchestrator to us-east · fabric a; us-east · fabric a to Node.
64 × H100 SXM5InfiniBand · us-*On-demand- GPU
- H100 SXM5 × 64
- interconnect
- infiniband
- region
- us-*
- capacity
- on_demand
- price ceiling
- catalog rate
- free 96asked 64
Placed - free 32asked 64
32 free < 64 - free 64asked 64
No InfiniBand - free 128asked 64
Region not allowed A virtual machine
64 × H100 SXM5InfiniBand · us-*On-demand- GPU
- H100 SXM5 × 64
- interconnect
- infiniband
- region
- us-*
- capacity
- on_demand
- price ceiling
- catalog rate
- free 96asked 64
Placed - free 32asked 64
32 free < 64 - free 64asked 64
No InfiniBand - free 128asked 64
Region not allowed A virtual machine
64 × H100 SXM5InfiniBand · us-*On-demand- GPU
- H100 SXM5 × 64
- interconnect
- infiniband
- region
- us-*
- capacity
- on_demand
- price ceiling
- catalog rate
- free 96asked 64
Placed - free 32asked 64
32 free < 64 - free 64asked 64
No InfiniBand - free 128asked 64
Region not allowed A virtual machine
- This request
- Passed over
$ fantasti explain cl_3m7q Output · illustrative
request 64 × H100 SXM5 · InfiniBand · us-* · on-demand
pool-a us-east · InfiniBand · 96 free placed
pool-b us-east · InfiniBand · 32 free ✕ 32 free < 64
pool-c us-west · no InfiniBand ✕ no InfiniBand
pool-d eu-west · InfiniBand · 128 free ✕ region not allowed
price on-demand · catalog rate The same decision, as a record.
fantasti explain prints why a request landed where it did. An object's placement field carries the result.
- Regioninside the regions your policy allows
- Fabricone InfiniBand fabric for a multi-node job
- Ratethe catalog rate, the spot price or the rate in your order form
- Capacity modeon-demand, spot or reserved
Objects and their states.
| Object | Id | Made with | REST | Explained on |
|---|---|---|---|---|
| Placed by the Orchestrator08 | ||||
| Instance Compute | ins_ | fx. POST / | POST /v1/instances | Compute |
| Cluster GPU Clusters | cl_ | fx. POST / | POST /v1/clusters | GPU Clusters |
| Workspace Early access Workspaces | ws_ | fx. POST / | POST /v1/workspaces | Workspaces |
| Sandbox Early access Sandboxes | sb_ | fx. POST / | POST /v1/sandboxes | Sandboxes |
| Job Early access Serverless | job_ | fx. POST / | POST /v1/jobs | Serverless |
| Endpoint Early access Serverless | ep_ | fx. POST / | POST /v1/endpoints | Serverless |
| Batch run Batch Inference | bat_ | fx. POST / | POST /v1/batch | Batch Inference |
| Flow run Planned Flows | run_ | python flow. POST / | POST /v1/flows/{flow}/runs | Flows |
| Storage and network03 | ||||
| Filesystem Storage | fs_ | fx. POST / | POST /v1/storage/filesystems | Storage |
| Bucket Storage | name | fx. POST / | POST /v1/storage/buckets | Storage |
| Network Networking | name | fx. POST / | POST /v1/networks | Networking |
| Account and records04 | ||||
| Reservation By request Reservations | rsv_ | A signed order form GET / | GET /v1/reservations/{id} | Reservations |
| Decision Agents | dec_ | Written for every decision GET / | GET /v1/decisions | Agents |
| Case Early access Support | case_ | fx. POST / | POST /v1/support/cases | Support |
| Preview Planned Previews | slug | fx. POST / | POST /v1/previews/{slug}/join | Previews |
| Object | States, in order | Ends when |
|---|---|---|
| Instance |
Ends whenYou release it, or its reservation ends. | You release it, or its reservation ends. |
| Sandbox |
or Ends whenIts TTL or idle timeout passes, or you delete it. | Its TTL or idle timeout passes, or you delete it. |
| Batch run |
on spot Ends whenThe last item completes, or retries run out (failed). | The last item completes, or retries run out (failed). |
| Reservation |
Ends whenThe term ends. | The term ends. |
In service End state
| State | Meaning | Compute charge |
|---|---|---|
blocked | Your max price is below the current spot price. Nothing has started. Compute chargeNone | None |
placing | Capacity at your price is being placed. Compute chargeNone | None |
running | Nodes are up. Compute chargeSpot price for each interval | Spot price for each interval |
stopping | Stop notice sent. 60 seconds to exit. Compute chargeSpot price until the node stops | Spot price until the node stops |
stopped_ | The spot price rose above your max. Disks are kept. Compute chargeNone. Storage continues. | None. Storage continues. |
stopped_ | The capacity was reclaimed. Disks are kept. Compute chargeNone. Storage continues. | None. Storage continues. |
resuming | Capacity at your price is back. Work restarts from its checkpoint. Compute chargeNone until running | None until running |
Compute is charged On spot capacity an object reports one of these states. How spot works
- Sheet
- 01 / 02
- Title
- API objects and states
- Objects
- 15
- Reviewed
- 2026-10-10
1 client
1 key
1 error model
The same objects, ids and limits.
Python, REST, a CLI and an MCP server sit over one API. Use the one your code, or your agent, already speaks.
Four interfaces send the same request, one sandbox on an L40S for fifteen minutes: the Python SDK calls fx.sandboxes.create, the command line runs fantasti sandbox create, REST posts to /v1/sandboxes and an agent calls the MCP tool sandboxes_create. All four reach the Fantasti API at api.fantasti.ai/v1 with one key and one error model, and the Fantasti Orchestrator places the request. One object comes back, sb_7q2m, with one id whichever interface asked. Connections: Python SDK to Fantasti API; CLI to Fantasti API; REST to Fantasti API; MCP server to Fantasti API; Fantasti API to sb_7q2m…: returns.
sb = fx.sandboxes.create(gpu="L40S", ttl="15m")- sync
- fantasti.Client
- async
- fantasti.AsyncClient
$ fantasti sandbox create \--gpu L40S --ttl 15m- binary
- fantasti
- grammar
- <noun> <verb>
POST /v1/sandboxes{ "gpu": "L40S", "ttl": "15m" }- body
- JSON over HTTPS
- auth
- Bearer $FANTASTI_API_KEY
sandboxes_create{ "gpu": "L40S", "ttl": "15m" }- wire
- Streamable HTTP
- tools
- 12 in early access
- host
- api.fantasti.ai/v1
- key
- one, for all four
- errors
- one model
- placed by
- Orchestrator
- L40S · 1 GPU
- id
- sb_7q2m…
- status
- ready
- placement
- us-east · on_demand
- ttl
- 15m
- policy
- team research
- concurrent
- 200 sandboxes
- max_ttl
- 60m
One object, whichever interface asked. The idone of them returns is the id the other threeuse, and the same policy limits all four.
sb = fx.sandboxes.create(gpu="L40S", ttl="15m")- sync
- fantasti.Client
- async
- fantasti.AsyncClient
$ fantasti sandbox create \--gpu L40S --ttl 15m- binary
- fantasti
- grammar
- <noun> <verb>
POST /v1/sandboxes{ "gpu": "L40S", "ttl": "15m" }- body
- JSON over HTTPS
- auth
- Bearer $FANTASTI_API_KEY
sandboxes_create{ "gpu": "L40S", "ttl": "15m" }- wire
- Streamable HTTP
- tools
- 12 in early access
- host
- api.fantasti.ai/v1
- key
- one, for all four
- errors
- one model
- placed by
- Orchestrator
- id
- sb_7q2m…
- status
- ready
- placement
- us-east · on_demand
- ttl
- 15m
- policy
- team research
- concurrent
- 200 sandboxes
- max_ttl
- 60m
One object, whichever interface asked. The id one of them returns is the id the other threeuse, and the same policy limits all four.
sb = fx.sandboxes.create(gpu="L40S", ttl="15m")- sync
- fantasti.Client
- async
- fantasti.AsyncClient
- to
- Fantasti API
$ fantasti sandbox create \--gpu L40S --ttl 15m- binary
- fantasti
- grammar
- <noun> <verb>
- to
- Fantasti API
POST /v1/sandboxes{ "gpu": "L40S", "ttl": "15m" }- body
- JSON over HTTPS
- auth
- Bearer $FANTASTI_API_KEY
- to
- Fantasti API
sandboxes_create{ "gpu": "L40S", "ttl": "15m" }- wire
- Streamable HTTP
- tools
- 12 in early access
- host
- api.fantasti.ai/v1
- key
- one, for all four
- errors
- one model
- placed by
- Orchestrator
- id
- sb_7q2m…
- status
- ready
- placement
- us-east · on_demand
- ttl
- 15m
- policy
- team research
- concurrent
- 200 sandboxes
- max_ttl
- 60m
One object, whichever interface asked. Theid one of them returns is the id the otherthree use, and the same policy limits allfour.
- One object, one id
- What comes back
curl -X POST https://api.fantasti.ai/v1/instances \
-H "Authorization: Bearer $FANTASTI_API_KEY" \
-H "Idempotency-Key: sft-0412-node" \
-H "Content-Type: application/json" \
-d '{
"name": "ft-01",
"gpu": "H100:1",
"capacity": { "mode": "spot", "max_price": "2.40",
"currency": "USD", "unit": "gpu_hour" },
"labels": { "team": "research", "run": "sft-0412" },
"placement_timeout": "15m"
}' Responses · illustrative
202 { "id": "ins_8f2a…", "status": "placing",
"labels": { "team": "research", "run": "sft-0412" } }
200 { "id": "ins_8f2a…", "status": "ready",
"placement": { "region": "us-east", "fabric": "a",
"capacity": "spot", "rate": "…" } } import fantasti
fx = fantasti.Client() # reads FANTASTI_API_KEY
ins = fx.instances.create(
name="ft-01",
gpu="H100:1",
capacity=fantasti.Spot(max_price=2.40), # USD per GPU-hour
labels={"team": "research", "run": "sft-0412"},
idempotency_key="sft-0412-node", # a retry returns the same object
placement_timeout="15m",
)
ins.wait("ready")
print(ins.placement) # region, fabric, rate, capacity mode
for obj in fx.instances.list(labels={"run": "sft-0412"}):
obj.release() # tear down the whole run Conventions.
One request carries all six. The same rules hold for every object and every interface.
- Authenticationa bearer token from
FANTASTI_API_KEY - Idempotencyan
Idempotency-Keyheader on every create, so retries are safe - Labelskey–value pairs on every object, used to list and tear down whole runs
- Placementevery placed object reports region, fabric, capacity mode and rate
- TimeUTC ISO 8601 timestamps; durations as
"15m"or seconds - MoneyUSD as decimal strings (
"2.40")
Errors that say why.
| Condition | Status | Code | The response says |
|---|---|---|---|
No pool can hold the request on one fabric The object stays placing until placement_timeout. The error then lists the closest pools and the constraint each failed. | 409 | no_ | The object stays placing until placement_timeout. The error then lists the closest pools and the constraint each failed. |
| The request exceeds a quota, cap or price ceiling Names the policy and the limit. | 403 | policy_ | Names the policy and the limit. |
A max price stays below the spot price past placement_timeout Until then the object reports blocked. Nothing has started. | 409 | spot_ | Until then the object reports blocked. Nothing has started. |
The same Idempotency-Key with a different body | 422 | idempotency_ | |
| Missing or invalid key | 401 | unauthorized |
{
"error": {
"status": 409,
"code": "no_capacity",
"request": { "gpu": "H100:8", "nodes": 16, "fabric": "infiniband" },
"closest": [
{ "pool": "pool-a", "region": "us-east", "failed": "96 free < 128" },
{ "pool": "pool-b", "region": "us-east", "failed": "32 free < 128" },
{ "pool": "pool-c", "region": "us-west", "failed": "no InfiniBand" },
{ "pool": "pool-d", "region": "eu-west", "failed": "region not allowed" }
]
}
} $ fantasti cluster create big-run --gpu H100:8 --nodes 16 --on-demand Output · illustrative
error 409 no_capacity
request 128 × H100 SXM5 · InfiniBand · us-* · on-demand
pool-a us-east · InfiniBand · 96 free ✕ 96 free < 128
pool-b us-east · InfiniBand · 32 free ✕ 32 free < 128
pool-c us-west · no InfiniBand ✕ no InfiniBand
pool-d eu-west · InfiniBand · 128 free ✕ region not allowed - Sheet
- 02 / 02
- Title
- API errors
- Conditions
- 5
- Reviewed
- 2026-10-10
The Fantasti API as tools for AI agents.
A remote MCP server that gives AI agents the Fantasti API as tools, inside the limits your admins set.
- Sign-inOAuth when a person is present, a scoped agent key when the agent runs alone
- Limitsquotas, spend caps and price ceilings apply to agents as they apply to people
{
"mcpServers": {
"fantasti": {
"type": "http",
"url": "https://mcp.fantasti.ai/mcp"
}
}
} {
"mcpServers": {
"fantasti": {
"type": "http",
"url": "https://mcp.fantasti.ai/mcp?features=sandboxes,jobs&project=evals",
"headers": { "Authorization": "Bearer ${FANTASTI_AGENT_KEY}" }
}
}
} Tool groups 12 tools in early access · 25 planned
- catalog 1 tool
- sandboxes 5 tools
- workspaces 3 tools
- jobs 2 tools
- usage 1 tool
- batch 3 tools
- flows 6 tools
- broker 3 tools
- quota 2 tools
- clusters 4 tools
- records 3 tools
- support 3 tools
- changelog 1 tool
One key. Every product.
Access opens in cohorts. Companies can request a place in the first, and places are limited.