API Reference
Base URL: https://subseq.bio/api/v1. Every response follows { "success": bool, "data"?: any, "error"?: string }. Send Authorization: Bearer <api_key> (or rely on the api_key cookie).
In every job container, uploaded or referenced data is mounted read-only at /inputs/, and auxiliary data is mounted read-only at /aux/. Results are written to /outputs/.
Rate limits
Per client IP: token bucket with burst of 10 requests, averaging ~6 req/s. Global: 800 requests per 10 seconds across all clients. If you receive HTTP 429, honor the Retry-After header (seconds to wait) or back off with exponential jitter.
Jobs
POST /job/submit
Launch a job via multipart/form-data. Include program, repeatable args, and one input source: uploaded folder files, input_src=dataset with digest, or input_src=job with from_job. input_src=upload is accepted but may be omitted when sending folder files. Optional fields include project, memo, deadline_minutes, aux_src (none | upload | dataset | job), aux_ref, and auxiliary file uploads via aux form fields (uploaded into /aux; aux_src=upload may be omitted when sending aux files).
Upload limits: request body up to 64 GiB total, and up to 20,000 files per upload field (folder and aux each).
curl -X POST https://subseq.bio/api/v1/job/submit \
-H "Authorization: Bearer sk-ss-admin-123" \
-F program=alphafold2 \
-F input_src=upload \
-F memo="Benchmark run 12" \
-F args=--fasta_paths=data/sample.fasta \
-F "folder=@data/sample.fasta;filename=data/sample.fasta"
{
"success": true,
"data": {
"job_id": "5bf2d83e40a47cf5"
}
}
POST /job/submit-guided
Launch a job through a program-specific guided schema. Use GET /program/params?program=... first to discover whether a program supports guided submit and which typed params it accepts. The request is multipart/form-data with program and params (a JSON object); optional project, memo, and the same uploaded folder, dataset digest, and previous-job from_job input fields from /job/submit are supported when guided file params refer to files under /inputs. input_src=upload may be omitted when sending folder files, but uploads cannot be combined with dataset or previous-job inputs. Guided auxiliary file params use the same aux_src/aux_ref/aux fields as /job/submit.
Do not send raw args or deadline_minutes; the guided builder owns server args, generated configs, /outputs, and related server paths. Guided input file and folder params accept source-relative paths such as target.pdb, /target.pdb, inputs/target.pdb, or /inputs/target.pdb. Guided auxiliary file params accept source-relative auxiliary paths such as main.py or aux/main.py.
curl -X POST https://subseq.bio/api/v1/job/submit-guided \
-H "Authorization: Bearer sk-ss-admin-123" \
-F program=rfdiffusion3 \
-F memo="guided RFD3 monomer" \
-F 'params={"mode":"unconditional_monomer","length":"120-130","num_structures":10}'
{
"success": true,
"data": {
"job_id": "5bf2d83e40a47cf5"
}
}
GET /job/list
List jobs (query params: limit <=100, offset, status, project, program, pipeline_id, before=YYYY-MM-DD). Each row includes input_src/input_ref and aux_src/aux_ref when the job depended on prior data, plus memo if one was provided.
curl -G https://subseq.bio/api/v1/job/list \
-H "Authorization: Bearer sk-ss-admin-123" \
--data-urlencode "limit=5" \
--data-urlencode "status=completed" \
--data-urlencode "program=alphafold2"
{
"success": true,
"data": {
"total": 12,
"jobs": [
{
"job_id": "5bf2d83e40a47cf5",
"status": "completed",
"cost": 18.5,
"program": "alphafold2",
"input_src": "dataset",
"input_ref": "08f9f54a1d55e548e54a9b857f2df70f44c2bcfe6ff5b846c8d3107568e1b6d9",
"project": "default",
"memo": "Benchmark run 12",
"aux_src": "job",
"aux_ref": "5bf2d83e40a47cf4",
"created_at": 1730678400,
"started_at": 1730678465,
"finished_at": 1730680200,
"last_charged_at": 1730679600
}
]
}
}
GET /job/view
Inspect a single job; requires jobid query. Returns input_src/input_ref and aux_src/aux_ref when the job used a dataset or another job as its source (omitted for generated jobs). Includes memo if provided and a manifest for finished jobs.
curl "https://subseq.bio/api/v1/job/view?jobid=5bf2d83e40a47cf5" \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true,
"data": {
"status": "completed",
"cost": 18.5,
"program": "alphafold2",
"user_args": "--fasta_paths=data/sample.fasta",
"server_args": "--max_template_date=2023-10-01",
"project": "default",
"memo": "Benchmark run 12",
"input_src": "job",
"input_ref": "5bf2d83e40a47cf4",
"aux_src": "dataset",
"aux_ref": "08f9f54a1d55e548e54a9b857f2df70f44c2bcfe6ff5b846c8d3107568e1b6d9",
"created_at": 1730678400,
"started_at": 1730678465,
"finished_at": 1730680200,
"log_tail": "Job finished successfully.",
"manifest": [
{
"path": "outputs/prediction.pdb",
"sha256": "b3b0bf9cf3b5c7d98a7d4012ee6324de470b01fb6bc2cbbb0f1e46f9d3db15bc",
"size": 2456789
}
]
}
}
POST /job/rerun
Create a new standalone job from a completed, failed, or canceled job. The rerun reuses the same program, validated arguments, project, deadline, and input/aux sources; uploaded input or auxiliary files are copied server-side. The new memo is set to Rerun of <jobid>: <prev memo>.
curl -X POST https://subseq.bio/api/v1/job/rerun \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"job_id":"5bf2d83e40a47cf5"}'
{
"success": true,
"data": {
"job_id": "6cf3e94f51b58d06",
"rerun_of_job_id": "5bf2d83e40a47cf5"
}
}
POST /job/cancel
Cancel a pending or running job via ?jobid=.
curl -X POST "https://subseq.bio/api/v1/job/cancel?jobid=5bf2d83e40a47cf5" \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true,
"data": "Job cancelled successfully"
}
GET /job/download
Download the job archive ZIP (?jobid=, optional accept_partial_data=true for failed/canceled jobs).
curl -L -o job_5bf2d83e40a47cf5.zip \
"https://subseq.bio/api/v1/job/download?jobid=5bf2d83e40a47cf5" \
-H "Authorization: Bearer sk-ss-admin-123"
HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="job_5bf2d83e40a47cf5.zip"
GET /job/file
Stream a single output (?jobid= & path= from manifest). Supports GET/HEAD.
curl -H "Authorization: Bearer sk-ss-admin-123" \
"https://subseq.bio/api/v1/job/file?jobid=5bf2d83e40a47cf5&path=outputs/prediction.pdb" \
| head
HTTP/1.1 200 OK
Content-Type: chemical/x-pdb
X-Subseq-File: 1
...raw file bytes...
POST /job/move-project
Reassign a job to an existing project (empty project removes assignment).
curl -X POST https://subseq.bio/api/v1/job/move-project \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"job_id":"5bf2d83e40a47cf5","project":"archive"}'
{
"success": true
}
Pipelines
POST /pipeline/submit
Create an auto-managed pipeline. Pipelines are ordered job steps that execute back-to-back. Each pipeline has one top-level pipeline input for shared static files, scripts, configs, targets, ligands, and other campaign assets. Step 2+ automatically consume the previous step outputs as their main input.
Each step can use either raw args or guided params. Do not include per-step input_src, input_ref, aux_src, or aux_ref; use top-level pipeline_input_src and pipeline_input_ref. Valid pipeline input sources are none, upload, and dataset. Multipart submits can upload files with the pipeline_input field when pipeline_input_src=upload.
curl -X POST https://subseq.bio/api/v1/pipeline/submit \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{
"project": "default",
"memo": "Two-step chain",
"pipeline_input_src": "dataset",
"pipeline_input_ref": "08f9f54a1d55e548e54a9b857f2df70f44c2bcfe6ff5b846c8d3107568e1b6d9",
"steps": [
{
"program": "rfdiffusion3",
"params": {
"mode": "unconditional_monomer",
"length": "80-90",
"num_structures": 1
}
},
{
"program": "ligandmpnn",
"args": ["--model_type=protein_mpnn"]
}
]
}'
{
"success": true,
"data": {
"pipeline_id": "ab12cd34",
"total_steps": 2
}
}
GET /pipeline/list
List pipelines (query params: limit <=100, offset, status, project).
curl -G https://subseq.bio/api/v1/pipeline/list \
-H "Authorization: Bearer sk-ss-admin-123" \
--data-urlencode "limit=5"
{
"success": true,
"data": {
"total": 1,
"pipelines": [
{
"pipeline_id": "ab12cd34",
"status": "running",
"project": "default",
"memo": "Two-step chain",
"active_job_id": "5bf2d83e40a47cf5",
"active_program": "rfdiffusion",
"next_step": 2,
"total_steps": 2,
"finished_at": 0
}
]
}
}
GET /pipeline/info
Inspect a pipeline by ?pipeline_id=. Includes steps_json (stringified JSON array of normalized steps), status, active job, and progress counters.
curl "https://subseq.bio/api/v1/pipeline/info?pipeline_id=ab12cd34" \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true,
"data": {
"pipeline_id": "ab12cd34",
"project": "default",
"memo": "Two-step chain",
"status": "running",
"steps_json": "[{\"program\":\"rfdiffusion3\",\"params\":{\"mode\":\"unconditional_monomer\",\"length\":\"80-90\",\"num_structures\":1}}]",
"active_job_id": "5bf2d83e40a47cf5",
"next_step": 2,
"total_steps": 2,
"finished_at": 0
}
}
Datasets
POST /dataset/new
Create a dataset: provide project, name, and either upload files via folder parts or set from_job to copy job outputs.
Use a short human label for name. Do not include dates or timestamps; creation time is already tracked in created_at.
Upload limits: request body up to 64 GiB total, and up to 20,000 files in folder.
Folder uploads strip the selected top-level folder. For example, run1/inputs/a.fa is stored as inputs/a.fa.
curl -X POST https://subseq.bio/api/v1/dataset/new \
-H "Authorization: Bearer sk-ss-admin-123" \
-F project=default \
-F name=protein-models \
-F "folder=@outputs/prediction.pdb;filename=prediction.pdb"
{
"success": true,
"data": {
"digest": "a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a"
}
}
POST /dataset/upload/presign
Mint an expiring, unauthenticated upload URL for a dataset ZIP archive. Requires SUBSEQ_PRESIGN_HMAC_SECRET to be set.
ZIP uploads strip one common top-level wrapper directory when all files share it; otherwise archive-relative paths are preserved. For example, bundle/prediction_inputs/a.fa becomes prediction_inputs/a.fa, while sibling directories such as boltz/a.yaml and msas/target.a3m stay nested.
curl -X POST https://subseq.bio/api/v1/dataset/upload/presign \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{
"project": "default",
"name": "protein-models",
"size_bytes": 123456789,
"format": "zip",
"sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"ttl_seconds": 3600
}'
{
"success": true,
"data": {
"upload_url": "https://subseq.bio/api/v1/dataset/upload?token=...",
"token": "...",
"expires_at": 1730683800,
"method": "PUT",
"max_bytes": 123456789
}
}
PUT /dataset/upload
Unauthenticated upload endpoint. Provide the presigned token as a query parameter. Upload a ZIP archive to create the dataset.
curl -X PUT -T protein-models.zip \
"https://subseq.bio/api/v1/dataset/upload?token=..."
{
"success": true,
"data": {
"digest": "a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a"
}
}
POST /dataset/edit
Edit a ready dataset by applying file deletes/additions. Use mode=update to keep the same dataset name, or mode=save_as to create under a new name.
curl -X POST https://subseq.bio/api/v1/dataset/edit \
-H "Authorization: Bearer sk-ss-admin-123" \
-F "base_digest=a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a" \
-F "mode=update" \
-F "delete=obsolete/model_old.pdb" \
-F "folder=@prediction_v2.pdb;filename=prediction_v2.pdb"
{
"success": true,
"data": {
"base_digest": "a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a",
"digest": "b2d7ad0fc2d88e35de9040f3fd3489e00cfba28d8803cbdc29a20d7db7787ba2",
"name": "protein-models",
"project": "default",
"mode": "update",
"changed": true
}
}
POST /dataset/delete
Delete by ?digest= or ?name=.
curl -X POST "https://subseq.bio/api/v1/dataset/delete?digest=a3d0...c8a" \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true
}
GET /dataset/info
Inspect dataset metadata (?digest= or ?name=).
curl "https://subseq.bio/api/v1/dataset/info?digest=a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a" \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true,
"data": {
"files": [
{
"path": "prediction.pdb",
"sha256": "936a1ec533d4c0bb7e90bcab44cbb6f4c012cfc16f0bcdf5ddf5d24c9fd4da45",
"size": 2456789
}
],
"meta": {
"name": "protein-models",
"digest": "a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a",
"project": "default",
"job_id": "5bf2d83e40a47cf5",
"size": 2456789,
"ready": true,
"dl_ready": true,
"created_at": "2025-10-01T17:20:45Z"
}
}
}
GET /dataset/list
List datasets (query: limit, offset, project). Returns the latest version per dataset name lineage.
curl -G https://subseq.bio/api/v1/dataset/list \
-H "Authorization: Bearer sk-ss-admin-123" \
--data-urlencode "limit=10"
{
"success": true,
"data": {
"total": 4,
"datasets": [
{
"digest": "a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a",
"name": "protein-models",
"project": "default",
"job_id": "5bf2d83e40a47cf5",
"size": 2456789,
"ready": true,
"dl_ready": true,
"created_at": 1730410800
}
]
}
}
GET /dataset/history
List version history for a dataset name. Query: name (required), limit, offset.
curl -G https://subseq.bio/api/v1/dataset/history \
-H "Authorization: Bearer sk-ss-admin-123" \
--data-urlencode "name=protein-models" \
--data-urlencode "limit=25"
{
"success": true,
"data": {
"total": 3,
"datasets": [
{
"digest": "b2d7ad0fc2d88e35de9040f3fd3489e00cfba28d8803cbdc29a20d7db7787ba2",
"name": "protein-models",
"project": "default",
"job_id": "",
"size": 2478910,
"ready": true,
"dl_ready": true,
"created_at": 1730497200
},
{
"digest": "a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a",
"name": "protein-models",
"project": "default",
"job_id": "5bf2d83e40a47cf5",
"size": 2456789,
"ready": true,
"dl_ready": true,
"created_at": 1730410800
}
]
}
}
GET /dataset/download
Download the dataset archive ZIP (available when dl_ready is true).
curl -L -o dataset_a3d0f65b.zip \
"https://subseq.bio/api/v1/dataset/download?digest=a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a" \
-H "Authorization: Bearer sk-ss-admin-123"
HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="dataset_a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a.zip"
GET /dataset/file
Stream a file from a ready dataset (?digest= & path=).
curl -H "Authorization: Bearer sk-ss-admin-123" \
"https://subseq.bio/api/v1/dataset/file?digest=a3d0...c8a&path=prediction.pdb" \
| head
HTTP/1.1 200 OK
Content-Type: chemical/x-pdb
X-Subseq-File: 1
...raw file bytes...
POST /dataset/move-project
Move a dataset lineage to an existing project (or clear by sending an empty string). All snapshots with the same name are updated.
curl -X POST https://subseq.bio/api/v1/dataset/move-project \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"digest":"a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a","project":"archive"}'
{
"success": true
}
POST /dataset/rename
Rename a dataset lineage. All snapshots with the same name are renamed together.
curl -X POST https://subseq.bio/api/v1/dataset/rename \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"name":"protein-models","new_name":"protein-models-v2"}'
{
"success": true
}
Presigned downloads
Mint short-lived, unauthenticated download links using a stateless HMAC-signed token. The minted link can be opened in a browser or shared with someone who should be able to download the data. The token expires after ttl_seconds (default: 3600; max: 604800).
Server config: requires SUBSEQ_PRESIGN_HMAC_SECRET to be set. All presigned downloads require dl_ready=true in the DB.
POST /download/presign
Authenticated endpoint to mint a presigned URL.
type is one of: job_download, job_file, dataset_download, dataset_file.
curl -X POST https://subseq.bio/api/v1/download/presign \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{
"type": "job_download",
"jobid": "5bf2d83e40a47cf5",
"ttl_seconds": 3600
}'
{
"success": true,
"data": {
"url": "https://subseq.bio/d?token=...",
"token": "...",
"expires_at": 1730683800
}
}
For failed/canceled jobs, include "accept_partial_data": true when minting job_download.
Mint a presigned URL for a single job file:
curl -X POST https://subseq.bio/api/v1/download/presign \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{
"type": "job_file",
"jobid": "5bf2d83e40a47cf5",
"path": "outputs/prediction.pdb",
"ttl_seconds": 600
}'
Mint a presigned URL for a dataset archive:
curl -X POST https://subseq.bio/api/v1/download/presign \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{
"type": "dataset_download",
"digest": "a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a",
"ttl_seconds": 3600
}'
Mint a presigned URL for a single dataset file:
curl -X POST https://subseq.bio/api/v1/download/presign \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{
"type": "dataset_file",
"digest": "a3d0f65ba9e14fdb8a95d9f31f4bc7b7ca5f2d93e8f12c6d42c439ab20c77c8a",
"path": "prediction.pdb",
"ttl_seconds": 600
}'
GET /download
Unauthenticated download endpoint. Provide the presigned token as a query parameter. Returns either a ZIP archive or a single file, depending on the token type.
curl -L -o out.zip "https://subseq.bio/d?token=..."
HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="job_5bf2d83e40a47cf5.zip"
Projects
POST /project/new
Create (or idempotently ensure) a project name.
curl -X POST https://subseq.bio/api/v1/project/new \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"name":"archive"}'
{
"success": true
}
GET /project/list
Return all projects for the account.
curl https://subseq.bio/api/v1/project/list \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true,
"data": [
{ "name": "archive", "created_at": 1730238000 },
{ "name": "default", "created_at": 1728000000 }
]
}
POST /project/delete
Delete a project and clear it from jobs/datasets.
curl -X POST https://subseq.bio/api/v1/project/delete \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"name":"archive"}'
{
"success": true
}
Public
GET /status
Service heartbeat.
curl https://subseq.bio/api/v1/status
{
"success": true
}
GET /program/list
List active programs with pricing info.
curl https://subseq.bio/api/v1/program/list
{
"success": true,
"data": [
{
"name": "alphafold2",
"display_name": "AlphaFold2",
"description": "AlphaFold2 monomer inference with reduced DBs.",
"cost_per_hour": 14.5,
"submit_fee": 0,
"min_run_time": 900
}
]
}
GET /program/params
Return the typed guided submission schema for one active program (?program=). A guided program returns guided: true plus ordered modes and params; a program without guided support returns guided: false with a message.
Each param includes a stable name, type, and label, with optional metadata such as required, default, options, extensions, min, max, bounds, depends_on, modes, selection, and help. Send selected values back as the JSON params field to /job/submit-guided.
curl "https://subseq.bio/api/v1/program/params?program=rfdiffusion3"
Abridged response:
{
"success": true,
"data": {
"program": "rfdiffusion3",
"guided": true,
"display_name": "RFdiffusion3",
"description": "RFdiffusion3 design for binders, unconditional monomers, and symmetric oligomers.",
"modes": [
{
"name": "binder_design",
"label": "Binder Design",
"description": "Design binders against a target structure using contigs and hotspot residues.",
"default": true
},
{
"name": "unconditional_monomer",
"label": "Unconditional Monomer",
"description": "Generate de novo monomers from a requested length range."
}
],
"params": [
{
"name": "target_structure",
"type": "structure_file",
"label": "Target Structure",
"required": true,
"modes": ["binder_design"],
"extensions": [".pdb", ".cif"]
},
{
"name": "length",
"type": "length_range",
"label": "Length",
"required": true,
"placeholder": "120-130",
"modes": ["unconditional_monomer"],
"min": 3,
"max": 2000
},
{
"name": "num_structures",
"type": "int",
"label": "Structures",
"default": 10,
"min": 1,
"max": 10000
},
{
"name": "output_format",
"type": "string",
"label": "Output Type",
"default": "cif",
"options": ["cif", "pdb", "cif.gz"]
}
]
}
}
GET /pricing
Current submit fee and server-configured payment top-up maximum.
curl https://subseq.bio/api/v1/pricing
{
"success": true,
"data": {
"submit_fee": 0,
"top_up_max_credits": 5000
}
}
Use data.top_up_max_credits as the numeric maximum for payment credit requests.
Auth & Account
POST /auth/otp
Send a one-time code to email ({ "email": string }).
curl -X POST https://subseq.bio/api/v1/auth/otp \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com"}'
{
"success": true
}
POST /auth/login
Exchange OTP for an admin API key. type=api returns the key; web sets the cookie.
curl -X POST https://subseq.bio/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","otp":"123456","type":"api"}'
{
"success": true,
"data": {
"token": "sk-ss-admin-123",
"expires_at": 1733107200
}
}
GET /account/info
Retrieve credits and metadata.
curl https://subseq.bio/api/v1/account/info \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true,
"data": {
"email": "you@example.com",
"credits": 87.5,
"created_at": 1693526400,
"last_activity": 1733073600
}
}
POST /account/logout
Invalidate the current admin key (Authorization header or cookie).
curl -X POST https://subseq.bio/api/v1/account/logout \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true
}
API Keys
Requires an admin key from /auth/login. Returned keys are non-admin client keys.
GET /key/list
List non-admin keys.
curl https://subseq.bio/api/v1/key/list \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true,
"data": [
{
"key_hash": "api_9ad2f7...",
"hint": "sk-ss-api-13****",
"label": "cli",
"expires_at": 1734316800
}
]
}
POST /key/new
Create a non-admin key (optional label, expires_in_days).
curl -X POST https://subseq.bio/api/v1/key/new \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"label":"cli","expires_in_days":30}'
{
"success": true,
"data": {
"key": "sk-ss-api-13abcdefg"
}
}
POST /key/delete
Delete a non-admin key by key_hash.
curl -X POST https://subseq.bio/api/v1/key/delete \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"key_hash":"api_9ad2f7..."}'
{
"success": true
}
Payments
POST /payment/create-checkout
Create a Stripe Checkout session ({ "credits": int }, minimum 1 and maximum top_up_max_credits from /pricing).
curl -X POST https://subseq.bio/api/v1/payment/create-checkout \
-H "Authorization: Bearer sk-ss-admin-123" \
-H "Content-Type: application/json" \
-d '{"credits":50}'
{
"success": true,
"data": {
"url": "https://checkout.stripe.com/c/pay/cs_test_a1b2..."
}
}
GET /payment/verify
Finalize a Stripe payment (?session_id=, ?tx= from checkout).
curl "https://subseq.bio/api/v1/payment/verify?session_id=cs_test_a1b2&tx=tx-6f828251" \
-H "Authorization: Bearer sk-ss-admin-123"
{
"success": true,
"data": {
"url": "https://subseq.bio"
}
}
POST /payment/x402/topup
Add credits with x402 using USDC on Base ({ "credits": int }, minimum 1 and maximum top_up_max_credits from /pricing). This endpoint is intended for AI agents and other automated clients.
curl -i -X POST https://subseq.bio/api/v1/payment/x402/topup \
-H "Authorization: Bearer sk-ss-api-123" \
-H "Content-Type: application/json" \
-d '{"credits":1}'
If no payment is attached, the server returns 402 Payment Required with a PAYMENT-REQUIRED header describing the required USDC payment.
HTTP/2 402
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQQVlNRU5ULVNJR05BVFVSRS...
WWW-Authenticate: x402
{
"x402Version": 2,
"error": "PAYMENT-SIGNATURE header is required",
"resource": {
"url": "https://subseq.bio/api/v1/payment/x402/topup",
"description": "Add compute credits to a subseq.bio account",
"mimeType": "application/json",
"serviceName": "subseq.bio",
"tags": ["bioinformatics", "compute", "credits"]
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "1000000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x...",
"maxTimeoutSeconds": 60,
"extra": {
"name": "USD Coin",
"version": "2"
}
}
]
}
An x402-aware client retries the same request with the PAYMENT-SIGNATURE header. After successful settlement, the account balance is credited immediately.
{
"success": true,
"data": {
"txid": "tx-6f828251",
"credits": 1,
"currency": "usdc",
"provider_ref": "0x...",
"payer": "0x...",
"network": "eip155:8453",
"amount": "1000000"
}
}
GET /tx/list
List transactions (query: limit, offset, status=pending|success|failed|any).
curl -G https://subseq.bio/api/v1/tx/list \
-H "Authorization: Bearer sk-ss-admin-123" \
--data-urlencode "limit=5"
{
"success": true,
"data": {
"total": 3,
"txs": [
{
"txid": "tx-6f828251",
"user_id": 42,
"email": "you@example.com",
"amount": 50,
"currency": "usd",
"status": "success",
"created_at": 1733071800,
"completed_at": 1733071860
}
]
}
}
Error Model
Failures use HTTP 4xx/5xx with {"success": false, "error": "message"}. Common cases: 400 invalid input, 401 missing/expired auth, 403 insufficient credits or non-admin, 404 missing resource, 429 rate limit, 503 compute backend offline.