API reference
API overview
Base URL, authentication, errors, pagination, idempotency and versioning for the Rayform HTTP API.
The Rayform API is a JSON-over-HTTPS API. It handles control: creating sessions, searching, freezing slices, starting exports. Bulk data never travels through it; uploads and downloads use signed storage URLs, and event streams use Arrow Flight.
Base URL
All endpoints are relative to this URL. The API is versioned in the path; breaking changes ship as a new version.
Authentication
Create keys in the console and send them as a bearer token. Keys are scoped to one organisation and carry read and, optionally, write permission.
curl https://api.rayform.world/v1/sessions \
-H "Authorization: Bearer $RAYFORM_API_KEY"| Key prefix | Use |
|---|---|
rf_live_ | Production data |
rf_test_ | A sandbox organisation with sample recordings, for integration tests (coming soon) |
Keep keys out of source control. On clusters, pass them through the environment or your secret manager.
Requests and responses
- Request bodies are JSON with
Content-Type: application/json. - Timestamps are ISO 8601 strings in UTC; times inside recordings are integer nanoseconds (
t_ns). - Every object has an
idand anobjectfield naming its type. - Responses include a
Request-Idheader. Quote it when you contact support.
Errors
Errors use standard HTTP status codes and a JSON body:
{
"error": {
"type": "invalid_request",
"code": "parameter_invalid",
"message": "format must be one of: lerobot, rlds, webdataset, mcap, usd, mjcf",
"param": "format",
"request_id": "req_01JA9C4T7V"
}
}| Status | type | When |
|---|---|---|
| 400 | invalid_request | A parameter is missing or malformed |
| 401 | authentication | The key is missing, revoked or wrong |
| 403 | permission | The key lacks write, or the object belongs to another organisation |
| 404 | not_found | The object does not exist |
| 409 | conflict | The request conflicts with the object's state, for example completing an upload twice |
| 422 | processing | The request is valid but cannot be done, for example exporting a slice with no segments |
| 429 | rate_limited | Too many requests; retry after Retry-After seconds |
| 5xx | api_error | A problem on our side; safe to retry with the same Idempotency-Key |
Pagination
List endpoints return up to limit items (default 50, maximum 500) and a cursor:
{
"object": "list",
"data": [{ "id": "seg_4f0a", "object": "segment" }],
"has_more": true,
"next_cursor": "c2VnXzRmMGE"
}Pass cursor=<next_cursor> to get the next page. The SDK iterates through pages for you.
Idempotency
Send an Idempotency-Key header with any POST. Repeating a request with the same key within 24 hours returns the original response instead of creating a second object.
curl -X POST https://api.rayform.world/v1/exports \
-H "Authorization: Bearer $RAYFORM_API_KEY" \
-H "Idempotency-Key: export-slc_7c1e04aa-lerobot-v1" \
-H "Content-Type: application/json" \
-d '{"slice": "slc_7c1e04aa", "format": "lerobot"}'Rate limits
Limits are per key and returned on every response in RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. Back off on 429 and honour Retry-After.
Resources
Last updated October 18, 2026