Calafai Docs

API Reference: Engagements

API Reference: Engagements

Engagements are the core resource in the Groundtruth Platform. An engagement represents an AI-powered consulting project: it has a brief, a set of tasks, a budget, and produces deliverables through crew execution runs.

All endpoints require authentication (cookie or API key Bearer token). Data is automatically scoped to your tenant.


List Engagements

GET /api/engagements

Returns all engagements for the authenticated tenant, sorted by creation date (newest first). Results are cached in Redis with automatic invalidation on create/delete.

Auth: Required (cookie or API key)

Response:

[
  {
    "id": "clx1abc2d0001...",
    "tenantId": "clx0xyz...",
    "name": "Brand Digital Presence",
    "client": "Acme Corp",
    "slug": "brand-digital-presence",
    "brief": "Develop a comprehensive digital presence strategy...",
    "budget": 5.0,
    "tasks": [],
    "status": "completed",
    "createdAt": "2025-10-15T08:30:00.000Z"
  }
]

curl example:

curl -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements

Create Engagement

POST /api/engagements

Creates a new engagement. Requires an active subscription and checks the monthly engagement limit for your plan.

Auth: Required + write access

Rate limit tier: api

Plan limits:

PlanMonthly Engagement Limit
Starter5
Professional25
EnterpriseUnlimited

Request body:

FieldTypeRequiredDefaultDescription
namestringYes--Display name for the engagement
clientstringYes--Client or project name
briefstringYes--The consulting brief / problem statement
budgetnumberNo5.0Maximum LLM spend in USD
tasksarrayNo[]Array of task configuration objects

Response: 201 Created

{
  "id": "clx1abc2d0001...",
  "tenantId": "clx0xyz...",
  "name": "Go To Market Strategy",
  "client": "Acme Corp",
  "slug": "go-to-market-strategy",
  "brief": "Develop a go-to-market strategy for our new B2B SaaS product...",
  "budget": 10.0,
  "tasks": [],
  "status": "pending",
  "createdAt": "2025-10-15T09:00:00.000Z"
}

Error responses:

StatusErrorCause
400"Name, client, and brief are required"Missing required fields
403"Active subscription required"No active Stripe subscription
403"Monthly engagement limit reached (5/5)"Plan limit exceeded

curl example:

curl -X POST \
  -H "Authorization: Bearer gt_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Go To Market Strategy",
    "client": "Acme Corp",
    "brief": "Develop a go-to-market strategy for our new B2B SaaS product targeting mid-market companies.",
    "budget": 10.0
  }' \
  https://app.groundtruth.ai/api/engagements

Get Engagement Detail

GET /api/engagements/:id

Returns a single engagement with its runs and deliverables included.

Auth: Required (cookie or API key)

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response:

{
  "id": "clx1abc2d0001...",
  "tenantId": "clx0xyz...",
  "name": "Brand Digital Presence",
  "client": "Acme Corp",
  "slug": "brand-digital-presence",
  "brief": "Develop a comprehensive digital presence strategy...",
  "budget": 5.0,
  "tasks": [],
  "status": "completed",
  "createdAt": "2025-10-15T08:30:00.000Z",
  "runs": [
    {
      "id": "clx2run001...",
      "engagementId": "clx1abc2d0001...",
      "status": "completed",
      "startedAt": "2025-10-15T08:31:00.000Z",
      "finishedAt": "2025-10-15T08:55:00.000Z",
      "estimatedCost": 2.34,
      "inputTokens": 45000,
      "outputTokens": 12000,
      "error": null,
      "pauseSnapshot": null
    }
  ],
  "deliverables": [
    {
      "id": "clx3del001...",
      "engagementId": "clx1abc2d0001...",
      "taskId": "digital_strategy",
      "filename": "digital-presence-strategy.md",
      "content": "# Digital Presence Strategy\n\n...",
      "version": 1,
      "wordCount": 2450,
      "createdAt": "2025-10-15T08:55:00.000Z"
    }
  ]
}

curl example:

curl -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001

Delete Engagement

DELETE /api/engagements/:id

Permanently deletes an engagement and all associated data (runs, deliverables). Cannot delete an engagement that is currently running -- stop it first.

Auth: Required + write access

Rate limit tier: api

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response:

{
  "success": true
}

Error responses:

StatusErrorCause
404"Not found"Engagement does not exist or belongs to another tenant
409"Cannot delete a running engagement. Stop it first."Engagement status is running

curl example:

curl -X DELETE \
  -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001

Start Run

POST /api/engagements/:id/run

Starts a crew execution run for the engagement. Creates a Run record, sets the engagement status to running, and dispatches the work to the execution engine on Railway.

This endpoint triggers the engagement.started webhook event and sends an email notification to the user.

Auth: Required + write access + active subscription

Rate limit tier: engine (5 requests per 60 seconds)

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response:

{
  "runId": "clx2run002...",
  "status": "running",
  "message": "Engagement started"
}

Error responses:

StatusErrorCause
403"Active subscription required"No active Stripe subscription
409"Engagement is already running"A run is already in progress
502"Engine error: ..."The execution engine is unreachable or failed to start

On engine failure, the run and engagement status are rolled back to failed.

curl example:

curl -X POST \
  -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001/run

Stop Run

POST /api/engagements/:id/stop

Stops a running engagement. The current run is marked as failed with the error "Stopped by user".

Auth: Required + write access

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response: Engine response (varies).

Error responses:

StatusErrorCause
404"Not found"Engagement not found
502"Engine error: ..."Engine communication failure

curl example:

curl -X POST \
  -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001/stop

Pause Run

POST /api/engagements/:id/pause

Pauses a running engagement. The engine saves a snapshot of the current execution state so it can be resumed later. The run and engagement status are set to paused.

Auth: Required + write access

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response: Engine response (varies).

Error responses:

StatusErrorCause
404"Not found"Engagement not found
502"Engine error: ..."Engine communication failure

curl example:

curl -X POST \
  -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001/pause

Resume Run

POST /api/engagements/:id/resume

Resumes a paused engagement from its saved execution snapshot. The run and engagement status are set back to running.

Auth: Required + write access

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response: Engine response (varies).

Error responses:

StatusErrorCause
404"Not found"Engagement not found
502"Engine error: ..."Engine communication failure

curl example:

curl -X POST \
  -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001/resume

Get Run Status

GET /api/engagements/:id/status

Returns the current status of an engagement. For active runs (running or paused), the API queries the execution engine directly for real-time status. For terminal states (completed, failed, pending), data is returned from the database.

When the engine reports a terminal state, the API automatically syncs the status back to the database, dispatches the appropriate webhook (engagement.completed or engagement.failed), and sends an email notification.

Auth: Required (cookie or API key)

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response:

{
  "engagementId": "clx1abc2d0001...",
  "status": "running",
  "estimated_cost": 1.23,
  "steps": 4,
  "error": null,
  "budget": 5.0
}

Status values: pending, running, paused, completed, failed

If the engine is unreachable during an active run, the endpoint falls through to return the last known database state.

curl example:

curl -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001/status

Get Run Logs

GET /api/engagements/:id/logs

Returns execution logs from the engine for the engagement.

Auth: Required (cookie or API key)

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Query parameters:

ParameterTypeDefaultDescription
offsetinteger0Number of log lines to skip (for pagination)

Response:

{
  "logs": [
    "2025-10-15T08:31:05Z [chief_strategist] Starting task: market_analysis",
    "2025-10-15T08:32:12Z [research_intelligence_analyst] Completed data gathering"
  ],
  "total": 47,
  "status": "running"
}

If the engine is unreachable, the response contains empty logs with the engagement's database status:

{
  "logs": [],
  "total": 0,
  "status": "running"
}

curl example:

curl -H "Authorization: Bearer gt_live_YOUR_KEY" \
  "https://app.groundtruth.ai/api/engagements/clx1abc2d0001/logs?offset=0"

SSE Stream

GET /api/engagements/:id/stream

Opens a Server-Sent Events (SSE) connection that proxies the real-time event stream from the execution engine. Use this for live dashboards that need immediate updates without polling.

Auth: Required (cookie or API key)

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response: Content-Type: text/event-stream

The stream emits events including:

  • Status updates (running, paused, completed, failed)
  • Cost changes (estimated spend updates)
  • Log lines (real-time agent output)
  • Task completions (individual task finish events)

Event format:

data: {"type":"status","status":"running","timestamp":"2025-10-15T08:31:05Z"}

data: {"type":"cost","estimated_cost":0.45,"timestamp":"2025-10-15T08:32:00Z"}

data: {"type":"log","message":"[chief_strategist] Starting market analysis","timestamp":"2025-10-15T08:31:05Z"}

data: {"type":"task_complete","taskId":"market_analysis","timestamp":"2025-10-15T08:35:00Z"}

Error responses:

StatusErrorCause
404"Not found"Engagement not found
502"Failed to connect to engine"Engine unreachable

curl example:

curl -N -H "Authorization: Bearer gt_live_YOUR_KEY" \
  -H "Accept: text/event-stream" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001/stream

JavaScript example:

const eventSource = new EventSource(
  "/api/engagements/clx1abc2d0001/stream",
  { withCredentials: true }
);

eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log(data.type, data);
};

eventSource.onerror = () => {
  console.log("Stream disconnected, falling back to polling");
  eventSource.close();
};

Get Quality Scores

GET /api/engagements/:id/quality

Returns quality scores for the latest run of an engagement. Scores are generated by the Observer module (GPT-4o-mini) which evaluates each task's output against quality rubrics.

Auth: Required (cookie or API key)

Rate limit tier: api

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response (with scores):

{
  "runId": "clx2run002...",
  "averageScore": 8.2,
  "runStatus": "completed",
  "runStartedAt": "2025-10-15T08:31:00.000Z",
  "scores": [
    {
      "id": "clx4score01...",
      "taskName": "market_analysis",
      "score": 8.5,
      "rubricType": "analytical",
      "feedback": "Thorough analysis with well-sourced data points...",
      "createdAt": "2025-10-15T08:55:00.000Z"
    },
    {
      "id": "clx4score02...",
      "taskName": "strategy_document",
      "score": 7.9,
      "rubricType": "writing",
      "feedback": "Clear structure but could benefit from more specific recommendations...",
      "createdAt": "2025-10-15T08:55:00.000Z"
    }
  ]
}

Response (no scores available):

{
  "runId": "clx2run002...",
  "averageScore": null,
  "scores": []
}

curl example:

curl -H "Authorization: Bearer gt_live_YOUR_KEY" \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001/quality

Get Run Analytics

GET /api/engagements/:id/analytics

Returns agent participation, delegation network, and model routing data for the engagement's latest run. Enriches raw run report data with agent configs (role, department) and model routing decisions.

Auth: Required (cookie or API key, minimum viewer role)

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Response:

{
  "agents": [
    {
      "slug": "research_intelligence_analyst",
      "role": "Research Intelligence Analyst",
      "department": "Research",
      "steps": 3,
      "models": [
        { "model": "gpt-4.1-nano", "taskCount": 2 },
        { "model": "claude-sonnet-4-6", "taskCount": 1 }
      ]
    }
  ],
  "delegations": [
    { "from": "chief_strategist", "to": "research_intelligence_analyst", "count": 1 }
  ],
  "modelRouting": [
    {
      "taskId": "task-1",
      "agentSlug": "research_intelligence_analyst",
      "agentRole": "Research Intelligence Analyst",
      "department": "Research",
      "selectedModel": "gpt-4.1-nano",
      "observerScore": 8,
      "cost": 0.0023
    }
  ]
}

Returns empty arrays if no run has completed yet.


Export Engagement Report as PDF

GET /api/engagements/:id/export/pdf

Generates and downloads a full PDF report for the engagement. The report includes all deliverables (latest version of each), quality scores, and tenant branding (logo, primary color).

System files (filenames starting with _, such as _run_report_*, _operations_review_*, _library_entry_*) are excluded from the report.

This endpoint dispatches the report.generated webhook event.

Auth: Required (cookie or API key, minimum viewer role)

Path parameters:

ParameterDescription
idEngagement ID (cuid)

Query parameters:

ParameterDefaultDescription
include_provenancefalseSet to true to add an "AI Provenance" appendix listing which agent and model produced each deliverable, along with observer scores and costs

Response: Content-Type: application/pdf

The response is a binary PDF file with a Content-Disposition header for download:

Content-Disposition: attachment; filename="brand-digital-presence-report.pdf"

Error responses:

StatusErrorCause
403"Insufficient permissions"User role is below viewer
404"Engagement not found"Engagement does not exist
404"No deliverables to export"No deliverables have been generated yet

curl example:

# Without provenance
curl -H "Authorization: Bearer gt_live_YOUR_KEY" \
  -o report.pdf \
  https://app.groundtruth.ai/api/engagements/clx1abc2d0001/export/pdf

# With provenance appendix
curl -H "Authorization: Bearer gt_live_YOUR_KEY" \
  -o report.pdf \
  "https://app.groundtruth.ai/api/engagements/clx1abc2d0001/export/pdf?include_provenance=true"

Engagement Status Lifecycle

pending --> running --> completed
              |
              +--> paused --> running (resume)
              |
              +--> failed (error, stopped, or engine failure)
StatusDescription
pendingCreated but never run
runningCrew execution is in progress
pausedExecution paused, can be resumed
completedAll tasks finished successfully
failedExecution failed, was stopped, or engine error occurred

  • Deliverables -- List, version, review, rerun, and export deliverables
  • Overview -- Authentication, rate limiting, error format

On this page