Skip to content
OpenTrain AIOpenTrain AIOpenTrain AIDocs

Ask OpenTrain

Answers from the documentation, with sources.

What would you like to do with OpenTrain?

AI answers can be mistaken. Check the linked sources. Don’t include private account information.

Open app

DEVELOPER DOCUMENTATION

Reviewer Feedback and Task Checklists API

Employer-only REST endpoints for reviewer reports, reviewer access, adaptive checklist authoring, visual preview, publishing, and submission review.

The Public API exposes Reviewer Feedback at /api/public/v1/job-feedback and adaptive Task Checklists at /api/public/v1/job-checklists. Both families require a stored OpenTrain API token and canonical employer access to the exact job.

FamilyRead scopeWrite scope
Reviewer Feedbackjob_feedback:readjob_feedback:write
Task Checklistsjob_checklists:readjob_checklists:write

The write scope implies read. Probe GET /api/public/v1/capabilities before using either family; its agentSurfaces entry reports the rollout and per-operation authorization state. The feature must also be enabled separately for each job before its tab appears to employers or workers.

All mutations require an Idempotency-Key header. Reuse a stable key only for the same intent and payload. The response’s replayed field reports whether the server returned the original durable outcome.

The TypeScript SDK exposes the same operations in @opentrain-ai/sdk 0.13.0 or later. Reviewer Feedback methods include listJobFeedback, getJobFeedbackReport, getJobFeedbackSummary, listJobFeedbackRoster, submitJobFeedback, triageJobFeedbackReport, linkJobFeedbackSubject, reviewer-access methods, and settings methods. Task Checklist methods include list/get/create/manage/validate/resolve/publish, version and submission reads, reorder, settings, capabilities, and previewJobChecklistGrant.

import { OpenTrainClient } from '@opentrain-ai/sdk';
const opentrain = new OpenTrainClient({
apiToken: process.env.OPENTRAIN_API_TOKEN!,
});
const feedback = await opentrain.getJobFeedbackSummary(jobId);
const checklists = await opentrain.listJobChecklists(jobId);
MethodPathPurpose
GET/job-feedback?jobId={jobId}List a bounded report page with authoritative status counts.
POST/job-feedbackSubmit one employer-authored report about a canonical subject.
GET/job-feedback/summary?jobId={jobId}Read total, unresolved, status, per-person, and unlinked aggregates.
GET/job-feedback/roster?jobId={jobId}Discover canonical subjects and all contracts held on the job.
GET/job-feedback/{reportId}Read one report and its append-only event history.
POST/job-feedback/{reportId}/triageChange status using the report’s exact updatedAt value.
POST/job-feedback/{reportId}/link-subjectReconcile a legacy unlinked report to a canonical subject once.
GET/job-feedback/jobs/{jobId}/reviewer-accessList eligible active-contract reviewers and their grant state.
POST/job-feedback/jobs/{jobId}/reviewer-accessGrant or revoke one person’s feedback-authoring access.
POST/job-feedback/jobs/{jobId}/reviewer-access/bulkGrant or revoke up to 200 people transactionally.
GET/job-feedback/jobs/{jobId}/settingsRead the default-off per-job feature state.
POST/job-feedback/jobs/{jobId}/settingsEnable or disable the job feature with confirm: true.

The list endpoint accepts status, subject, severity, reporter, search, createdFrom, createdTo, and 1-based page filters. Use subject=UNLINKED for legacy rows without a canonical person. hasMore is the only continuation signal; never infer completeness from the returned row count.

Terminal window
curl -sS https://app.opentrain.ai/api/public/v1/job-feedback \
-H "Authorization: Bearer $OT_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: feedback-task-482-v1" \
-d '{
"jobId": "<job-id>",
"subjectUserId": "<user-id>",
"externalTrainerId": "masked-482",
"externalTaskId": "task-482",
"severity": "MAJOR",
"suggestedAction": "RETRAINING",
"report": "The response repeatedly applies the wrong acceptance rule to ambiguous regions."
}'

subjectContractId is optional. When omitted, OpenTrain stores a deterministic contract reference: the newest active contract, otherwise the newest ended contract. Use the roster endpoint if the caller needs to choose a specific contract.

Terminal window
curl -sS https://app.opentrain.ai/api/public/v1/job-feedback/<report-id>/triage \
-H "Authorization: Bearer $OT_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: feedback-actioned-482-v1" \
-d '{
"toStatus": "ACTIONED",
"expectedUpdatedAt": "<updated-at-from-get>",
"note": "Assigned the focused retraining module and paused production work."
}'

Terminal transitions to ACTIONED or DISMISSED, and reopening from a terminal state, require a nonblank note. A stale expectedUpdatedAt returns 409; get the report again and deliberately re-evaluate the transition.

MethodPathPurpose
GET/job-checklists/capabilitiesRead the live schema, limits, operations, and optional job state.
GET/job-checklists?jobId={jobId}List every definition in display order plus the per-job enabled state.
POST/job-checklistsCreate one complete draft atomically.
POST/job-checklists/validateValidate a complete local bundle without writing.
POST/job-checklists/reorderReorder the complete definition set with a compare-and-set guard.
GET/job-checklists/{definitionId}Read the employer builder detail and draft revision.
PATCH/job-checklists/{definitionId}Update the draft, retire, or restore a definition.
POST/job-checklists/{definitionId}/validateValidate the stored draft or published tree.
POST/job-checklists/{definitionId}/resolveResolve caller-supplied sample answers without storing them.
POST/job-checklists/{definitionId}/preview-grantMint a short-lived browser URL bound to an exact draft or published revision.
POST/job-checklists/{definitionId}/publishPublish an immutable version with draft and live-version guards.
GET/job-checklists/{definitionId}/versionsPage immutable versions newest first.
GET/job-checklists/{definitionId}/versions/{versionNumber}Read one immutable version and tree.
GET/job-checklists/submissions?jobId={jobId}Filter and page employer-visible submission rows.
GET/job-checklists/submissions/{submissionId}Read one version-pinned submitted tree and active answers.
POST/job-checklists/jobs/{jobId}/settingsEnable the feature, or disable it with explicit confirmation.
Terminal window
curl -sS https://app.opentrain.ai/api/public/v1/job-checklists/validate \
-H "Authorization: Bearer $OT_API_TOKEN" \
-H "Content-Type: application/json" \
-d @checklist-validate.json
checklist-validate.json
{
"mode": "inline",
"title": "Image QC",
"required": true,
"tree": [
{
"id": "domain",
"type": "SINGLE_CHOICE",
"text": "What is your domain specialization?",
"requiredBoolean": true,
"options": [
{ "id": "automotive", "label": "Automotive" },
{ "id": "general", "label": "General" }
]
},
{
"id": "car-count",
"type": "NUMBER",
"text": "How many cars are in the image?",
"requiredBoolean": true,
"numberConfig": { "integerOnly": true, "min": 0, "max": 20 }
},
{
"id": "cars",
"type": "REPEAT_GROUP",
"text": "Inspect each car",
"repeatConfig": {
"countNodeId": "car-count",
"maxInstances": 20,
"instanceLabelText": "Car"
},
"children": [
{
"id": "car-edges",
"type": "CHECKBOX",
"text": "Verify the object boundary",
"requiredBoolean": true
}
]
}
]
}

Inline validation can include baselineDefinitionId and expectedDraftVersion to calculate publish impact and detect a stale local base before writing. Use the exact same server validator for create, draft update, and publish readiness—do not reimplement its rules in a client.

Mint a preview grant with one closed source mode:

{ "source": "draft", "expectedDraftVersion": 4 }

or:

{ "source": "published", "versionNumber": 2 }

The response returns a short-lived previewUrl whose fragment carries the capability. Open that URL in an authenticated browser. It renders the exact bound snapshot and strips the fragment after exchange.

Publish only after previewing:

{
"expectedDraftVersion": 4,
"expectedPublishedVersionNumber": 2,
"confirmPublish": true
}

The response reports the immutable version and content hash, the change impact, open runs swept, and answers that workers must reconfirm. Read the canonical definition afterward rather than incrementing a version locally.

StatusMeaningRecovery
400Invalid enum, tree, transition, filter, confirmation, or limit.Correct the structured request; do not retry unchanged.
403Missing scope, unavailable family, or no employer organization.Inspect capabilities and use the correct claimed employer token.
404The job or resource is absent or not canonically accessible.Resolve access without probing resource existence.
409Stale revision, invalid lifecycle state, or idempotency conflict.Re-read canonical state and deliberately re-evaluate.
429Write throttle exceeded.Honor retryAfterSeconds; keep the same idempotency key for the same intent.

Use the machine-readable OpenAPI document for the exact schemas served by the current deployment.