xPlantAPI
API referenceSOPs and runs

Record a step measurement

Records a numeric reading against one step of a run — the pH of a medium, the mass of an ingredient, a temperature — with its unit, as the bench station running the SOP reads it from a balance, pH meter or probe.

POST/api/v1/sop-runs/{id}/steps/{stepId}/measurements
Scope write:sop_stepsHonours Idempotency-Key

The reading joins the same trail as the step events, with eventType measured, so a run reads in one order. The unit is required: a number without one is not a record anyone can rely on later. Send an Idempotency-Key so a retried post does not record the reading twice.

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.

Path parameters

NameTypeRequiredDescription
idstring (uuid)YesThe run's id.
stepIdstringYesThe step's id in the version the run follows, as Get an SOP lists it in version.steps. It is recorded as sent and not checked against the procedure.

Headers

NameTypeRequiredDescription
Idempotency-KeystringNoAny 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

FieldTypeRequiredDescription
metricstringYesWhat was measured, in your own words — temperature, ph, mass. 1–60 characters.
valuenumberYesThe reading.
unitstringYesThe unit the reading is in, such as C, pH or g. Required. 1–20 characters.
recorded_atstring (date-time)NoWhen it happened, in UTC with a trailing Z, such as 2026-09-25T08:30:00Z. A timestamp with an offset is refused. Defaults to when xPlant receives it.
notesstringNoAnything the reading needs beside it. Up to 500 characters.

Example

curl -X POST https://app.xplantpro.com/api/v1/sop-runs/2a4c6e8b-1d3f-4b5a-a7c9-e1f3a5b7c9d1/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",
    "recorded_at": "2026-09-25T08:21:40Z",
    "notes": "Initiation medium before pouring."
  }'

Response

201 with { "ok": true, "data": … }. data holds the result.

FieldTypeRequiredDescription
idstring (uuid)Yes—
runIdstring (uuid)YesThe run the evidence belongs to.
stepKeystringYesThe step it was recorded against — the stepId it was posted to.
eventTypestringYesconfirmed, scanned, skipped, note or device_state for a step event; measured for a measurement.
recordedAtstringYesWhen it happened: the recorded_at that was sent, or when xPlant received it.
payloadobjectYesThe detail sent with the event. For a measurement: metric, value, unit, and notes when there were any.
Response
{
  "ok": true,
  "data": {
    "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."
    }
  }
}
Response headerMeaning
Idempotent-Replaytrue when this response is a replay of an earlier request with the same Idempotency-Key.
X-Request-IdIdentifies this request. Include it when you contact support.

Errors

StatusCodeWhen
400VALIDATION_ERRORThe request body is not valid JSON.
401UNAUTHORIZEDThe key is missing, malformed or revoked, or its owner is no longer a member of the workspace.
402PAID_PLAN_REQUIREDThe 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.
403FORBIDDENThe 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.
403DEVICE_TOKEN_NOT_ACCEPTEDA device token was sent; this operation needs a workspace API key.
404NOT_FOUNDNo run with this id exists in the key's workspace, or the run id is not a well-formed id.
409IDEMPOTENCY_IN_FLIGHTA request with this Idempotency-Key is still being processed; retry after Retry-After seconds.
409SOP_RUN_CLOSEDThe run is complete. A completed run's record is final and takes no more evidence.
422VALIDATION_ERRORThe Idempotency-Key header is malformed.
422VALIDATION_ERRORA field failed validation — a missing unit, a value that is not a number, or a recorded_at that is not a UTC timestamp. error gives the first problem but does not name the field.
429RATE_LIMIT_EXCEEDEDToo many requests for this key, device token or workspace. Wait Retry-After seconds.
500SOP_STEP_EVENT_CREATE_FAILEDThe evidence could not be saved. Retry with the same Idempotency-Key.

Branch on code, never on the error text. See Errors.

On this page