view_submission handler and the email magic-link confirmation page (each with their own auth shape — Slack signature, magic-link token).
Authorization
| Caller | Allowed? |
|---|---|
| Admin bearer token | ✓ |
| Operator session | ✓ |
| Assignee session | ✓ |
| Other logged-in user | 403 |
Request
| Field | Type | Required | Description |
|---|---|---|---|
response | object | yes | Must validate against the task’s response_schema. |
completed_by_email | string | null | no | Override stamped attribution. Browser-driven calls leave null and the server reads the session. |
completed_via_channel | string | null | no | Free-form channel identifier (dashboard, slack, email). Used by the audit log. |
Response
POST /api/tasks response). The status field reflects what happened:
completed— verifier passed (or no verifier). Final.rejected— verifier rejected this attempt; the task is non-terminal, the human can resubmit.verification_exhausted— verifier rejected, attempts exhausted. Final.
verifier_result.reason for the verifier’s explanation when rejected / verification_exhausted.
With verifier
Iftask.verifier_config is set:
- Server runs the LLM call inline (5–30s typical).
- Pass →
status=completed,responsesaved, audit log recordsaction=verified. - Fail with attempts left →
status=rejected,verification_attemptbumped, audit log recordsaction=rejected+verifier_reason. The task stays open for resubmission. - Fail with attempts exhausted →
status=verification_exhausted(terminal), audit log recordsaction=verification_exhausted.
error_code and DO NOT consume an attempt.
With redact_payload=True
The verifier is skipped entirely. The operator marked the payload sensitive; we don’t ship it to a third-party LLM. Status goes straight tocompleted.
Errors
| Status | error_code | Cause |
|---|---|---|
| 400 | (validation) | Body shape mismatch. |
| 401 | — | Missing / invalid auth. |
| 403 | — | Caller isn’t operator / admin / assignee. |
| 404 | TASK_NOT_FOUND | Task ID doesn’t exist. |
| 409 | TASK_ALREADY_TERMINAL | Task is already in a terminal status (race with timeout / cancel). |
| 422 | VERIFIER_CONFIG_INVALID | Stored verifier config doesn’t match the current schema. |
| 422 | VERIFIER_PROVIDER_UNKNOWN | Operator typo’d the provider name. |
| 500 | VERIFIER_API_KEY_MISSING | Server can’t read the LLM API key. |
| 500 | VERIFIER_PROVIDER_UNAVAILABLE | SDK extra not installed. |
| 502 | VERIFIER_PROVIDER_ERROR | Vendor returned an error. |
error_code + docs URL.
Outbound webhook
Iftask.callback_url is set AND the task transitions to a terminal status, an HMAC-signed POST fires to the callback URL after the response is sent (FastAPI BackgroundTask — the human’s submit doesn’t wait on it). See Self-hosting → Security for the signature scheme.
SDK equivalent
The dashboard calls this directly from the form submission. From your own code:await_human().