Checkpoint.
A Checkpoint is a lease for "hold this for me." You drop a session output or state snapshot in, walk away, come back later, pull it down. Retrieval triggers deletion. Useful when your agent is about to terminate and needs to park something for its next incarnation (or for a successor) to pick up.
That's the shortcut. Under the hood, a Checkpoint is a Lease keyed by a workflow_id you pick, reserving a bounded slot of JSON state. The v1 backend treats the slot as a mutable, versioned key/value cell — you can overwrite it as many times as you want inside the paid capacity, and you can read it repeatedly. The clean "park once, pull once" pattern above is the typical way to use it; the cell just happens to support more.
Use Checkpoint when you want the shortcut. If you need the explicit file semantics or the multi-party handoff affordance, Storage is the primitive.
How the backend implements this shortcut today
- Keyed by
workflow_id. You pick the identifier at creation (up to 128 chars,A-Z a-z 0-9 . _ -). Every subsequent read/write/delete addresses the lease by that ID, not by the opaquelease_id. - Single cell, many versions.
PUToverwrites the current body; each write increments an internal version counter (returned asX-Checkpoint-Versionon reads). Only the latest body is served. - Reservation pricing. You pay upfront for
max_body_bytes × duration. Writes up to that size don't trigger additional charges — the "reservation" covers the lifetime. - Owner-only. Create, read, write, and delete all require authentication by the lease owner. Handoff is coming soon (see below) — today there is no anonymous access path.
Create a Checkpoint
Pay once. The initial request body becomes the first version of the stored state. X-Workflow-Id is your key; X-Max-Body-Bytes caps the reserved slot (defaults and ceilings come from system config).
# 256 KB slot for 1 hour, keyed by "crawl-job-42" curl -X POST https://relaystation.ai/api/checkpoint \ -H "Authorization: Bearer rs_live_YOUR_KEY" \ -H "X-Workflow-Id: crawl-job-42" \ -H "X-Duration-Seconds: 3600" \ -H "X-Max-Body-Bytes: 262144" \ -H "Content-Type: application/json" \ -d '{"cursor": 0, "visited": []}'
const state = { cursor: 0, visited: [] }; const res = await fetch('https://relaystation.ai/api/checkpoint', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.RS_KEY}`, 'X-Workflow-Id': 'crawl-job-42', 'X-Duration-Seconds': '3600', 'X-Max-Body-Bytes': '262144', 'Content-Type': 'application/json', }, body: JSON.stringify(state), }); console.log(await res.json());
state = {'cursor': 0, 'visited': []}
res = requests.post(
'https://relaystation.ai/api/checkpoint',
headers={
'Authorization': f'Bearer {os.environ["RS_KEY"]}',
'X-Workflow-Id': 'crawl-job-42',
'X-Duration-Seconds': '3600',
'X-Max-Body-Bytes': '262144',
'Content-Type': 'application/json',
},
json=state,
)
print(res.json())
Read the current state
The response body is the latest version as a raw JSON blob. Version and last-written timestamp come back in response headers so you can compare-and-set on the next write.
curl -i https://relaystation.ai/api/checkpoint/crawl-job-42 \
-H "Authorization: Bearer rs_live_YOUR_KEY"
const res = await fetch( 'https://relaystation.ai/api/checkpoint/crawl-job-42', { headers: { Authorization: `Bearer ${process.env.RS_KEY}` } }, ); const version = res.headers.get('x-checkpoint-version'); const state = await res.json();
res = requests.get( 'https://relaystation.ai/api/checkpoint/crawl-job-42', headers={'Authorization': f'Bearer {os.environ["RS_KEY"]}'}, ) version = res.headers['X-Checkpoint-Version'] state = res.json()
Update the state
A PUT overwrites the body. No additional payment — the initial lease reservation covers writes up to max_body_bytes. The version counter increments automatically; read it back in X-Checkpoint-Version.
curl -X PUT https://relaystation.ai/api/checkpoint/crawl-job-42 \ -H "Authorization: Bearer rs_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"cursor": 128, "visited": ["a", "b"]}'
await fetch( 'https://relaystation.ai/api/checkpoint/crawl-job-42', { method: 'PUT', headers: { 'Authorization': `Bearer ${process.env.RS_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ cursor: 128, visited: ['a', 'b'] }), }, );
requests.put( 'https://relaystation.ai/api/checkpoint/crawl-job-42', headers={ 'Authorization': f'Bearer {os.environ["RS_KEY"]}', 'Content-Type': 'application/json', }, json={'cursor': 128, 'visited': ['a', 'b']}, )
Delete early
The clean "pull it down and be done" flow doesn't require an explicit delete — lease expiry sweeps the slot regardless. But if your agent finishes before expiry and wants the capacity gone immediately:
curl -X DELETE https://relaystation.ai/api/checkpoint/crawl-job-42 \
-H "Authorization: Bearer rs_live_YOUR_KEY"
No refund is issued for early delete at v1 — you paid for the reservation, not for the occupancy.
Pricing
Checkpoint uses reservation pricing: you pay max_body_bytes × duration × rate at creation and write as many versions as you want inside that capacity, for free. See GET /api/pricing for the live rate.
Handing off a Checkpoint lease
Coming soon. Claim-token semantics for Checkpoint are in design;
POST /api/handoff/:lease_idis wired for Storage only today.If your agent wants to park a state snapshot for another agent to pick up right now, the direct path is: wrap the snapshot in a Storage lease with
delete_on_claim: true, and hand off the Storage lease. The successor agent redeems the claim URL once and gets the bytes — same one-shot flavor you'd want from a Checkpoint handoff, on a lease variant where handoff is already shipped.
Checkpoint-native handoff is tracked in the changelog.
Expiry behavior
At expires_at, the current body and every prior version are deleted. No grace period, no way to extend. Reads after expiry return 410 Gone.