Skip to Content
ReferenceApp API

App API

This page documents HTTP endpoints exposed by an installed SeqDesk instance — the in-app API surface, as opposed to the public seqdesk.com endpoints covered by the Pipeline API. Most are used by the SeqDesk UI itself, but they are stable enough to call from automation, scripts, or external tools.

All endpoints live under /api/ on your SeqDesk host. Authentication uses the standard NextAuth session cookie unless noted. The pipeline weblog is the main exception — it is authenticated by a shared secret, not a session.

Form schemas

The dynamic form configuration is exposed read-only so external tooling can mirror the same field set the SeqDesk UI renders.

GET /api/form-schema

Returns the order-form schema as configured by the facility admin in the Order Form Builder.

{ "fields": [ { "id": "...", "name": "library_strategy", "type": "select", "options": [...], "required": true, "groupId": "..." } ], "groups": [ { "id": "group_sequencing", "name": "Sequencing Information", "icon": "Dna", "order": 1 } ], "version": "2026-04-01T00:00:00Z", "enabledMixsChecklists": ["ERC000022"], "perSampleFields": ["sample_name", "barcode"] }

The response is filtered by the caller’s role: facility-admin-only fields are omitted for researchers.

GET /api/study-form-schema

Same shape, but for the study metadata form. Includes additional studyFields and modules keys describing study-level vs. sample-level fields and which modules’ fields are currently enabled.

MIxS checklists

MIxS  is the GSC’s Minimum Information about a Sequence checklist standard. SeqDesk ships checklist definitions and field templates; admins enable specific checklists through the form builder, and researchers see the corresponding required fields when filling out study metadata.

GET /api/mixs-checklists

List all available checklists.

curl https://your-host/api/mixs-checklists
{ "checklists": [ { "name": "soil", "file": "soil-checklist.json", "fieldCount": 53, "mandatoryCount": 12, "accession": "ERC000022" } ], "total": 16 }

Single-checklist lookup with ?accession= or ?name=:

curl https://your-host/api/mixs-checklists?accession=ERC000022

Returns the full checklist definition including every field, its data type, unit options, MIxS section, and whether it is mandatory.

GET /api/mixs-templates

The same field definitions but in template form, ready to be embedded in the form builder. ?name=<checklist> returns templates for one checklist.

Pipeline weblog

Nextflow runs are configured to POST execution events to the SeqDesk weblog endpoint. The endpoint also accepts events from other pipeline-runtime adapters (SLURM trace, queue updates, internal step events). See Pipeline Runtime for the client-side configuration.

POST /api/pipelines/weblog?runId=<id>&token=<secret>

Each call records one PipelineRunEvent. The target run is identified by the runId query parameter, and the call is authenticated by the shared weblog secret passed as the token query parameter — there is no session cookie and no runId in the body.

ConditionStatus
No weblog secret configured on the instance503
token does not match the configured secret403
Missing runId400
Unknown runId404

The weblog secret is configured under Admin → Application Settings → Pipeline execution; until it is set the endpoint fails closed (503) so the state-mutating webhook is never left unauthenticated.

The JSON body is the Nextflow -with-weblog payload (or another adapter’s event). SeqDesk reads the event type from event / eventType / type and the process/trace details from trace (or task):

curl -X POST "https://your-host/api/pipelines/weblog?runId=ckxx...&token=$WEBLOG_SECRET" \ -H "Content-Type: application/json" \ -d '{ "event": "process_completed", "trace": { "process": "MAG:ASSEMBLY:MEGAHIT", "status": "COMPLETED", "exit": 0, "duration": "00:43:12", "%cpu": "812", "rss": "12.3 GB" } }'

On success the endpoint returns { "success": true }.

Event types and sources

The source field categorizes where an event came from. Recognized values:

SourceMeaning
weblogNextflow -with-weblog payload
traceParsed .nextflow/trace.txt row
queueSLURM queue poller (e.g., a step transitioned PD → R)
processInternal SeqDesk step lifecycle event

Common eventType values include run_started, run_completed, process_submitted, process_started, process_completed, process_failed. Anything ingested without a recognized type is still stored verbatim — the server does not gate-keep on the value, so custom adapters can add their own.

Multipart upload flow

The order page uses a chunked upload protocol when reads or other artifacts are attached to a sample. These endpoints are FACILITY_ADMIN-only. Build automation that mimics the same flow when bulk-loading data.

POST /api/orders/[id]/sequencing/uploads

Initiate an upload session. targetKind is read or artifact; for read uploads targetRole must be R1 or R2, and the filename must use an allowed sequencing-file extension.

{ "targetKind": "read", "targetRole": "R1", "originalName": "S1_R1.fastq.gz", "expectedSize": 1843921023, "checksumProvided": "6f1b...", "mimeType": "application/gzip", "sampleId": "smpl_...", "metadata": { "dataClass": "raw" } }

targetKind, targetRole, originalName, and expectedSize are required (400 otherwise). Response:

{ "success": true, "uploadId": "upl_...", "tempPath": "orders/.../.tmp/upl_.../S1_R1.fastq.gz", "status": "PENDING", "receivedSize": 0 }

Stream chunks to tempPath (relative to the configured data base path). When the file is fully written, call complete.

POST /api/orders/[id]/sequencing/uploads/[uploadId]/complete

Takes no body. Returns { "success": true, ... } with the finalized upload fields. If checksumProvided was supplied at initiate, the complete call verifies the computed checksum against it before promoting the file out of .tmp.

File operations

These endpoints back the in-app file browser and assembly downloader. They respect demo-session restrictions (Demo mode) and the allowUserAssemblyDownload setting.

GET /api/files/download?path=<rel>

Streams a file. Path is resolved relative to the configured data base path and validated against directory traversal. Demo sessions get 403.

GET /api/files/preview?path=<rel>

Serves an HTML report (e.g., FastQC, MultiQC) inline with strict CSP headers. Useful for embedding QC reports in the SeqDesk UI without downloading.

POST /api/files/checksum

FACILITY_ADMIN-only. Computes MD5 for a list of paths (max 50) and updates the Read record (if any) for each. Checksums are returned as raw lowercase hex (no md5: prefix). Useful as a one-shot integrity audit.

// Request { "filePaths": ["orders/abc/S1_R1.fastq.gz", "orders/abc/S1_R2.fastq.gz"] } // Response { "success": true, "results": [ { "filePath": "orders/abc/S1_R1.fastq.gz", "checksum": "6f1b...", "updatedReadRecord": true } ], "summary": { "total": 2, "successful": 2, "failed": 0, "updatedReadRecords": 2, "notLinkedToRead": 0 } }

POST /api/files/delete

Bulk-delete a list of paths. Removes the file from disk and clears any referencing Read records. Idempotent on already-deleted entries.

Sequencing run import

POST /api/orders/[id]/sequencing/runs/import

FACILITY_ADMIN-only. Accepts a multipart form with an Excel attachment (file) describing a run plan — one row per (runId, sampleCode, barcode). Used by the “Import run plan” button on the sequencing tab of the order detail page. (CSV is not accepted; the body is parsed with ExcelJS.)

This is a two-phase flow. Without ?apply=true the endpoint returns a preview only — it never mutates state:

{ "sheet": "Run Samples", "rows": [ { "rowNumber": 2, "runId": "RUN-2026-04-30-001", "sampleCode": "S1", "barcode": "BC01", "customFields": {}, "unmapped": {} } ], "rowCount": 1, "unmappedColumns": ["Notes"], "missingSamples": ["S99"], "duplicateBarcodes": [ { "runId": "RUN-2026-04-30-001", "barcode": "BC01", "count": 2 } ], "rowErrors": [ { "rowNumber": 7, "message": "Sample not found on this order: S99" } ], "applyReady": false }

applyReady is true only when there is at least one row and rowErrors is empty. With ?apply=true and a clean preview, the endpoint upserts SequencingRun and SequencingRunSample rows and returns the same preview fields plus:

{ "success": true, "createdOrUpdated": [ { "runId": "RUN-2026-04-30-001", "assignments": 2 } ] }

If apply=true is sent while rowErrors is non-empty, the endpoint returns 400 with the preview echoed alongside the error.

Pipeline run control

These endpoints operate on a single PipelineRun ([id]). Except where noted they are FACILITY_ADMIN-only and disabled in the public demo.

POST /api/pipelines/runs/[id]/start

Stages and launches a run. Accepts an optional JSON body of start options (empty body allowed). Returns the launcher result body with its own status code (e.g. 200/202 on success, error status otherwise).

POST /api/pipelines/runs/[id]/sync

Reconciles a run’s status against its execution backend (SLURM/local queue and on-disk outputs). Authenticated by session: a FACILITY_ADMIN or a researcher who owns the run’s target may call it. Returns the sync result body.

PUT /api/pipelines/runs/[id]/selection

Marks a completed run as the final selected result for its study/order + pipeline target (upserts a PipelineResultSelection). Returns { "success": true, "selection": { ... } }. Returns 400 if the run is not completed or has no study/order target.

DELETE /api/pipelines/runs/[id]/selection

Clears the selection for that run’s target. Returns { "success": true, "cleared": <bool> }.

POST /api/pipelines/runs/[id]/resolve-outputs

Re-discovers outputs for a completed or failed run and writes the resulting Assembly/Bin/PipelineArtifact records. Requires runFolder to be set and the target to have samples.

{ "success": true, "discovered": { "...": "adapter summary" }, "resolved": { "assembliesCreated": 1, "binsCreated": 12, "artifactsCreated": 4 }, "errors": [], "warnings": [] }

GET /api/pipelines/runs/[id]/cleaned-reads

Lists the cleaned-read candidates produced by a read-cleaning run, for the admin review/promotion flow. Returns a candidate summary.

POST /api/pipelines/runs/[id]/cleaned-reads

Promotes selected cleaned-read candidates into canonical Read records. Optional body { "sampleIds": ["..."] } limits promotion to specific samples; omit it to promote all. Returns { "success": true, ... }.

GET /api/pipelines/runs/[id]/pending-writebacks

Lists the pending result writebacks for an order-targeted run — the read candidates and report files an admin can promote. Returns:

{ "run": { "id": "...", "runNumber": "...", "pipelineId": "...", "status": "...", "orderId": "..." }, "readCandidates": [ { "artifactId": "...", "outputId": "...", "sampleId": "...", "sampleCode": "S1", "file1": "...", "file2": null, "targetDataClass": "cleaned", "status": "candidate", "currentRead": { "id": "...", "dataClass": "raw", "isProtectedRaw": true } } ], "reports": [ { "id": "...", "name": "multiqc_report.html", "path": "...", "outputId": "..." } ], "review": { "...": "UI copy" } }

POST /api/pipelines/runs/[id]/pending-writebacks

Promotes the pending writebacks (the candidate reads/reports above) into canonical records. Optional body { "sampleIds": ["..."] } scopes the promotion; omit to promote all. Returns the promotion result.

Live stream (MinKNOW ingest)

These endpoints back the live ONT stream-ingest subsystem. They are FACILITY_ADMIN-only (the read endpoints accept a facility-admin read session). See the stream data models.

GET /api/orders/[id]/stream

Lists the order’s stream runs (most recent first, up to 50) with their latest event. totalBases is serialized as a string (BigInt).

POST /api/orders/[id]/stream

Starts a stream run watching outputDir (required; validated to live under the configured MinKNOW output root). Optional deviceId, flowCellId, minknowRunId, and a barcodeMap object. Only one ACTIVE run may watch a given directory — a conflicting start returns 409; an invalid outputDir returns 400.

GET /api/orders/[id]/stream/[streamRunId]/events

Cursor-paginated event feed. Without a cursor it returns the newest events (live-tail); with ?after=<seq> it pages forward oldest-first. ?limit=<n> is clamped to [1, 500] (default 100). Response:

{ "events": [ { "id": "...", "seq": 42, "ts": "2026-05-01T10:00:00.000Z", "kind": "FILE_INGESTED", "payload": { "...": "..." } } ], "cursor": 42 }

Advance your client cursor to the returned cursor to resume without dropping events.

POST /api/orders/[id]/stream/[streamRunId]/stop

Stops a stream run. Returns { "ok": true }, or { "ok": true, "alreadyStopped": true } / { "ok": true, "alreadyStopping": true } if it was already in a terminal/stopping state.

GET /api/orders/[id]/stream/[streamRunId]/by-barcode

Aggregates the run’s FILE_INGESTED events by barcode. Response:

{ "barcodes": [ { "barcode": "barcode01", "fileCount": 12, "totalSize": 1048576, "totalReads": 4000, "totalBases": 1200000, "lastFileAt": "2026-05-01T10:05:00.000Z", "lastFilePath": "..." } ] }

Conventions

  • All POST endpoints accept application/json unless they explicitly take a multipart body (the run import and uploads are the main exceptions).
  • Errors return { "error": "<message>" } with an appropriate 4xx/5xx status.
  • Sequencing data management (uploads, run-plan import, checksums) and pipeline control (start, selection, resolve-outputs, cleaned-reads, pending-writebacks) require FACILITY_ADMIN. Read-only run endpoints (e.g. run sync) also admit a researcher who owns the run’s target. The weblog uses a shared secret rather than a session.
  • Pagination uses ?cursor=<id>&limit=<n> (the stream events feed uses ?after=<seq>&limit=<n>) where supported.