Platform API Reference
Complete REST API reference for CenterOS. 39 actions across 9 categories, all discoverable via a single endpoint.
Base URL
All API endpoints are relative to the production backend:
https://fearless-backend-533466225971.us-central1.run.app
For local development, the Vite dev server proxies /api to localhost:8000 automatically. You can also use the CENTEROS_API_URL environment variable to override the base URL in the CLI and MCP server.
Authentication
The API supports two authentication methods. All authenticated endpoints require a Bearer token in the Authorization header.
JWT (Session Token)
Obtained by logging in with username and password. Short-lived, suitable for interactive sessions.
# Login and get a JWT $ curl -X POST https://fearless-backend-533466225971.us-central1.run.app/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "jerry", "password": "***"}' # Response includes: {"access_token": "eyJ...", "user": {...}}
PAT (Personal Access Token)
Long-lived tokens for CI/CD pipelines, scripts, and agent workflows. PAT tokens start with the frl_ prefix. Create one via the CLI or the platform dashboard.
# Create a PAT via CLI $ centeros pat create --name "my-agent" --scopes "*" # PAT created: frl_abc123... # Use the PAT in API calls $ curl https://fearless-backend-533466225971.us-central1.run.app/api/actions \ -H "Authorization: Bearer frl_abc123..."
datasets:read,training:write). Use * for full access. The API filters visible actions based on your token's scopes.
Health Check
$ curl https://fearless-backend-533466225971.us-central1.run.app/api/health # {"status": "ok", "version": "...", "database": "ok"}
No authentication required. Returns 200 when the backend is healthy.
Action Layer
The Action Layer is the unified API surface shared by the platform UI, CLI, MCP server, and AI agents. All 39 actions are discoverable via two endpoints:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/actions | List all available actions with input schemas. Optionally filter by ?category=datasets. |
| POST | /api/actions/{name} | Execute an action by name. Body: {"params": {...}}. Requires Bearer token. |
Discover actions
# List all actions (public — no auth needed for discovery) $ curl https://fearless-backend-533466225971.us-central1.run.app/api/actions # Filter by category $ curl "https://fearless-backend-533466225971.us-central1.run.app/api/actions?category=training"
Execute an action
$ curl -X POST https://fearless-backend-533466225971.us-central1.run.app/api/actions/list_datasets \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"limit": 10}}' # {"ok": true, "data": [...]}
Datasets
Manage robotics datasets — list, get details, upload, and delete. Scopes: datasets:read datasets:write
| Action | Description | Required Params | Scope |
|---|---|---|---|
list_datasets | List datasets with optional search, file type, and pagination filters. | None | datasets:read |
get_dataset | Get detailed information about a single dataset. | dataset_id | datasets:read |
delete_dataset | Delete a dataset and its associated file from storage. | dataset_id | datasets:write |
upload_dataset | Create a dataset record (metadata). For file upload, use get_upload_signed_url. | name | datasets:write |
get_upload_signed_url | Generate a GCS signed URL for direct-to-cloud dataset upload. | filename, file_size | datasets:write |
confirm_upload | Confirm that a signed-URL upload completed. Marks the dataset as ready. | dataset_id | datasets:write |
# List datasets with search filter $ curl -X POST .../api/actions/list_datasets \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"search": "grasp", "file_type": "hdf5", "limit": 20}}' # Upload flow: get signed URL, upload file, confirm $ curl -X POST .../api/actions/get_upload_signed_url \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"filename": "episode_001.hdf5", "file_size": 52428800}}'
Training
Create and manage training and fine-tuning jobs. Scopes: training:read training:write
| Action | Description | Required Params | Scope |
|---|---|---|---|
list_training_jobs | List training jobs with optional status and model type filters. | None | training:read |
create_training_job | Create a new training or fine-tuning job from one or more datasets. | dataset_ids | training:write |
get_training_status | Get the current status and details of a training job. | job_id | training:read |
launch_training | Launch a pending training job (transition to running). | job_id | training:write |
get_finetune_catalog | List all supported fine-tuning base model providers and models. | None | training:read |
estimate_cost | Estimate the cost of a training run based on datasets and infra. | None | training:read |
# Create a training job $ curl -X POST .../api/actions/create_training_job \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"name": "dp-v1", "model_type": "diffusion_policy", "dataset_ids": [1, 2], "mode": "finetune"}}' # Launch a pending job $ curl -X POST .../api/actions/launch_training \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"job_id": "abc123def456"}}'
Models
Model registry with lifecycle management. Scopes: models:read models:write
| Action | Description | Required Params | Scope |
|---|---|---|---|
list_models | List model versions with optional status and name filters. | None | models:read |
register_model | Register a new model version in the model registry. | name | models:write |
promote_model | Promote a model through lifecycle stages: draft → validated → deployed → retired. | model_id, target_status | models:write |
get_model_lineage | Get full lineage: training job, datasets, deployments, evaluations. | model_id | models:read |
# Register a model from a training run $ curl -X POST .../api/actions/register_model \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"name": "dp-v1", "artifact_uri": "gs://bucket/model.pt", "training_job_id": "abc123"}}' # Promote to validated $ curl -X POST .../api/actions/promote_model \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"model_id": 5, "target_status": "validated"}}'
Fleet
Robot fleet management, deployment, and safety commands. Scopes: fleet:read fleet:write
| Action | Description | Required Params | Scope |
|---|---|---|---|
get_fleet_summary | High-level fleet summary: counts by status, alerts, tickets. | None | fleet:read |
list_robots | List robots with optional status, site, and search filters. | None | fleet:read |
get_robot_state | Detailed state of a single robot: heartbeat, commands, alerts. | robot_id | fleet:read |
register_robot | Register a new robot in the fleet. | robot_id | fleet:write |
deploy_model | Deploy a validated model version to a specific robot. | robot_id, model_version_id | fleet:write models:read |
emergency_stop | Send an emergency stop (e-stop) command to a robot. Highest priority. | robot_id | fleet:write |
# Register a robot $ curl -X POST .../api/actions/register_robot \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"robot_id": "arm-01", "name": "Lab Arm 1", "robot_type": "arm"}}' # Deploy a model to a robot $ curl -X POST .../api/actions/deploy_model \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"robot_id": "arm-01", "model_version_id": 5, "strategy": "immediate"}}' # Emergency stop $ curl -X POST .../api/actions/emergency_stop \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"robot_id": "arm-01", "reason": "safety_check"}}'
Annotations
Data annotation task management and quality metrics. Scopes: annotations:read annotations:write
| Action | Description | Required Params | Scope |
|---|---|---|---|
list_annotation_tasks | List annotation tasks with optional status, assignee, and search filters. | None | annotations:read |
create_annotation_task | Create a new annotation task, optionally linked to a dataset. | None (title recommended) | annotations:write |
get_annotation_metrics | Aggregated quality metrics: pass rate, review counts, status distribution. | None | annotations:read |
submit_task | Submit an annotation task for review (transition to in_review). | task_id | annotations:write |
# Create an annotation task $ curl -X POST .../api/actions/create_annotation_task \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {"title": "Label grasp episodes", "dataset_id": 42, "data_type": "video", "priority": "high"}}'
Organizations
Organization and team membership management. Scopes: orgs:read orgs:write
| Action | Description | Required Params | Scope |
|---|---|---|---|
list_orgs | List organizations. Superadmins see all; others see only their org. | None | orgs:read |
list_org_members | List members of an organization with their roles. | None (org_id optional) | orgs:read |
invite_member | Invite a user to an organization. Creates the user if they do not exist. | org_id, email | orgs:write |
Stats
Platform-wide statistics and system health checks. Scope: stats:read
| Action | Description | Required Params | Scope |
|---|---|---|---|
get_platform_stats | Aggregated platform statistics: dataset counts, training jobs, robots, annotations. | None | stats:read |
get_system_health | Check the health of backend systems: database, storage, overall status. | None | stats:read |
# Get platform stats $ curl -X POST .../api/actions/get_platform_stats \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {}}' # Check system health $ curl -X POST .../api/actions/get_system_health \ -H "Authorization: Bearer frl_..." \ -H "Content-Type: application/json" \ -d '{"params": {}}'
Error Codes
All action errors return a JSON body with {"ok": false, "detail": "..."} and the appropriate HTTP status code.
| Code | Meaning | Common Cause |
|---|---|---|
| 400 | Bad Request | Missing required parameter or invalid value. |
| 401 | Unauthorized | Missing or invalid Bearer token. |
| 403 | Forbidden | Token scopes do not include the required permission, or org isolation violation. |
| 404 | Not Found | Unknown action name, or resource (dataset, model, robot) does not exist. |
| 409 | Conflict | Duplicate resource (e.g. robot already registered, user already a member). |
| 413 | Payload Too Large | File exceeds the maximum upload size. |
| 500 | Internal Server Error | Unhandled exception in the action handler. |
Scopes Reference
Scopes control which actions a token can access. PATs can be created with specific scopes; JWTs derive scopes from the user's role.
| Scope | Actions Granted |
|---|---|
datasets:read | list_datasets, get_dataset |
datasets:write | delete_dataset, upload_dataset, get_upload_signed_url, confirm_upload |
training:read | list_training_jobs, get_training_status, get_finetune_catalog, estimate_cost |
training:write | create_training_job, launch_training |
models:read | list_models, get_model_lineage |
models:write | register_model, promote_model |
fleet:read | get_fleet_summary, list_robots, get_robot_state |
fleet:write | register_robot, deploy_model, emergency_stop |
annotations:read | list_annotation_tasks, get_annotation_metrics |
annotations:write | create_annotation_task, submit_task |
orgs:read | list_orgs, list_org_members |
orgs:write | invite_member |
stats:read | get_platform_stats, get_system_health |
* | All actions (wildcard) |
Role-to-Scope Mapping
| Role | Scopes |
|---|---|
| admin | All scopes |
| operator | datasets:*, training:*, models:read, fleet:*, annotations:*, stats:read |
| annotator | datasets:read, annotations:*, stats:read |
| viewer | All :read scopes |