API referenceSOPs and runs
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.
GET
https://app.xplantpro.com/ api/ v1/ sop-runs/ {id}Scope
read:sop_runsPath parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | Yes | The run's id. |
Example
curl https://app.xplantpro.com/api/v1/sop-runs/2a4c6e8b-1d3f-4b5a-a7c9-e1f3a5b7c9d1 \
-H "Authorization: Bearer $XPLANT_API_KEY"Response
200 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. |
events | object[] | Yes | Every piece of evidence posted against the run's steps, oldest first. |
events[].id | string (uuid) | Yes | — |
events[].runId | string (uuid) | Yes | The run the evidence belongs to. |
events[].stepKey | string | Yes | The step it was recorded against — the stepId it was posted to. |
events[].eventType | string | Yes | confirmed, scanned, skipped, note or device_state for a step event; measured for a measurement. |
events[].recordedAt | string | Yes | When it happened: the recorded_at that was sent, or when xPlant received it. |
events[].payload | object | Yes | The detail sent with the event. For a measurement: metric, value, unit, and notes when there were any. |
{
"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": [],
"events": [
{
"id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
"runId": "9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
"stepKey": "step-2",
"eventType": "measured",
"recordedAt": "2026-09-25T08:21:40+00:00",
"payload": {
"metric": "ph",
"value": 5.7,
"unit": "pH",
"notes": "Initiation medium before pouring."
}
},
{
"id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
"runId": "9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
"stepKey": "step-3",
"eventType": "scanned",
"recordedAt": "2026-09-25T08:30:00+00:00",
"payload": {
"code": "LINE-0412-J07"
}
}
]
}
}| Response header | Meaning |
|---|---|
X-Request-Id | Identifies this request. Include it when you contact support. |
Errors
| Status | Code | When |
|---|---|---|
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 | No run with this id exists in the key's workspace, or the run id is not a well-formed id. |
429 | RATE_LIMIT_EXCEEDED | Too many requests for this key, device token or workspace. Wait Retry-After seconds. |
500 | SOP_RUN_QUERY_FAILED | The run could not be read. Retry later. |
Branch on code, never on the error text. See Errors.
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.
Record step evidence
Records what happened at one step of a run: someone confirmed it, scanned a label or vessel, skipped it, or left a note, or an instrument reported its state.