Workflows API
The Workflows API manages configurable workflow processes for quality events, document approvals, supplier qualification, and other business processes requiring structured state transitions and approvals.
Workflow Model
Section titled “Workflow Model”{ "id": "wf_abc123def456", "name": "Deviation Workflow", "description": "Standard workflow for deviation management", "entity_types": ["deviation"], "version": 2, "is_active": true, "states": [ { "id": "draft", "name": "Draft", "type": "initial", "allowed_transitions": ["submitted"] }, { "id": "submitted", "name": "Submitted", "type": "intermediate", "allowed_transitions": ["investigation", "rejected"] }, { "id": "investigation", "name": "Under Investigation", "type": "intermediate", "allowed_transitions": ["root_cause_identified", "rejected"] }, { "id": "root_cause_identified", "name": "Root Cause Identified", "type": "intermediate", "allowed_transitions": ["action_planning"] }, { "id": "action_planning", "name": "Action Planning", "type": "intermediate", "allowed_transitions": ["pending_approval"] }, { "id": "pending_approval", "name": "Pending Approval", "type": "approval", "allowed_transitions": ["implementation", "action_planning"], "approval_config": { "required_approvers": 1, "approver_roles": ["quality_manager"] } }, { "id": "implementation", "name": "Implementation", "type": "intermediate", "allowed_transitions": ["verification"] }, { "id": "verification", "name": "Verification", "type": "intermediate", "allowed_transitions": ["closed", "implementation"] }, { "id": "closed", "name": "Closed", "type": "final" }, { "id": "rejected", "name": "Rejected", "type": "final" } ], "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-15T10:00:00Z"}State Types
Section titled “State Types”| Type | Description |
|---|---|
initial | Starting state for new items |
intermediate | Normal processing state |
approval | Requires approval to transition |
final | Terminal state (closed, rejected, etc.) |
List Workflows
Section titled “List Workflows”GET /v1/workflowsQuery Parameters
Section titled “Query Parameters”| Parameter | Type | Description |
|---|---|---|
entity_type | string | Filter by applicable entity type |
is_active | boolean | Filter by active status |
curl -X GET "https://api.cohera.io/v1/workflows?entity_type=deviation&is_active=true" \ -H "Authorization: Bearer YOUR_API_KEY"response = requests.get( "https://api.cohera.io/v1/workflows", params={"entity_type": "deviation", "is_active": True}, headers={"Authorization": "Bearer YOUR_API_KEY"})
workflows = response.json()["data"]for wf in workflows: print(f"{wf['name']} (v{wf['version']}) - {len(wf['states'])} states")const params = new URLSearchParams({ entity_type: "deviation", is_active: "true",});
const response = await fetch( `https://api.cohera.io/v1/workflows?${params}`, { headers: { Authorization: `Bearer ${process.env.COHERA_API_KEY}`, }, });
const { data: workflows } = await response.json();workflows.forEach((wf) => { console.log(`${wf.name} (v${wf.version}) - ${wf.states.length} states`);});Get Workflow Instance
Section titled “Get Workflow Instance”Get the current workflow state for a specific entity.
GET /v1/workflows/instances/{entity_id}Response
Section titled “Response”{ "data": { "entity_id": "qe_deviation_123", "entity_type": "deviation", "workflow_id": "wf_abc123", "workflow_name": "Deviation Workflow", "current_state": { "id": "investigation", "name": "Under Investigation", "entered_at": "2024-01-20T10:00:00Z", "entered_by": "user_quality_lead" }, "available_transitions": [ { "to_state": "root_cause_identified", "requires_fields": ["root_cause.category", "root_cause.description"], "requires_approval": false }, { "to_state": "rejected", "requires_fields": ["rejection_reason"], "requires_approval": false } ], "history": [ { "from_state": "submitted", "to_state": "investigation", "transitioned_at": "2024-01-20T10:00:00Z", "transitioned_by": "user_quality_lead", "comment": "Beginning investigation" }, { "from_state": "draft", "to_state": "submitted", "transitioned_at": "2024-01-20T08:30:00Z", "transitioned_by": "user_lab_analyst", "comment": null } ] }}Execute Transition
Section titled “Execute Transition”Move an entity to a new workflow state.
POST /v1/workflows/instances/{entity_id}/transitionRequest Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
to_state | string | Yes | Target state ID |
comment | string | No | Transition comment |
data | object | Conditional | Required fields for the transition |
curl -X POST "https://api.cohera.io/v1/workflows/instances/qe_deviation_123/transition" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "to_state": "root_cause_identified", "comment": "Root cause determined through investigation", "data": { "root_cause": { "category": "supplier_quality", "description": "Supplier process variation led to sub-specification material" } } }'response = requests.post( f"https://api.cohera.io/v1/workflows/instances/{entity_id}/transition", headers={ "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, json={ "to_state": "root_cause_identified", "comment": "Root cause determined through investigation", "data": { "root_cause": { "category": "supplier_quality", "description": "Supplier process variation led to sub-specification material" } } })
result = response.json()["data"]print(f"Transitioned to: {result['current_state']['name']}")const response = await fetch( `https://api.cohera.io/v1/workflows/instances/${entityId}/transition`, { method: "POST", headers: { Authorization: `Bearer ${process.env.COHERA_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ to_state: "root_cause_identified", comment: "Root cause determined through investigation", data: { root_cause: { category: "supplier_quality", description: "Supplier process variation led to sub-specification material", }, }, }), });
const { data: result } = await response.json();console.log(`Transitioned to: ${result.current_state.name}`);Transition Errors
Section titled “Transition Errors”{ "error": { "code": "invalid_transition", "message": "Cannot transition from 'investigation' to 'closed'", "details": { "current_state": "investigation", "requested_state": "closed", "allowed_transitions": ["root_cause_identified", "rejected"] } }}Approvals
Section titled “Approvals”List Pending Approvals
Section titled “List Pending Approvals”Get items pending your approval.
GET /v1/workflows/approvals/pendingcurl -X GET "https://api.cohera.io/v1/workflows/approvals/pending" \ -H "Authorization: Bearer YOUR_API_KEY"response = requests.get( "https://api.cohera.io/v1/workflows/approvals/pending", headers={"Authorization": "Bearer YOUR_API_KEY"})
pending = response.json()["data"]print(f"You have {len(pending)} items pending approval")
for item in pending: print(f" - {item['entity_type']}: {item['title']} (requested by {item['requested_by']})")const response = await fetch( "https://api.cohera.io/v1/workflows/approvals/pending", { headers: { Authorization: `Bearer ${process.env.COHERA_API_KEY}`, }, });
const { data: pending } = await response.json();console.log(`You have ${pending.length} items pending approval`);
pending.forEach((item) => { console.log( ` - ${item.entity_type}: ${item.title} (requested by ${item.requested_by})` );});Response
Section titled “Response”{ "data": [ { "approval_id": "apr_abc123", "entity_id": "qe_deviation_456", "entity_type": "deviation", "title": "DEV-2024-0042: Out-of-specification result", "current_state": "pending_approval", "requested_at": "2024-01-22T14:00:00Z", "requested_by": "user_quality_lead", "due_date": "2024-01-25T14:00:00Z", "approval_type": "single", "summary": { "classification": "major", "root_cause": "supplier_quality", "proposed_actions": 4 } } ]}Submit Approval Decision
Section titled “Submit Approval Decision”POST /v1/workflows/approvals/{approval_id}Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
decision | string | Yes | approve or reject |
comment | string | Yes | Approval/rejection comment |
conditions | array | No | Conditions for conditional approval |
curl -X POST "https://api.cohera.io/v1/workflows/approvals/apr_abc123" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "decision": "approve", "comment": "Approved. Root cause analysis is thorough and proposed actions are appropriate." }'response = requests.post( f"https://api.cohera.io/v1/workflows/approvals/{approval_id}", headers={ "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, json={ "decision": "approve", "comment": "Approved. Root cause analysis is thorough and proposed actions are appropriate." })
result = response.json()["data"]print(f"Approval submitted. Entity moved to: {result['new_state']}")const response = await fetch( `https://api.cohera.io/v1/workflows/approvals/${approvalId}`, { method: "POST", headers: { Authorization: `Bearer ${process.env.COHERA_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ decision: "approve", comment: "Approved. Root cause analysis is thorough and proposed actions are appropriate.", }), });
const { data: result } = await response.json();console.log(`Approval submitted. Entity moved to: ${result.new_state}`);Rejection with Return to Previous State
Section titled “Rejection with Return to Previous State”{ "decision": "reject", "comment": "Additional information required. Please provide supplier investigation report.", "return_to_state": "action_planning"}Electronic Signatures
Section titled “Electronic Signatures”For compliance with 21 CFR Part 11, certain transitions require electronic signatures.
Signature-Required Transitions
Section titled “Signature-Required Transitions”When a transition requires an electronic signature:
POST /v1/workflows/instances/{entity_id}/transition{ "to_state": "closed", "comment": "Deviation closed after successful verification", "signature": { "meaning": "I have reviewed and approve closure of this deviation", "password": "user_password" }}Signature Response
Section titled “Signature Response”{ "data": { "entity_id": "qe_deviation_123", "current_state": { "id": "closed", "name": "Closed", "entered_at": "2024-01-25T16:00:00Z" }, "signature_record": { "signer": "user_quality_manager", "signer_name": "Jane Smith", "meaning": "I have reviewed and approve closure of this deviation", "timestamp": "2024-01-25T16:00:00Z", "signature_id": "sig_xyz789" } }}Workflow Configuration
Section titled “Workflow Configuration”Create Workflow
Section titled “Create Workflow”POST /v1/workflows{ "name": "Document Approval Workflow", "description": "Workflow for controlled document approvals", "entity_types": ["document"], "states": [ { "id": "draft", "name": "Draft", "type": "initial", "allowed_transitions": ["review"] }, { "id": "review", "name": "Under Review", "type": "intermediate", "allowed_transitions": ["approval", "draft"] }, { "id": "approval", "name": "Pending Approval", "type": "approval", "allowed_transitions": ["effective", "draft"], "approval_config": { "required_approvers": 2, "approver_roles": ["document_owner", "quality_assurance"], "require_signature": true } }, { "id": "effective", "name": "Effective", "type": "final" } ]}Update Workflow
Section titled “Update Workflow”PATCH /v1/workflows/{workflow_id}Workflow Metrics
Section titled “Workflow Metrics”Get Workflow Statistics
Section titled “Get Workflow Statistics”GET /v1/workflows/{workflow_id}/metricsResponse
Section titled “Response”{ "data": { "workflow_id": "wf_abc123", "period": "30d", "total_instances": 45, "completed_instances": 32, "average_completion_time_hours": 156, "by_state": { "draft": 3, "submitted": 2, "investigation": 5, "pending_approval": 3, "closed": 32 }, "bottlenecks": [ { "state": "pending_approval", "average_time_hours": 48, "instances_waiting": 3 } ], "sla_compliance": { "on_time": 28, "overdue": 4, "compliance_rate": 87.5 } }}