Skip to main content
Waitpoints are durable approval/external-completion pauses created by a routine wait step. Tokens are opaque capabilities; do not expose them in logs.

List pending waitpoints

Requires workspace authentication and membership. The response is an array (maximum 200) of objects: A database failure is 500.

Who may decide

Every completing route goes through one resolve door (B14, #2388, PR #2394) that derives the decider from the request’s auth, never from the body:
  • a session or CLI-token principal is a person — the inbox, the routine page, crewship routine waitpoints approve|reject;
  • the holder of the token on the external route is external (recorded as external-callback);
  • an agent’s internal token is an agent, and the door refuses it: 403 {"error": …, "reason": "waitpoint_decider_not_allowed"}. The waitpoint is untouched and the attempt is written to the audit log as waitpoint.decision_refused (crewship audit --action waitpoint.decision_refused). A request with no principal at all is refused the same way. In practice an agent never reaches the authenticated route — internal tokens are 401 there — but the door checks the kind regardless, so a future agent-facing route cannot quietly become a way for a peer agent to say “go”.

Approve or deny from the inbox

The body is optional; absent approved means false on this authenticated route. comment is optional and is stored as the decision payload. This is an update/MANAGER+ operation. A successful response is {"ok":true,"approved":true|false} and resumes the parked run for either decision. Missing tokens are 400; malformed JSON is 400; an expired/already-decided token is 409; an unauthenticated caller is 401, a role below MANAGER 403, and an agent or principal-less caller 403 with reason: waitpoint_decider_not_allowed (see above); an unavailable waitpoint store is 503; and completion failures are 500.

Complete from an external service

This route has no JWT: the high-entropy token is the authentication. The body is optional and approved defaults to true (unlike the authenticated approve route). payload accepts any JSON and is stored for the resumed step. It returns {"ok":true,"approved":true|false}; an empty token is 400, an already-decided or expired token is 409, malformed JSON is 400, an unavailable or non-completing waitpoint store is 503, and other completion failures are 500.