Run an SOP from a bench station
Start a run of the SOP in force, confirm steps with scans, and record measurements with their units.
Scopes: read:sops, write:sop_runs, write:sop_steps, and read:sop_runs to read a run back. Endpoints: Get an SOP, Start an SOP run, Record step evidence, Record a step measurement, Get an SOP run.
A bench station (a tablet, a Pi with a touchscreen, a scanner) can walk a technician through an SOP and record what actually happened: who confirmed each step, what was scanned, which pH was measured.
1. Load the SOP
curl "https://app.xplantpro.com/api/v1/sops/$SOP_ID" \
-H "Authorization: Bearer $XPLANT_API_KEY"You always get the version the lab works from right now. You never get a draft, or a version that has been approved but hasn't taken effect yet. If no version is in force, version is null and there are no steps: show that to the technician rather than presenting an empty procedure.
currentVersion on the SOP is the highest version number that exists; version.version is the one in force. They often differ.
2. Start a run
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": "9d2c4b6a-8e1f-4a3b-b5c7-d9e1f3a5b7c9", "batch_code": "WK-38"}'There is deliberately no version argument. A run always follows the version in force, because a run is a record of what someone did, and what they did was follow the lab's current procedure. An SOP with no version in force answers 409 SOP_RUN_NOT_EFFECTIVE (not 404: the SOP exists, it just can't be run yet).
3. Record evidence against steps
A scanner confirms a step:
curl -X POST "https://app.xplantpro.com/api/v1/sop-runs/$RUN_ID/steps/step-3/events" \
-H "Authorization: Bearer $XPLANT_API_KEY" \
-H "Idempotency-Key: station-3-wk38-step3-scan" \
-H "Content-Type: application/json" \
-d '{"event_type": "scanned", "payload": {"code": "LINE-0412"}}'Step events cover confirmations, scans, skips, notes and device states.
A meter posts a reading against the same step. The unit is required and has no default: a number without a unit isn't a measurement.
curl -X POST "https://app.xplantpro.com/api/v1/sop-runs/$RUN_ID/steps/step-3/measurements" \
-H "Authorization: Bearer $XPLANT_API_KEY" \
-H "Idempotency-Key: station-3-wk38-step3-ph" \
-H "Content-Type: application/json" \
-d '{"metric": "ph", "value": 5.7, "unit": "pH"}'Measurements appear on the run's timeline as measured events, alongside the confirmations, so Get an SOP run reads as one story from start to finish.
Runs are append-only
Nothing on a run can be edited or deleted. To correct a mistake, record another event that says so. Once a run is completed, further writes answer 409 SOP_RUN_CLOSED: its record is what happened.
Use an Idempotency-Key on every write from a station. Bench networks are flaky, and a retried scan must not count twice.
Bench stations and keys
Device tokens only cover sensor readings, device events and heartbeats, so a station that runs SOPs needs a workspace key. Keep the damage from a lost or copied station small:
- Give each station its own key, named after the station, holding only what it uses. For SOP runs that's
read:sops,write:sop_runsandwrite:sop_steps; addread:labelsandwrite:label_scansif it scans, andwrite:transfersif it records transfers. - Keep the key in the station's configuration or secrets store, never in code or a shared repository.
- If a station goes missing, revoke its key in Settings → Integrations → API Keys. Nothing else stops working.