Plan a Run via the API
This guide shows you how to use the Run Planning API programmatically — to plan sequencing runs, manage their content, and generate sample sheets without going through the BaseSpace Sequence Hub UI.
Status of this guide: This is the first published cut. It covers the most common starting workflow — get a token, discover catalog IDs, create a planned run, revise it, and generate the sample sheet. We will expand it over time to cover additional endpoints (sample-sheet validation, library / library pool management, analysis configuration templates, run lifecycle, etc.). For the complete endpoint list, see the API Reference link below.
In this guide
Authenticating —
POST /v1/users/tokenProvider:createTokenDiscovering catalog IDs — analysis and its versions, genomes
Combined example: Plan a sequencing run end to end
Create a planned run —
POST /v1/sequencing/runs:planReplace a planned run —
PUT /v1/sequencing/runs/{runId}/planGenerate the sample sheet —
POST /v1/sequencing/runs/{runId}:generateSampleSheet
Prerequisites
An Illumina Platform API Key. See Generate an API Key for instructions on creating one. You can use the same API key you use for ICA / the CLI.
Your workgroup ID, if you want the token to be scoped to a specific workgroup (recommended for shared resources). See Workgroup ID below.
The base hostname for the regional Illumina Platform gateway your enterprise lives on. The platform is deployed regionally — see BaseSpace Sequence Hub Global Regions for the list of available regions. The hostname you need is not the same as the BaseSpace URLs shown on that page; contact your Illumina representative or support team to obtain it for your enterprise.
About the example code
The examples below use Python with the requests library, but you can use any HTTP client (curl, Postman, etc.). Install Python from https://www.python.org/ and install requests with pip install requests. The inline examples omit timeout= for readability; production scripts should set an explicit timeout on each call to avoid hanging on network issues.
Authenticating
Every call must carry an Illumina Platform JWT in the Authorization header:
To obtain this JWT, call the User Token Provider endpoint. It accepts your Illumina Platform API Key and returns a JWT that the Run Planning API will accept.
Note: This token-exchange flow is specific to the Run Planning API. Other Illumina services (e.g. ICA) have their own authentication flows — see their respective documentation.
Get a token
POST <platform-base>/v1/users/tokenProvider:createToken
X-API-Key
Your raw Illumina Platform API Key. Do not Base64-encode it — the server handles that internally.
Content-Type
application/json
The body is optional. An empty {} works for most cases. The most useful query parameter is cwid — see Workgroup ID below.
A successful response is HTTP 201 Created with:
Pass access_token to every API call as Authorization: Bearer <access_token>.
Scopes
The token will carry the scopes your user is permitted to receive — typically gss.config.* (read-only resource catalog) and gss.sequencing.* (planned runs, samples, libraries, etc.). The example workflow below requires:
gss.sequencing.create— to create the planned rungss.sequencing.update— to replace itgss.sequencing.read— to generate the sample sheet
Scope matching is case-insensitive, so the casing of the strings in the JWT does not need to match exactly.
Token lifetime
Tokens are long-lived (currently 7 days; subject to change without notice). Cache the token across calls and only call :createToken again when the token is close to expiry or after a 401 response.
Workgroup ID
Most resources in the Illumina platform — projects, sequencing runs, samples, libraries — belong to a workgroup. A user can belong to multiple workgroups; the workgroup the token is issued for determines which resources the token can see and act on.
Where to find it: In the Illumina Platform UI, switch to the workgroup you want to use, then look in the URL or your user profile menu for the workgroup ID (a GUID).
If you omit it: The token is issued in your personal context. Resources you create are owned by you (only you can read them) but workgroup-shared resources (which is most production data) will not be visible.
Recommendation: Set
cwidto the workgroup that owns the planned runs you intend to manage.
API Reference
The complete, always-up-to-date list of endpoints is available as an interactive Swagger UI hosted alongside the API. The exact URL depends on your region, and follows this pattern:
The raw OpenAPI specification is at <platform-base>/gss/swagger/v1/swagger.json. Use Swagger to look up request and response schemas, error codes, and endpoints not yet covered in this guide. Your Illumina representative can provide the exact <platform-base> for your region.
Swagger's Authorize button accepts the JWT obtained in the previous section.
Discovering catalog IDs
The create / replace examples below reference an analysis version definition (AVD) ID and, for genome-aware analyses, a genome ID. You discover them with GET calls before your first :plan.
GSS distinguishes between an analysis definition (AD) — an analysis family such as "BCL Convert" or "DRAGEN Germline" — and an analysis version definition (AVD) — a specific version of that analysis. The :plan payload references AVD IDs, not AD IDs.
Analysis definitions (pipelines)
Required scope for all calls in this subsection: gss.config.read.
List analysis definitions
GET <platform-base>/v1/sequencing/analysisdefinitions
Returns a paginated list of analysis pipelines accessible to the request token. Useful for finding the AD ID of an analysis(e.g. DRAGEN Germline) before drilling into its versions.
Get a single analysis definition
GET <platform-base>/v1/sequencing/analysisdefinitions/{analysisDefinitionId}?Include=AnalysisVersions
Returns details for a single AD and its associated versions
Analysis version definitions
Required scope for all calls in this subsection: gss.config.read.
Get a single AVD by ID
GET <platform-base>/v1/sequencing/analysisdefinitions/versions/{analysisVersionDefinitionId}
Returns the full definition of a single AVD and the following table shows optional Include query flags:
CompatibleLibraryPrepKits
Inline the LPKs that are compatible (and any that are explicitly excluded)
CompatibleGenomes
Inline the supported and excluded genomes
JavascriptFunctions
Inline the associated JavaScript functions (onSubmit, onRender, etc.)
CompatibleBclConvertVersions
Inline the BCL Convert versions compatible with this AVD. Requires InstrumentPlatform or InstrumentType as an additional query parameter; the API returns 400 Bad Request if it is missing
Settings in the response
Each AVD response contains three top-level setting fields. The tables below provide further details of these settings and their respective child fields.
analysisSettings.fields[]
Analysis-level settings (apply to all samples)
analysisSampleSettings.fields[]
Per-sample settings
runContentSettings.fields[]
Per-library / lane settings consumed by the analysis
Each entry inside fields[] has the following properties (the most relevant ones for an integrator):
id
The setting key. This is what you use as the JSON key when sending settings back to :plan / PUT .../plan.
type
One of textbox, checkbox, radio, select, genome, number, integer, custom, file, fileSelect, section, text, date, referenceFile, sample, fieldgroup
label
Human-readable display name (used by the UI; not a valid settings key)
value
The default value, if any
required
Whether the setting is mandatory
For BCL Convert, sending an empty settings: {} is supported and produces a working sample sheet for the typical default configuration.
Genomes
Required scope: gss.config.read.
For analyses that use reference genomes (e.g. DRAGEN Germline), the ReferenceGenomeDir setting takes a Genome ID (e.g. gen.85b1459dde1c41cca064110602xxxxx) that you can extract from the list of genome objects via:
GET <platform-base>/v1/sequencing/genomes
See Swagger for the full schema and filtering options. There is also GET /v1/sequencing/genomes/{genomeId} for a single-genome lookup once you have the ID.
Library prep kits and index adapter kits
Required scope: gss.config.read.
Looking up a Library Prep Kit (LPK) or Index Adapter Kit (IAK) is an advanced step. The first runnable example below omits all kit fields, which is supported and produces a valid sample sheet. Once you have a working basic flow, see Swagger for:
GET /v1/sequencing/libraryPrepKits(camelCase path segment)GET /v1/sequencing/indexadapterkits(all-lowercase path segment)
Note on URL casing. The casing asymmetry between
libraryPrepKitsandindexadapterkitsis intentional and matches the routes registered in the API — it is not a typo. Make sure your client preserves the exact casing.
Combined example — plan a sequencing run end to end
The remainder of this guide walks through a single workflow: create a planned run, revise it, and generate the sample sheet.
1. Create a planned run
POST <platform-base>/v1/sequencing/runs:plan
Required scope: gss.sequencing.create
This endpoint creates a new planned run in the Draft/Planned state, based on the isDraft flag provided in the payload. When a run is in Planned state, an operator will be able to select it from the sequencer to start the sequencing.
The example below uses BCL Convert + DRAGEN Germline with two samples. It uses "Not Specified" Library Prep Kit and "Not Specified" Index Adapter Kit, so you can run it without first looking up kit IDs. The only placeholders you must fill in are the two AVD IDs and the Genome ID — see Discovering catalog IDs.
A successful response is HTTP 201 Created with the full sequencing-run resource. Save its id — you will need it for the next steps.
Important —
isDraftand run visibility on the sequencer. Only runs that are saved asPlanned(isDraft: false) are surfaced on the sequencer for an operator to select and start. ADraftrun (isDraft: true) is persisted on the server but will not appear on the sequencer. For an end-to-end create → sequencer → sequence flow, always sendisDraft: false.
2. Replace a planned run
PUT <platform-base>/v1/sequencing/runs/{runId}/plan
Required scope: gss.sequencing.update
Use this when you need to update an existing planned run. The body has the same shape as create, and PUT semantics apply: the run is fully replaced by what you send. Anything you omit (or send as an empty array) is removed.
The example below mirrors the create example but changes the description and flips Sample_002's VariantCallingMode from SmallVariantCaller to AllVariantCallers.
Notes on PUT semantics:
Full replace.
runConfiguration,runContents, andrunAnalysisConfigurationsare each replaced by the value you send. To remove an analysis configuration, send the list without it; to keep one unchanged, re-send it as-is.isDraft: falsesaves the run asPlannedand runs full validation. Same behavior as POST:plan, and what makes the run visible to the sequencer.You cannot replace a run that has moved past planning (started, locked, or no longer planned).
3. Generate the sample sheet
POST <platform-base>/v1/sequencing/runs/{runId}:generateSampleSheet
Required scope: gss.sequencing.read
Generates a Sample Sheet CSV (and optionally a structured JSON) from the planned run identified by {runId} in the path. The run configuration, run contents, and analysis configurations are taken from the saved run — you do not resend them in the body. This is the same sample sheet the sequencer will execute, so it is the authoritative artifact for downstream tooling.
The body has only two optional fields:
getSampleSheetSnapshotIfExisted
bool
If true and a sample sheet has already been snapshotted for a launched local-analysis run, return that snapshot instead of regenerating
include
array of strings
Extra content to include in the response (see table below)
The include flags let you control what comes back:
IncludeJsonFormat
Adds a sampleSheetConfig field with a structured JSON representation of the CSV. Omitted by default.
IncludeFileReferences
Adds a fileReferences array with resolved paths to genomes, reference files, etc. Omitted by default.
IncludeAnalysisReferenceInfo
Populates the analysisReferenceInfos[].downloadableReferenceFiles / nameBasedGenomeInfos / nameBasedReferenceFileInfos arrays. The analysisReferenceInfos[] outer array is always present (one entry per analysis configuration); these inner arrays are populated only when the run uses non-cloud reference files.
IncludeNotMappedFields
Includes analysis fields that are not formally mapped (rare; for advanced workflows)
Use this endpoint to retrieve the sample sheet for a planned run. However, please note that run execution itself does not require calling this endpoint: once a planned run is created, the sequencer fetches the run, and the operator selects it on the sequencer to start the sequencing.
What you'll see in the generated sample sheet
The generated CSV contains content the API auto-populates — you do not (and cannot) supply it in the request. Knowing this avoids surprise during downstream parsing. Below is the actual CSV produced by running the create / generate example above (BCL Convert + DRAGEN Germline, two samples with different variant-calling modes per sample):
Please refer to this GUIDE, if you wish to learn more about our Sample Sheet structure.
Naming and value constraints
The fields below are validated with regular expressions. Common values like sample IDs containing periods or descriptions containing commas will be rejected with 400 Bad Request — validate your inputs before sending.
runConfiguration.runName
alphanumeric, _, -, ., space; must start with alphanumeric / _ / -; no trailing whitespace
runConfiguration.description
any character except , * " '; also avoid [ ]
laneLibraries[].sampleName
alphanumeric, _, - only
laneLibraries[].index1Sequence / index2Sequence
A, G, C, T only (uppercase)
laneLibraries[].adapterSequence* (lane- and library-level)
A, G, C, T, +
Troubleshooting
Errors are grouped by the endpoint that returned them.
POST /v1/users/tokenProvider:createToken (Get a token)
POST /v1/users/tokenProvider:createToken (Get a token)401 Unauthorized — Either X-API-Key header or Authorization header must be provided
None of X-API-Key, Authorization, or the psToken cookie were sent.
Send X-API-Key: <your-raw-api-key> (do not Base64-encode it), or send Authorization: Bearer <psToken> / Basic <base64(username:password)>.
401 Unauthorized — Invalid authorization header format. Expected 'Bearer <token>' or 'Basic <credentials>'
An Authorization header was sent but not in the expected Bearer … / Basic … form.
Fix the header format. For API-key auth use X-API-Key instead — do not put the API key in Authorization.
409 Conflict — Platform Auth request failed. (response details carries Platform Auth's errorCode / message)
Platform Auth rejected the credentials or could not be reached. Common causes: invalid or expired API key; cwid doesn't belong to a workgroup the user is a member of; the user lacks the permissions required for the scopes IMS requests; Platform Auth is unavailable.
Inspect the details.errorCode / details.message returned in the response. Generate a new API key if it's invalid/expired, confirm the cwid is one your user is a member of, and contact your Illumina representative if the user is missing required permissions.
POST /v1/sequencing/runs:plan (Create a planned run)
POST /v1/sequencing/runs:plan (Create a planned run)400 Bad Request — does not match regular expression …
A field failed regex validation. Most common: sampleName / libraryName with periods or spaces; index1Sequence / index2Sequence outside A/G/C/T; description containing , * " ' [ ].
Sanitize input. See Naming and value constraints.
401 Unauthorized
JWT is missing, expired, or malformed.
Re-fetch a token via :createToken.
403 Forbidden — (message contains a scope name)
Token lacks gss.sequencing.create, or cwid does not match the workgroup that owns the referenced resources.
Confirm the token's scopes; reissue the token under the correct workgroup.
409 Conflict — One or more unknown settings found: <ids>
A label was sent as a settings key, or an id not defined on the AVD was used.
Use the AVD's field ids (e.g. ReferenceGenomeDir, VariantCallingMode), not the labels. See Discovering catalog IDs.
409 Conflict — Failed BCL Convert data validation check: …
The run failed sample-sheet validation. Common reasons: insufficient index distance between samples, illegal characters in free-text fields (e.g. [, ], tabs in runName, description, sampleName), or inconsistent OverrideCycles / kit settings across libraries on the same lane.
Read the message after the colon — it pinpoints the exact issue.
409 Conflict (other)
Strict validation failed — typically index collisions across libraries on the same lane, kit incompatibility, or cycle counts inconsistent with the read type.
Inspect error details for more information.
PUT /v1/sequencing/runs/{runId}/plan (Replace a planned run)
PUT /v1/sequencing/runs/{runId}/plan (Replace a planned run)All errors from create also apply. In addition:
403 Forbidden
Token lacks gss.sequencingruns.update (or the parent gss.sequencing.update).
Reissue with the correct scope and / or workgroup.
404 Not Found / 410 Gone
runId doesn't exist (404) or the run was deleted (410).
Verify the run id; deleted runs surface as 410, not 404.
409 Conflict — run is not editable
Run has progressed past planning. Specific error codes: SequencingRunStarted (sequencing has begun), PlannedRunLocked (claimed by a sequencer), SequencingRunNotPlanned (IsPlanned == false).
Replace is allowed while the run was created via run planning (draft or planned), sequencing hasn't started.
POST /v1/sequencing/runs/{runId}:generateSampleSheet (Generate the sample sheet)
POST /v1/sequencing/runs/{runId}:generateSampleSheet (Generate the sample sheet)401 Unauthorized
JWT is missing, expired, or malformed.
Re-fetch a token via :createToken.
403 Forbidden — Required scope ...
Token lacks gss.sequencing.read, or cwid does not match the workgroup that owns the run.
Reissue the token with the correct scope and / or workgroup.
404 Not Found
The {runId} does not exist or is not visible in the current workgroup.
Verify the run ID and that the token's cwid matches the workgroup that owns the run.
409 Conflict — <resource> resource '<urn>' is either not found or inaccessible. / Failed to retrieve reference file(s)
A genome, reference file, or other resource the run depends on is no longer accessible to the caller (deleted, moved, or outside the workgroup the token is scoped to).
Confirm the resource ids in the run are still valid and that the workgroup the token represents has access. If a resource was removed, point the run at a replacement via PUT :plan before generating the sample sheet.
Need an endpoint that's not covered yet? Use the API Reference and let us know which workflows you need documented next.
Last updated
Was this helpful?
