curl -sS "https://app.opentrain.ai/api/public/v1/contracts?status=active" \
-H "Authorization: Bearer $OT_API_TOKEN"
opentrain contracts list --status active --json
{
"status": "active"
}
{
"contracts": [
{
"id": "<CONTRACT_ID>",
"status": "active",
"title": "Spanish Sentiment Labeling Contract",
"jobId": "<JOB_ID>",
"proposalId": "<PROPOSAL_ID>",
"paymentType": "FIXED_PRICE",
"rateUsd": 300,
"estimatedTotalUsd": 300,
"estimatedVolume": null,
"hasActiveMilestone": true,
"startDate": "2026-06-12T09:30:00.000Z",
"endDate": null,
"createdAt": "2026-06-12T09:30:00.000Z",
"updatedAt": "2026-06-12T09:30:00.000Z",
"freelancer": {
"userId": "<FREELANCER_ID>",
"displayName": "Maria G.",
"country": "Spain",
"profilePath": "/profile/maria-g"
},
"milestones": [
{
"id": "<MILESTONE_ID>",
"name": "First labeling batch",
"description": "Label the first 5,000 posts per the guidelines",
"status": "ACTIVE_FUNDED",
"amountUsd": 300,
"volume": null,
"milestoneNumber": 1,
"dueDate": "2026-07-01T00:00:00.000Z",
"pendingApproval": false,
"needsReview": false,
"invoiceId": "<INVOICE_ID>",
"createdAt": "2026-06-12T09:30:00.000Z"
}
]
}
]
}
Contracts
List Contracts
List your contracts (hired AI trainers) with milestones, optionally filtered by job or status.
GET
/
api
/
public
/
v1
/
contracts
curl -sS "https://app.opentrain.ai/api/public/v1/contracts?status=active" \
-H "Authorization: Bearer $OT_API_TOKEN"
opentrain contracts list --status active --json
{
"status": "active"
}
{
"contracts": [
{
"id": "<CONTRACT_ID>",
"status": "active",
"title": "Spanish Sentiment Labeling Contract",
"jobId": "<JOB_ID>",
"proposalId": "<PROPOSAL_ID>",
"paymentType": "FIXED_PRICE",
"rateUsd": 300,
"estimatedTotalUsd": 300,
"estimatedVolume": null,
"hasActiveMilestone": true,
"startDate": "2026-06-12T09:30:00.000Z",
"endDate": null,
"createdAt": "2026-06-12T09:30:00.000Z",
"updatedAt": "2026-06-12T09:30:00.000Z",
"freelancer": {
"userId": "<FREELANCER_ID>",
"displayName": "Maria G.",
"country": "Spain",
"profilePath": "/profile/maria-g"
},
"milestones": [
{
"id": "<MILESTONE_ID>",
"name": "First labeling batch",
"description": "Label the first 5,000 posts per the guidelines",
"status": "ACTIVE_FUNDED",
"amountUsd": 300,
"volume": null,
"milestoneNumber": 1,
"dueDate": "2026-07-01T00:00:00.000Z",
"pendingApproval": false,
"needsReview": false,
"invoiceId": "<INVOICE_ID>",
"createdAt": "2026-06-12T09:30:00.000Z"
}
]
}
]
}
Lists the contracts on your account — one per hired AI trainer per job — newest first, each with its milestone timeline. Contracts are created by hiring from a proposal. The AI trainer’s identity stays masked: first name + last initial, country, and profile path (never a full last name or an email — see privacy).
Refunded and cancelled milestones are excluded from the milestone timeline, mirroring the in-app contract view. For the post-hire conversation ID, read a single contract with
GET /contracts/{id}.
Requirements: payments:read scope. Works pre-claim.
Request
string
Only return contracts on this job. Must be a job you own or can access (
403 otherwise; 404 if the job doesn’t exist).string
Filter by contract status:
active or ended. Omit to list both.Response
object[]
Show contract entry
Show contract entry
string
Contract ID — use with
GET /contracts/{id}, POST /contracts/{id}/milestones, and POST /contracts/{id}/end.string
active or ended.string | null
Contract display title.
string | null
The job this contract belongs to.
string | null
The proposal the hire came from.
string | null
Payment model:
FIXED_PRICE, PAY_PER_HOUR, or PAY_PER_LABEL.number | null
Contract rate in USD (per hour / per label for per-unit contracts; total for fixed-price).
number | null
Estimated total contract value in USD.
number | null
Estimated unit volume for per-unit contracts.
boolean
true when the contract currently has a funded, in-progress milestone.string | null
ISO contract start timestamp.
string | null
ISO contract end timestamp,
null while active.string
ISO creation timestamp.
string
ISO last-change timestamp.
object
The hired AI trainer:
{userId, displayName, country, profilePath}. displayName is masked to first name + last initial ("Maria G."); full last names and emails are never included.object[]
Milestone timeline, ordered by milestone number.
Show milestone entry
Show milestone entry
string
Milestone ID — use with
POST /milestones/{id}/fund and POST /milestones/{id}/approve.string | null
Short milestone name.
string | null
Work to deliver.
string | null
NOT_FUNDED, ACTIVE_FUNDED, or COMPLETED.number | null
Milestone amount in USD.
number | null
Unit volume for per-unit milestones.
number | null
Position in the contract’s milestone sequence.
string | null
ISO due date.
boolean
true when the AI trainer has submitted work and the milestone awaits your approval.boolean
true when the milestone is flagged for review.string | null
Linked invoice once funded/paid.
string
ISO creation timestamp.
Errors
| Status | code | Meaning |
|---|---|---|
400 | BAD_REQUEST | status is not active or ended (details: {field: "status"}) |
401 | UNAUTHORIZED | Missing or invalid token |
403 | FORBIDDEN | Missing payments:read scope, or jobId belongs to another account |
404 | NOT_FOUND | jobId does not exist |
curl -sS "https://app.opentrain.ai/api/public/v1/contracts?status=active" \
-H "Authorization: Bearer $OT_API_TOKEN"
opentrain contracts list --status active --json
{
"status": "active"
}
{
"contracts": [
{
"id": "<CONTRACT_ID>",
"status": "active",
"title": "Spanish Sentiment Labeling Contract",
"jobId": "<JOB_ID>",
"proposalId": "<PROPOSAL_ID>",
"paymentType": "FIXED_PRICE",
"rateUsd": 300,
"estimatedTotalUsd": 300,
"estimatedVolume": null,
"hasActiveMilestone": true,
"startDate": "2026-06-12T09:30:00.000Z",
"endDate": null,
"createdAt": "2026-06-12T09:30:00.000Z",
"updatedAt": "2026-06-12T09:30:00.000Z",
"freelancer": {
"userId": "<FREELANCER_ID>",
"displayName": "Maria G.",
"country": "Spain",
"profilePath": "/profile/maria-g"
},
"milestones": [
{
"id": "<MILESTONE_ID>",
"name": "First labeling batch",
"description": "Label the first 5,000 posts per the guidelines",
"status": "ACTIVE_FUNDED",
"amountUsd": 300,
"volume": null,
"milestoneNumber": 1,
"dueDate": "2026-07-01T00:00:00.000Z",
"pendingApproval": false,
"needsReview": false,
"invoiceId": "<INVOICE_ID>",
"createdAt": "2026-06-12T09:30:00.000Z"
}
]
}
]
}
⌘I