REST API¶
FastAPI application exposing the SeqChain engine over HTTP. Tracks are immutable UUID-keyed resources — every computation produces a new track. Results are cached by provenance (identical operation + inputs + params returns the same track ID).
Design: generic method dispatch¶
The API has no per-method handlers. Instead, a declarative registry
(METHOD_REGISTRY in routes/methods.py) maps method IDs to:
- Discovery fields: name, description, parameter schema, return type. Serialized as JSON for hubs to build UI from.
- Dispatch fields: the callable, input specs (which store to load from), and parameter names. Never serialized — internal to the dispatcher.
The generic dispatcher does the same thing for every method:
- Look up method in registry (404 if missing)
- For each input: load from the declared store (track or genome), 404 if missing
- Collect params from request body
- Call the registered function
- Store result with provenance
- Return
{track_id}
Adding a new method = one registry entry. Zero handler code.
Sidecar protocol¶
SeqChain runs as a sidecar service. A frontend hub discovers and calls methods without hardcoding knowledge of engine internals.
Hub SeqChain
─── ────────
1. GET /api/methods → method catalog with parameter schemas
2. POST /api/tracks → upload data, receive track_id
3. POST /api/methods/{id} → call method with track_ids → result_id
4. GET /api/tracks/{id} → download result
Parameter types tell the hub how to render each field:
| Type | Hub behavior |
|---|---|
track |
Show file/track picker, upload to /api/tracks, use returned ID |
genome |
Show genome picker, upload to /api/genomes, use returned ID |
string |
Show text input, pass value directly |
number |
Show number input, pass value directly |
boolean |
Show toggle, pass value directly |
object |
Show structured input (JSON), pass value directly |
The engine never knows what UI the hub builds. The hub never knows what the engine does internally. The contract is the method schema.
Quick start¶
# Health check
curl localhost:8000/api/health
# Discover available methods
curl localhost:8000/api/methods
# Describe a single method
curl localhost:8000/api/methods/overlay
# Upload two tracks
QID=$(curl -s -X POST localhost:8000/api/tracks/upload \
-F "file=@query.bed" | jq -r .track_id)
RID=$(curl -s -X POST localhost:8000/api/tracks/upload \
-F "file=@reference.bed" | jq -r .track_id)
# Call a method
curl -X POST localhost:8000/api/methods/overlay \
-H 'Content-Type: application/json' \
-d "{\"query_track_id\": \"$QID\", \"reference_track_id\": \"$RID\"}"
# Download result
curl localhost:8000/api/tracks/$RESULT_ID
Endpoints¶
| Endpoint | Method | Purpose |
|---|---|---|
/api/health |
GET | Liveness probe |
/api/methods |
GET | List all available methods |
/api/methods/{id} |
GET | Describe a single method |
/api/methods/{id} |
POST | Generic method dispatch |
/api/tracks |
CRUD | Track management (upload, export, query) |
/api/genomes |
CRUD | Genome management (upload, metadata, features) |
Pages¶
- App Factory —
create_app()and router wiring - Stores —
TrackStore,GenomeStore, provenance caching - Serializers — Track/Region → JSON via public protocol