Upsert Lab Visit Test Results (v1)
Method & Path
PUT /api/v1/workspace/:workspaceId/labs/visits/:labVisitId/test-results
Actual backend path: /v1/workspace/:workspaceId/labs/visits/:labVisitId/test-results
Description
Upsert (create/replace) entered test results for a lab visit. The backend validates that:
testIdexists in the visit’s selected testsnodeResultskeys are valid composite keys in the formatSectionName::nodeIdfrom the test’sdesignTest.sections[].nodes[].id
nodeResults values support visit-only overrides (do not modify the general test design):
- Legacy/simple value:
"Section::12": "35" - Structured value with overrides:
unitOverride: override the unit for this visit onlyrangeOverride: override the displayed "normal range" for this visit only (and for numeric nodes, used for indicator high/low)
If every test in the visit has at least one entered node result, the visit status is automatically set to results-entered.
Authentication
Required: JWT token in Authorization header
Persona Access:
- Admin: Not applicable (workspace-scoped endpoint)
- Workspace Owner: Allowed (root persona for workspace features)
- Staff: Allowed (role-based)
- Customer: Not allowed
Required Permissions:
labs.run
Headers
| Header | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer token: Bearer <token> |
Content-Type | string | Yes | application/json |
X-Staff-Id | string | No | Staff member ID (used for staff permission checks; omit for Workspace Owner access) |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
staffId | string | No | Alternative to X-Staff-Id header |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
workspaceId | string | Yes | Workspace identifier (MongoDB ObjectId) |
labVisitId | string | Yes | Lab visit identifier (MongoDB ObjectId) |
Request Body
{
"testResults": [
{
"testId": 286406,
"nodeResults": {
"Section-1::1": "Negative",
"Section-1::2": {
"value": "35",
"unitOverride": "g/dl",
"rangeOverride": { "kind": "num", "from": 13.5, "to": 18 }
}
}
}
]
}
Response 200 OK
{
"labVisit": {
"id": "507f1f77bcf86cd799439011",
"workspaceId": "507f1f77bcf86cd799439012",
"clientId": "507f1f77bcf86cd799439013",
"labVisitType": "in-lab",
"labVisitStatus": "results-entered",
"labTestIds": [286406],
"labTestSnapshots": [
{
"test": { "testId": 286406, "testTitle": "CBC" },
"designTest": { "id": "507f1f77bcf86cd799439099", "testId": 286406, "sections": [] }
}
],
"labTestResults": [
{
"testId": 286406,
"nodeResults": {
"Section-1::1": "Negative",
"Section-1::2": {
"value": "35",
"unitOverride": "g/dl",
"rangeOverride": { "kind": "num", "from": 13.5, "to": 18 }
}
},
"updatedAt": "2026-01-11T10:00:00.000Z",
"updatedBy": {
"type": "workspace",
"id": "507f1f77bcf86cd799439012",
"name": "Workspace Owner",
"email": "owner@example.com"
}
}
],
"labVisitDate": "2026-01-10T12:00:00.000Z",
"labVisitNotes": null,
"labVisitPricing": {
"labVisitSubtotal": 30,
"labCouponId": null,
"labCouponCode": null,
"labVisitDiscountAmount": 0,
"labVisitTotal": 30
},
"deletedAt": null,
"createdAt": "2026-01-10T12:00:00.000Z",
"updatedAt": "2026-01-11T10:00:00.000Z"
}
}
Common Errors
400 Bad Request: Missing testResults
401 Unauthorized: Missing or invalid authentication token
403 Forbidden: Insufficient permissions (labs.run required for staff)
404 Not Found: Workspace or lab visit not found
422 Validation Error:
- Test not part of this visit
- Invalid node IDs in
nodeResults - Attempt to update results for invoiced/cancelled visit