REST API

Overview

Lucihub exposes a versioned REST API under /api/v1. The API is the single mode of interaction with the system: both LuciHubClient and the lucihub-cli package go through it. Because the API is described by an OpenAPI-compatible specification (linked below), third-party clients can interface with LUCIHUB just as easily.

Live documentation

The deployed server serves the OpenAPI UI at /api/docs (Swagger UI) and /api/redoc (ReDoc). For anabrid's production deployment of LUCIHUB, this is reachable at https://redac.anabrid.com/api/docs.

Authentication

Every request to /api/v1/* must carry a Bearer token:

Authorization: Bearer <api_key>

Missing, disabled, or unknown keys are answered with 403 Forbidden. For run-task creation, the server additionally checks device access for the user (403 on denial) and hourly / daily rate limits for the device class (429 when exceeded). Limits are set by operators in the auth.yml file — contact your operator if you need to bump your limits.

Endpoint groups

For more detailed information and data types, please refer to the API documentation linked above.

Prefix Purpose
/api/v1/system Deployment identity and uptime.
/api/v1/users Authenticated user's profile and remaining quota.
/api/v1/devices Registered devices and their cached entity blobs.
/api/v1/tasks Compile and run tasks: creation, listing, status, logs, results, cancel, delete.

/system

Method Path Description
GET /api/v1/system/status Domain, version, uptime (seconds since server start).

/users

Method Path Description
GET /api/v1/users/me Profile (name, email, subscription, device whitelist) and per-device-class rate-limit status.

/devices

Method Path Description
GET /api/v1/devices List registered devices with name, type, availability, queue length.
GET /api/v1/devices/{device_name}/entity Retrieves the entity specification as binary blob. Can be used with pyredacc to configure the SIMULATOR and to analyze the structure of the hardware.

/tasks

Method Path Description
POST /api/v1/tasks/compile Create a compile task for devices (except SIMULATOR-type devices) which creates a circuit description from a system of ODEs.
POST /api/v1/tasks/run Given a manually-created (via pybrid) or compiled circuit, run it on one device. Since a hardware description is embedded in every circuit, users may also point it to SIMULATOR devices in order to get a mathematical simulation of the circuit.
GET /api/v1/tasks List tasks for the caller, identified via its API key, with their states.
GET /api/v1/tasks/{task_id} Returns details on a task given its ID.
GET /api/v1/tasks/{task_id}/status Current state plus full state history given a task ID.
GET /api/v1/tasks/{task_id}/log Retrieve log generated by a task, e.g., from the compiler executable.
GET /api/v1/tasks/{task_id}/result Download task's result. application/octet-stream (APB binary) for compile, application/json (nested measurement list) for run. Returns 404 until the task reaches succeeded.
POST /api/v1/tasks/{task_id}/cancel Cancel a queued task. Returns 409 if not in queued state.
DELETE /api/v1/tasks/{task_id} Delete the task and its blobs. Returns 409 if INPROGRESS and the 2-minute grace window has not elapsed. 204 on success.

Non-versioned endpoints

Method Path Auth Description
GET /health none Liveness probe, returns {"status": "healthy"} when the server is operational.

Common types and workflows

All task creation endpoints return the same shape:

class TaskCreatedResponse(BaseModel):
    id: UUID
    type: "compile" | "run"
    state: TaskStateEnum  # always "queued" at creation
    created_at: datetime

Task state values are queued, inprogress, succeeded, failed, and cancelled; the last three are terminal. Errors use a consistent body of {"detail": "<message>"}.

Status Meaning
400 Bad request (e.g. backend = SIMULATOR on a compile task).
403 Auth failure or device access denied.
404 Task / device not found, or task result not yet available.
409 State conflict (cancel a non-queued task, delete an in-flight task within grace).
429 Rate limit exceeded for the device class.
500 Server error.
503 Target device not available.

LUCIHUB is a distributed system made up of a server (accepting and processing HTTP requests), a database (holding task data), a queue per registered device (a list of pending jobs to be processed), and workers that perform the actual processing of tasks. Different components may be deployed to different physical machines, but this is transparent from an API-only perspective. It is, however, useful to understand how tasks are processed in order to understand why a job might take a long time or fail:

sequenceDiagram autonumber actor User participant API as REST API participant Q as Queue / Worker participant DB as Storage User->>API: POST /api/v1/tasks/{compile|run} API->>DB: persist task, blobs API->>Q: enqueue API-->>User: 201 TaskCreatedResponse (state=queued) loop until terminal User->>API: GET /api/v1/tasks/{id}/status API-->>User: TaskStatusResponse end Q->>DB: write result + log (state -> succeeded/failed) User->>API: GET /api/v1/tasks/{id}/result API-->>User: APB bytes (compile) or JSON measurements (run) User->>API: GET /api/v1/tasks/{id}/log API-->>User: log lines opt cleanup User->>API: DELETE /api/v1/tasks/{id} API->>DB: drop task and blobs API-->>User: 204 end

For Developers: Generating clients

The OpenAPI document served at https://redac.anabrid.com/api/docs / https://redac.anabrid.com/api/redoc (with raw JSON at https://redac.anabrid.com/openapi.json, assuming anabrid's production setup) is suitable as input to any standard OpenAPI client generator. lucihub-cli is the reference Python client; equivalent clients in other languages can be produced from the same schema.