Start an SOP run
Starts a run of an SOP: the record that a procedure was carried out, step by step, against the version the lab had in force.
https://app.xplantpro.com/ api/ v1/ sop-runswrite:sop_runsHonours Idempotency-KeyA bench station typically:
- Reads the SOP with Get an SOP and shows the steps of the version in force.
- Starts a run here, naming the batch or line it is for in
batch_code. - Posts evidence against each step as the work happens — a confirmation, a scanned vessel label, a reading from a balance or pH meter — with Record a step event and Record a step measurement.
The run follows the version in force when it starts, and you cannot choose another. Send an Idempotency-Key so a retried start does not open a second run.
See also: Run an SOP from a bench station.
Send an Idempotency-Key header to make retries safe: a repeat with the same key within 24 hours returns the first response instead of writing twice. See Idempotency.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | No | Any unique string you choose per logical write. A retry carrying the same key within 24 hours returns the first result instead of writing again. Scoped to your API key and this operation. 8–255 characters. Must match ^[A-Za-z0-9._:~-]+$. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
sop_id | string (uuid) | Yes | The SOP to run. It must have a version in force. |
batch_code | string | No | Your lab's own identifier for what is being run, such as a batch or line code. Up to 120 characters. |
plant_id | string (uuid) | No | The plant the run is for, when there is one. It must be in this workspace. |
Example
curl -X POST https://app.xplantpro.com/api/v1/sop-runs \
-H "Authorization: Bearer $XPLANT_API_KEY" \
-H "Idempotency-Key: station-3-wk38-start" \
-H "Content-Type: application/json" \
-d '{
"sop_id": "2e4f6a8c-0b1d-4e3f-9a5b-7c9d1e3f5a7b",
"batch_code": "LINE-0412"
}'Response
201 with { "ok": true, "data": … }. data holds the result.
| Field | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | Yes | — |
sopId | string | null (uuid) | Yes | The SOP being run. |
version | integer | null | Yes | The version of the SOP this run follows — the one in force when it started. It never changes afterwards. |
versionId | string | null (uuid) | Yes | That version's id. |
status | string | Yes | in_progress from the moment a run starts. A run is completed in xPlant, once every step is ticked off; runs can also be pending, on_hold, failed, cancelled or archived. |
batchCode | string | null | Yes | Your lab's own identifier for what is being run. |
startedAt | string | null | Yes | — |
completedAt | string | null | Yes | — |
progress | number | Yes | How far through its steps the run is, from 0 to 100, as ticked off in xPlant. |
steps | any[] | Yes | The step checklist as ticked off in xPlant, one entry per step, such as { "id": "step-3", "completed": true }. Empty until someone works the run in xPlant. Evidence posted through the API is in events and does not tick steps off here. |
{
"ok": true,
"data": {
"id": "9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
"sopId": "2e4f6a8c-0b1d-4e3f-9a5b-7c9d1e3f5a7b",
"version": 2,
"versionId": "5c6d7e8f-9a0b-4c1d-8e2f-3a4b5c6d7e8f",
"status": "in_progress",
"batchCode": "LINE-0412",
"startedAt": "2026-09-25T08:02:13.000Z",
"completedAt": null,
"progress": 0,
"steps": []
}
}| Response header | Meaning |
|---|---|
Idempotent-Replay | true when this response is a replay of an earlier request with the same Idempotency-Key. |
X-Request-Id | Identifies this request. Include it when you contact support. |
Errors
| Status | Code | When |
|---|---|---|
400 | VALIDATION_ERROR | The request body is not valid JSON. |
401 | UNAUTHORIZED | The key is missing, malformed or revoked, or its owner is no longer a member of the workspace. |
402 | PAID_PLAN_REQUIRED | The workspace's plan does not include the API. The full API is included with xPlant+ Teams and Enterprise; on Hobby and Pro Lab, keys can connect devices only. |
403 | FORBIDDEN | The key lacks a scope this operation requires, or its owner's current role in the workspace cannot use it — a key never does more than its owner can in xPlant. error names the scope, and for a role, the role it needs. |
403 | DEVICE_TOKEN_NOT_ACCEPTED | A device token was sent; this operation needs a workspace API key. |
404 | NOT_FOUND | The SOP, or the plant named in plant_id, is not in this workspace. |
409 | IDEMPOTENCY_IN_FLIGHT | A request with this Idempotency-Key is still being processed; retry after Retry-After seconds. |
409 | SOP_RUN_NOT_EFFECTIVE | The SOP has no version in force, so there is nothing approved to run. Put a version into force in xPlant, then start the run. |
422 | VALIDATION_ERROR | The Idempotency-Key header is malformed. |
422 | VALIDATION_ERROR | A field failed validation, for example sop_id is missing or is not an id. error gives the first problem but does not name the field. |
429 | RATE_LIMIT_EXCEEDED | Too many requests for this key, device token or workspace. Wait Retry-After seconds. |
500 | SOP_RUN_CREATE_FAILED | The run could not be started. Retry with the same Idempotency-Key. |
Branch on code, never on the error text. See Errors.
Update a media recipe
Changes only the fields you send. Only the recipe's creator can change it.
Get an SOP run
One run: the SOP and version it follows, where it stands, and every piece of evidence posted against its steps, oldest first — the trail to read forwards when you need to know what was done, in what order.