Skip to main content

Work Order QMS Module — API Endpoint Specification

Classification: Internal — Engineering
Date: 2026-02-13
Artifact: 71 of WO System Series
Status: Proposed
Source Artifacts: 13-tdd.md §1.1, 16-prisma-data-model.md, 22-rbac-permissions-matrix.md, 67-integration-api-strategy.md


1. API Conventions

1.1 Base URL & Versioning

Production:  https://api.coditect.io/v1
Staging: https://api-staging.coditect.io/v1
Development: http://localhost:3000/v1

Versioning: URL path (/v1/, /v2/)
Current: v1 (GA)
Sunset: None (first version)

1.2 Authentication

All endpoints require authentication via one of:

MethodHeaderUse CaseToken Lifetime
Bearer JWTAuthorization: Bearer <token>Human users (browser/mobile)1 hour (refresh: 7 days)
Service API KeyX-API-Key: <key>Service-to-service integrations90-day rotation
Agent TokenAuthorization: Bearer <agent-token>CODITECT agent executionPer-execution (ephemeral)

All tokens carry tenant_id claim. PostgreSQL RLS enforces tenant isolation regardless of application logic.

1.3 Standard Headers

HeaderDirectionRequiredDescription
AuthorizationRequestYesBearer token or API key
Content-TypeRequestYes (POST/PUT/PATCH)application/json
X-Request-IDRequestRecommendedIdempotency key (UUID v7) — prevents duplicate operations
X-Tenant-IDRequestNo (derived from token)Override for super-admin operations only
X-Correlation-IDResponseAlwaysTrace ID for observability — include in support tickets
X-RateLimit-RemainingResponseAlwaysRemaining requests in current window
X-RateLimit-ResetResponseAlwaysUnix timestamp when window resets
SunsetResponseConditionalISO 8601 date when endpoint will be removed

1.4 Pagination

All list endpoints use cursor-based pagination:

{
"data": [...],
"pagination": {
"cursor": "eyJpZCI6ImNsdTEyMzQ1Njc4OTAifQ==",
"has_more": true,
"total_count": 1247
}
}
ParameterTypeDefaultMaxDescription
limitinteger25100Items per page
cursorstringnullOpaque cursor from previous response
sortstringcreated_at:descField and direction (field:asc or field:desc)

1.5 Error Response Format

All errors follow RFC 7807 (Problem Details):

{
"type": "https://docs.coditect.io/errors/validation-failed",
"title": "Validation Failed",
"status": 422,
"detail": "Work order cannot transition from DRAFT to IN_PROGRESS without approval.",
"instance": "/v1/work-orders/clu12345/status",
"correlation_id": "01HRX7QBPK4N8JMZV3Y5K2DWTF",
"errors": [
{
"field": "status",
"code": "INVALID_TRANSITION",
"message": "Transition DRAFT→IN_PROGRESS is not permitted; required: DRAFT→PENDING_APPROVAL"
}
],
"timestamp": "2026-02-13T14:30:00.000Z"
}

1.6 Error Code Catalog

HTTP StatusError TypeCodeDescriptionRetry
400Bad RequestINVALID_INPUTMalformed JSON or missing required fieldNo
400Bad RequestINVALID_TRANSITIONState machine transition not permittedNo
401UnauthorizedTOKEN_EXPIREDJWT expiredYes (refresh)
401UnauthorizedTOKEN_INVALIDToken signature invalid or revokedNo (re-auth)
403ForbiddenPERMISSION_DENIEDAuthenticated but insufficient permissionsNo
403ForbiddenSOD_VIOLATIONSeparation of Duties conflictNo
403ForbiddenTENANT_MISMATCHResource belongs to different tenantNo
404Not FoundRESOURCE_NOT_FOUNDEntity does not exist or is not visible to callerNo
409ConflictVERSION_CONFLICTOptimistic concurrency violationYes (re-fetch)
409ConflictDUPLICATE_OPERATIONIdempotency key collision (same request already processed)No (use existing)
422UnprocessableVALIDATION_FAILEDBusiness rule validation failureNo
422UnprocessableGUARD_REJECTEDState machine guard condition not metNo (fix condition)
422UnprocessableDEPENDENCY_UNSATISFIEDLinked WO dependency not completeNo (wait)
429Rate LimitedRATE_EXCEEDEDToo many requestsYes (after reset)
500InternalINTERNAL_ERRORUnhandled server errorYes (with backoff)
503UnavailableSERVICE_DEGRADEDUpstream dependency unavailableYes (with backoff)

1.7 Rate Limits

TierRead (GET)Write (POST/PATCH/PUT)Audit ExportWindow
Starter100/min30/min5/hourRolling
Professional500/min100/min20/hourRolling
Enterprise2,000/min500/minUnlimitedRolling
Agent (internal)5,000/min1,000/minN/ARolling

2. Work Order Endpoints

2.1 Create Work Order

POST /v1/work-orders

Authorization: wo:create permission (ORIGINATOR, ASSIGNER, SYSTEM_OWNER)

Request Body:

{
"type": "CORRECTIVE" | "PREVENTIVE" | "CALIBRATION" | "INSTALLATION" | "UPGRADE" | "DECOMMISSION",
"regulatory": true,
"priority": "LOW" | "MEDIUM" | "HIGH" | "CRITICAL",
"title": "HPLC-001 Annual PM and Calibration",
"description": "Perform annual preventive maintenance...",
"assetId": "asset_clu123",
"masterId": null,
"dependsOn": [],
"scheduledStart": "2026-03-15T09:00:00Z",
"scheduledEnd": "2026-03-15T17:00:00Z",
"metadata": {}
}
FieldTypeRequiredValidation
typeenumYesOne of 6 WO types
regulatorybooleanYesIf true, requires QA approval chain
priorityenumYesOne of 4 priority levels
titlestringYes5–500 chars
descriptionstringNoMax 10,000 chars
assetIdstringNoMust exist in asset registry if provided
masterIdstringNoIf set, creates a linked WO under this master
dependsOnstring[]NoWO IDs that must complete before this WO starts
scheduledStartdatetimeNoISO 8601; must be future
scheduledEnddatetimeNoMust be after scheduledStart

Response (201 Created):

{
"data": {
"id": "wo_clu789",
"status": "DRAFT",
"type": "PREVENTIVE",
"regulatory": true,
"priority": "HIGH",
"title": "HPLC-001 Annual PM and Calibration",
"description": "...",
"assetId": "asset_clu123",
"masterId": null,
"dependsOn": [],
"scheduledStart": "2026-03-15T09:00:00Z",
"scheduledEnd": "2026-03-15T17:00:00Z",
"createdBy": "user_abc",
"createdAt": "2026-02-13T14:30:00Z",
"updatedAt": "2026-02-13T14:30:00Z",
"version": 1,
"metadata": {}
}
}

Audit: Creates AuditTrail entry: {action: "CREATE", entity_type: "WorkOrder", entity_id: "wo_clu789"}.

Compliance: If regulatory: true, compliance engine validates required fields and pre-populates approval chain template.


2.2 Get Work Order

GET /v1/work-orders/:id

Authorization: wo:read per RBAC matrix (role + ownership determines field visibility)

Response (200 OK):

Full WO object (same shape as create response) plus computed fields:

{
"data": {
"...": "all creation fields",
"assigneeId": "user_def",
"assigneeName": "Jane Smith",
"completedAt": null,
"closedAt": null,
"approvals": [
{
"id": "apr_001",
"approverId": "user_ghi",
"role": "SYSTEM_OWNER",
"status": "APPROVED",
"decidedAt": "2026-02-13T15:00:00Z",
"signatureId": "sig_xyz"
}
],
"linkedWorkOrders": 3,
"progress": {
"total": 5,
"completed": 2,
"blocked": 1,
"percentComplete": 40
},
"riskAssessment": {
"riskScore": 12,
"likelihood": 3,
"impact": 4,
"category": "COMPLIANCE"
}
}
}

VENDOR role: Receives filtered view — no riskAssessment, limited approvals, no internal metadata.


2.3 List Work Orders

GET /v1/work-orders?status=IN_PROGRESS&priority=HIGH&regulatory=true&limit=25&cursor=xxx

Query Parameters:

ParameterTypeDescription
statusenum (comma-separated)Filter by status(es)
typeenum (comma-separated)Filter by WO type(s)
priorityenum (comma-separated)Filter by priority(ies)
regulatorybooleanFilter regulatory/non-regulatory
assetIdstringFilter by asset
masterIdstringFilter linked WOs under a master
assigneeIdstringFilter by assignee
createdAfterdatetimeCreated after this timestamp
createdBeforedatetimeCreated before this timestamp
searchstringFull-text search on title + description

Authorization: Results filtered by RBAC. VENDOR sees only WOs assigned to their entity. AUDITOR sees all WOs read-only.


2.4 Transition Status

PATCH /v1/work-orders/:id/status

Authorization: Transition-specific per state machine guard (19-state-machine-with-guards.md)

Request Body:

{
"targetStatus": "PENDING_APPROVAL",
"reason": "Job plan complete, ready for SO review",
"version": 3
}
FieldTypeRequiredValidation
targetStatusenumYesMust be valid transition from current status
reasonstringConditionalRequired if regulatory: true
versionintegerYesOptimistic concurrency — must match current version

Response (200 OK): Updated WO with new status and incremented version.

Error Responses:

  • 409 VERSION_CONFLICT if version doesn't match (another user modified the WO)
  • 422 INVALID_TRANSITION if state machine rejects the transition
  • 422 GUARD_REJECTED if a guard condition fails (e.g., missing approval for regulatory WO)
  • 403 SOD_VIOLATION if approver is same as originator

Guards Evaluated (examples):

  • DRAFT→PENDING_APPROVAL: Job plan exists, required fields populated
  • PENDING_APPROVAL→ASSIGNED: All required approvals collected, e-signatures valid
  • IN_PROGRESS→COMPLETED: All linked WOs completed or explicitly waived
  • COMPLETED→CLOSED: Final documentation attached, compliance engine sign-off

Audit: Immutable audit entry with previous_value (old status) and new_value (new status), plus reason and performer identity.


2.5 Update Work Order Fields

PUT /v1/work-orders/:id

Authorization: wo:update — varies by status (DRAFT: broad; post-DRAFT: restricted fields only)

Mutable Fields by Status:

StatusMutable Fields
DRAFTAll fields except id, tenantId, createdBy, createdAt
PLANNED, PENDING_APPROVALpriority, scheduledStart, scheduledEnd, description, metadata
ASSIGNED, IN_PROGRESSpriority (with re-approval if regulatory), metadata
BLOCKEDmetadata (block reason, unblock plan)
COMPLETED, CLOSEDNone (immutable)

Request requires version field for optimistic concurrency.


3. Approval Endpoints

3.1 Request Approval

POST /v1/work-orders/:id/approvals

Request:

{
"approverId": "user_ghi",
"role": "SYSTEM_OWNER",
"dueDate": "2026-02-15T17:00:00Z"
}

3.2 Submit Approval Decision

PATCH /v1/work-orders/:id/approvals/:approvalId

Request:

{
"decision": "APPROVED" | "REJECTED" | "RETURNED_FOR_REVISION",
"comments": "Approved. Job plan adequate for HPLC-001 annual PM.",
"signature": {
"authMethod": "PASSWORD_REAUTH",
"meaning": "Approval of Work Order wo_clu789 as System Owner"
}
}

Compliance: If regulatory: true, signature block is required. Triggers re-authentication flow (64-security-architecture.md §2.3). Creates ElectronicSignature record with cryptographic hash binding (17-e-signature-architecture.md).

SOD Enforcement: Server rejects if approverId matches createdBy for same WO (22-rbac-permissions-matrix.md §5.1).

3.3 List Approvals

GET /v1/work-orders/:id/approvals

Returns all approval records for the WO including pending, approved, rejected, with signature verification status.


4. Job Plan Endpoints

4.1 Create/Update Job Plan

POST /v1/work-orders/:id/job-plan

Request:

{
"steps": [
{
"sequence": 1,
"description": "Power down HPLC system",
"estimatedMinutes": 15,
"toolRequirements": ["tool_wrench_set", "tool_multimeter"],
"experienceRequirements": ["exp_hplc_maintenance"],
"personCount": 1
}
],
"materialRequirements": [
{"materialId": "mat_filter_001", "quantity": 2, "unit": "EACH"}
],
"estimatedTotalHours": 8.0,
"specialInstructions": "Requires cleanroom access"
}

4.2 Get Job Plan

GET /v1/work-orders/:id/job-plan

5. Hierarchy & Dependency Endpoints

5.1 List Linked Work Orders

GET /v1/work-orders/:id/linked?include_progress=true

Returns all WOs linked to a master, with optional progress summaries.

5.2 Get Dependency Graph

GET /v1/work-orders/:id/dependency-graph

Response:

{
"data": {
"nodes": [
{"id": "wo_001", "status": "COMPLETED", "title": "..."},
{"id": "wo_002", "status": "IN_PROGRESS", "title": "..."},
{"id": "wo_003", "status": "DRAFT", "title": "...", "blockedBy": ["wo_002"]}
],
"edges": [
{"from": "wo_001", "to": "wo_002"},
{"from": "wo_002", "to": "wo_003"}
],
"hasCycles": false
}
}

5.3 Get Critical Path

GET /v1/work-orders/:id/critical-path

Returns the longest dependency chain through the Master WO's linked WOs with estimated completion dates.

5.4 Get Master WO Progress

GET /v1/work-orders/:id/progress

Returns aggregated progress: total linked WOs, completion percentages, blocked items, estimated completion.


6. Audit Trail Endpoints

6.1 Get Audit Trail

GET /v1/work-orders/:id/audit-trail?limit=50&cursor=xxx

Authorization: audit:read (QA, SYSTEM_OWNER, AUDITOR, ADMIN)

Response:

{
"data": [
{
"id": "aud_001",
"entityType": "WorkOrder",
"entityId": "wo_clu789",
"action": "STATUS_CHANGE",
"performedBy": "user_abc",
"performedByName": "John Doe",
"performedByRole": "ASSIGNER",
"performedAt": "2026-02-13T15:00:00Z",
"previousValue": "{\"status\":\"DRAFT\"}",
"newValue": "{\"status\":\"PENDING_APPROVAL\"}",
"reason": "Job plan complete",
"ipAddress": "10.0.1.42",
"userAgent": "CODITECT-Web/1.0",
"chainHash": "sha256:abc123..."
}
],
"pagination": { "cursor": "...", "has_more": true, "total_count": 47 },
"chainIntegrity": {
"verified": true,
"entriesChecked": 47,
"lastVerifiedAt": "2026-02-13T15:05:00Z"
}
}

Compliance: Audit trail entries are immutable. No UPDATE or DELETE operations exist. chainHash enables tamper detection per 64-security-architecture.md §1 (STRIDE: Tampering).

6.2 Export Audit Trail

GET /v1/work-orders/:id/audit-trail/export?format=pdf|csv|json

Authorization: audit:export (AUDITOR, ADMIN) — rate limited per tier.

Generates a compliance evidence package suitable for FDA inspection (see 75-audit-readiness-guide.md).


7. Resource Endpoints

7.1 Resource Matching

POST /v1/resources/match

Request:

{
"workOrderId": "wo_clu789",
"requirements": {
"tools": ["tool_wrench_set"],
"experience": ["exp_hplc_maintenance"],
"personCount": 2,
"scheduledStart": "2026-03-15T09:00:00Z",
"scheduledEnd": "2026-03-15T17:00:00Z"
}
}

Response: Ranked candidate list with availability, experience match score, and cost.

7.2 Asset Registry

GET /v1/assets?search=HPLC&status=ACTIVE&limit=25
GET /v1/assets/:id
POST /v1/assets (ADMIN only)
PUT /v1/assets/:id (ADMIN only)

7.3 Person Registry

GET /v1/persons?team=calibration&experience=hplc_maintenance
GET /v1/persons/:id
GET /v1/persons/:id/experience (experience + certifications with expiry)
GET /v1/persons/:id/availability (schedule for date range)

7.4 Tool & Material Registries

GET /v1/tools?calibrationDueBefore=2026-04-01
GET /v1/materials?belowMinimum=true

8. Risk Assessment Endpoints

Per G16 (CAPA workflow — see 74-capa-workflow.md):

8.1 Create Risk Assessment

POST /v1/work-orders/:id/risk-assessment

Request:

{
"likelihood": 3,
"impact": 4,
"category": "COMPLIANCE" | "SAFETY" | "OPERATIONAL" | "DATA_INTEGRITY",
"mitigationPlan": "...",
"residualRisk": 6
}

Guard integration: WO cannot transition to PENDING_REVIEW if regulatory: true and no risk assessment exists.

8.2 Get Risk Assessment

GET /v1/work-orders/:id/risk-assessment

9. Health & System Endpoints

GET /v1/health                    # Basic health (public, no auth)
GET /v1/health/detailed # Component health (ADMIN only)
GET /v1/health/compliance # Compliance engine status (QA, ADMIN)
GET /v1/metrics # Prometheus metrics (internal network only)

10. Webhook Delivery

Outbound webhooks per 67-integration-api-strategy.md §4:

POST {customer_webhook_url}

Headers:
X-Webhook-ID: evt_uuid7
X-Webhook-Signature: sha256=hmac_signature
X-Webhook-Timestamp: 1707836400
Content-Type: application/json

Subscribable Events:

EventTriggerPayload Key Fields
work_order.createdWO createdid, type, regulatory, priority
work_order.status_changedStatus transitionid, previousStatus, newStatus, reason
work_order.approval_requestedApproval createdid, approverId, role, dueDate
work_order.approval_decidedApproval submittedid, approvalId, decision
work_order.completedWO reaches COMPLETEDid, completedAt, duration
work_order.closedWO reaches CLOSEDid, closedAt, full summary
work_order.blockedWO enters BLOCKEDid, blockReason
compliance.violation_detectedCompliance engine findingworkOrderId, violation, severity

11. Cross-Reference

ConcernSpecification Source
State machine transitions19-state-machine-with-guards.md
RBAC per endpoint22-rbac-permissions-matrix.md
Data model schemas16-prisma-data-model.md
E-signature flow17-e-signature-architecture.md
Agent message contracts26-agent-message-contracts.md
API design philosophy67-integration-api-strategy.md §2
Error experience68-user-experience-journeys.md §5
Rate limit tiers60-business-model.md (subscription tiers)
Webhook architecture67-integration-api-strategy.md §4

This specification is the contract between frontend, agent, and integration consumers. All endpoint behavior is validated by integration tests (65-testing-strategy.md §1) and contract tests. Breaking changes require API versioning per 69-versioning-evolution-strategy.md §1.