xPlantAPI

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_runs and write:sop_steps; add read:labels and write:label_scans if it scans, and write:transfers if 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.
Edit on GitHub

On this page