Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt

Use this file to discover all available pages before exploring further.

GET /api/v1/approvals

List approval requests filtered by status.

Query Parameters

ParameterTypeDefaultDescription
statusstring"pending"Filter by status: "pending", "approved", "rejected"

Response

[
  {
    "id": "approval_001",
    "entityType": "qualificationRule",
    "entityId": "qr_001",
    "entityName": "Credit Score Rule",
    "action": "update",
    "status": "pending",
    "requesterId": "user_001",
    "requesterName": "John Doe",
    "payload": { "config": { "threshold": 650 } },
    "createdAt": "2026-03-15T10:00:00.000Z"
  }
]

POST /api/v1/approvals

Create a new approval request.

Request Body

FieldTypeRequiredDescription
entityTypestringYesEntity type (e.g., "qualificationRule", "contactPolicy", "decisionFlow", "offer")
entityIdstringYesID of the entity to modify
entityNamestringYesDisplay name of the entity
actionstringYes"create", "update", or "delete"
payloadobjectNoThe proposed changes to apply on approval
stagesArray<{ stageName, requiredRole }>NoOptional multi-stage chain. Each stage has stageName: string and requiredRole: "viewer" | "editor" | "admin". Decisions walk the stages in order. When omitted, one default admin stage is created. See Four-eyes governance.

Example

curl -X POST https://playground.kaireonai.com/api/v1/approvals \
  -H "Content-Type: application/json" \
  -H "X-Tenant-Id: my-tenant" \
  -d '{
    "entityType": "qualificationRule",
    "entityId": "qr_001",
    "entityName": "Credit Score Rule",
    "action": "update",
    "payload": { "config": { "threshold": 650 } }
  }'
Response: 201 Created

GET /api/v1/approvals/

Get a single approval request.

POST /api/v1/approvals/

Resolve an approval request (approve or reject). Editors and admins can decide; the per-stage requiredRole is then enforced inside the walk. Viewers are 403’d at the route boundary. When the last stage of the chain is approved, the stored payload is automatically applied to the target entity. Supported entity types for auto-application: algorithmModel, qualificationRule, contactPolicy, decisionFlow, offer, creative, channel, arbitrationProfile. An unsupported entityType causes the whole transaction (stage update + parent flip + apply) to roll back — returning a 409 — so an approval cannot flip to approved without the entity actually changing.

Request Body

FieldTypeRequiredDescription
actionstringYes"approve" or "reject"
commentsstringNoReviewer comments

Response (approved)

{
  "id": "approval_001",
  "status": "approved",
  "approverId": "user_002",
  "approverName": "Admin",
  "comments": "Looks good, deploying to production",
  "resolvedAt": "2026-03-16T14:30:00.000Z"
}

Response (rejected)

{
  "id": "approval_001",
  "status": "rejected",
  "approverId": "user_002",
  "approverName": "Admin",
  "comments": "Threshold too aggressive, please revise",
  "resolvedAt": "2026-03-16T14:30:00.000Z"
}

Roles

EndpointAllowed Roles
GET /approvalsany authenticated
POST /approvalsany authenticated
GET /approvals/{id}any authenticated (returns parent + ordered stages array in one round-trip)
POST /approvals/{id} (resolve)editor or admin (per-stage requiredRole is enforced inside the walk)

Auto-expiry

Pending approvals that sit unresolved for longer than APPROVAL_MAX_AGE_HOURS (default 168 = 7 days) are auto-flipped to status = "expired" by the /api/v1/cron/approvals-expire endpoint. Wire it into your scheduler at any cadence — every 15 minutes is plenty since the operation is a single bulk UPDATE and idempotent. The cutoff is configurable per-deployment via the APPROVAL_MAX_AGE_HOURS env var. Expired requests retain their full audit trail; only status and resolvedAt change. See also: Compliance · Cron jobs