Skip to main content
Project To-dos are the required actions an employer assigns to hired AI trainers on one job: acknowledgements, external training, native forms and quizzes, and work submitted for employer review. The developer surface manages the same list the employer web app shows — there is no separate agent-only store. Everything below applies identically to the HTTP API, the CLI, and the MCP tools.

The data model

  • An item is one logical to-do on a job, organized under an optional category.
  • Every edit publishes a new immutable version. History is never rewritten.
  • An assignment is one person’s obligation for one item version, with an append-only event and evidence trail.
  • Quizzes are to-do items pinned to one immutable published form version.

Audiences are always explicit

Every create, assign, or reissue names its audience. There is no default: omitting audience fails with 400 instead of assigning anyone. SELECTED fails closed. The list must be non-empty and duplicate-free, and every ID must be an active contract of that exact job. An unknown, ended, or foreign ID rejects the whole request with each offender named — nothing is silently dropped, and SELECTED can never turn on future-hire auto-assignment.

Preflight receipts for broad assignments

ACTIVE, FUTURE, and ACTIVE_AND_FUTURE fan out beyond an explicit list, so they require a two-step confirmation:
  1. Call the no-write preflight with the exact request you intend to send. It returns the live recipients (masked names, contract IDs, and counts), future-hire semantics, projected due and blocking behavior, duplicate candidates, and a signed receipt.
  2. Send the mutation unchanged with preflightReceipt set to that token.
The receipt is signed and short-lived (about 15 minutes) and is bound to your token’s account, the job, the action, the audience, the exact request payload, and the live roster. If anything changes — the payload, the roster, the audience — the mutation fails with 409 and a PREFLIGHT_RECEIPT_* reason, and you preflight again. Roster changes that land between the receipt check and the write itself also fail closed with 409 RECIPIENTS_CHANGED. SELECTED does not need a receipt: the explicit ID list is already the exact confirmation.

Idempotency is bound to the whole request

Every mutation requires an idempotencyKey (8–200 characters). For item creation the key is bound to the complete request — definition, audience, selected contracts, placement, and future-hire semantics:
  • The same key with the same request replays: you get the committed result with replayed: true, and no new assignments are created. A replay never re-resolves the roster, so a person hired after the original create is not silently added.
  • The same key with a changed request fails with 409 — a reused key can never widen a fan-out.
  • A different key with an identical active request fails with 409 LIKELY_DUPLICATE unless you explicitly pass allowDuplicate: true.
Item creation and its assignment fan-out commit in one transaction: you never get an item without its assignments or a partial fan-out.
update_item publishes a new immutable version on every call and is not retry-convergent. Do not blind-retry it; verify the result with a read instead.

Normalized results

Mutations return an explicit, machine-readable outcome: the item and version IDs, the audience echo with future-hire semantics, a fan-out summary (matchedContracts, createdAssignments, assignmentIds), the masked recipients the request was verified against, a replayed flag, and warnings. Archiving returns the exact number of open assignments it closed, and that archiving is not reversible through this surface while history is retained.

Privacy

Agent responses identify people by contract ID, user ID, and a masked display name (first name plus last initial). Personal emails never appear in list responses, and the CSV export serves the worker_email column blank.

Permissions

Reads require project_todos:read; every mutation requires project_todos:write, employer access to the job, and a claimed account. Both scopes are available on fine-grained keys and included in full-access keys. The account must also have the default-off project_todos_integrations agent-surface family enabled; a full-access key does not bypass that separate gate. See Scopes and capabilities.

Where to go next

  • API reference — endpoints, actions, and errors.
  • Quiz surface — authoring, assigning, grading, and retakes.
  • CLI — preview-first opentrain todos commands.
  • MCP tools — the same safety contract for MCP agents.