Resumes a run that paused for human-in-the-loop (HITL) input. The counterpart to the waiting callback: a task pauses by sending { type: 'waiting', tokenId, … }, and this endpoint completes that waitpoint and lets the task resume.
Use it when the decision is made outside the platform — an external approval service, a Slack-app backend, or agent runtime code. The platform UI uses the same mechanism internally.
Endpoint
POST /api/runs/{runId}/waitpoint
Auth: Authorization: Bearer <agent_api_key>
Same per-agent key as the callback and credential resolution endpoints. Holding it already lets you complete or fail the run, so resuming a waitpoint is the same trust level.
The waitpoint token id is resolved server-side from the run's stored wait state — you only need the platform runId, never the token. A caller (an emailed approval link, a Slack backend) typically knows the run but not the runtime token.
Request
{
"payload": { "decision": "approved", "note": "ship it" },
"userId": "8f3c…"
}
| Field | Type | Description |
|---|---|---|
payload | object | Optional. Forwarded to the runtime as the waitpoint result — the value your task receives where it called wait.forToken(). |
userId | string | Optional attribution (UUID) recorded on the run.waitpoint_completed audit entry. Dropped silently if it is not a member of the agent's org. |
An empty body is valid (completes the waitpoint with no payload).
Response
200 OK → { "ok": true }. The run transitions waiting → running; its final state arrives later via the runtime callback.
Errors
| Status | Reason |
|---|---|
401 | Missing or invalid agent_api_key (also returned when the run does not exist, to avoid leaking run ids). |
409 | The run is not waiting, has no pending token, the runtime does not support waitpoints, or the runtime rejected the completion. |
429 | Per-agent rate limit (20 req/min). |
SDK
import { createAgentClient } from '@cxpa/sdk/agent'
const cxpa = createAgentClient({
baseUrl: process.env.CXPA_API_URL!,
apiKey: process.env.CXPA_REVENUE_CHAT_AGENT_API_KEY!,
runId, // the paused run
})
await cxpa.completeWaitpoint({ decision: 'approved' })
Zones
Zone apps cannot hold the agent_api_key. They resume a waitpoint through the zone-scoped sibling, authenticated by the zone JWT:
POST /api/zones/agents/{agentId}/runs/{runId}/waitpoint
await cxpa.runs.completeWaitpoint(runId, { decision: 'approved' })
See the zone client reference.