Skip to main content
Selective coaching returns only the questions an employer chose. It does not grant a full retake or expose grading material to the worker. The account’s default-off Project To-dos agent surface must be enabled for tenant reads and writes.

Discover the contract

GET /coaching/capabilities requires project_todos:read but deliberately does not require feature enablement, a claimed account, or a job. It returns static operation, scope, limit, export, image, event, and typed-error facts without tenant data.

Employer reads

These endpoints require project_todos:read, employer access to the job, and a claimed account. Names are masked; emails and answer keys never appear.

Draft and apply employer feedback

Employer coaching mutations use POST /manage with project_todos:write and a stable idempotencyKey: The plan action is keyless and requires only project_todos:read; nothing becomes worker-visible until confirm. Any changed selection, draft, submission, or review state makes confirm fail closed with 409 PLAN_STALE.

Worker lane

Workers mint the separate project_todos:respond scope from their own settings. Employer API keys — including Full access — cannot receive or use this scope. Autosave rejects changes to answers outside the requested set and uses expectedRevision as an optimistic lock. Worker responses never include answer keys, correct values, scoring rules, other workers, or private employer drafts.

Feedback images

Images use a three-step private lifecycle under /coaching/{assignmentId}/assets: prepare a deterministic reservation and short-lived single-PUT grant, upload bytes directly with upsert disabled, then finalize after server-side size, type, and SHA-256 verification. Status and delivery endpoints return lifecycle facts or a short-lived delivery link. Never log or persist the upload grant. Bytes do not belong in JSON or base64 request fields. If an upload outcome is ambiguous, retry through canonical finalize/status reconciliation rather than requesting a different object path.

Full retakes

To reopen the entire quiz, use require_retake_plan and require_retake_apply. Those checksum-bound actions are intentionally separate from selective coaching.