structuredContent; failures return isError: true with the HTTP status and the error envelope. Scopes and feature flags are explained in Scopes and Capabilities.
All tool names below carry the
opentrain_ prefix.
Auth and Identity
opentrain_register_agent
Register a brand-new anonymous OpenTrain agent account — no prior credentials needed. The newot_pat_ token and claim token are saved to the shared config file, so every other tool works immediately afterwards. Refuses to overwrite existing saved credentials unless force is set. Next step: ask the human for their email and call opentrain_claim_account.
Requires: nothing — anonymous and tokenless. Wraps:
POST /api/agent/identity
opentrain_claim_account
Send the human owner a claim invite for the agent-registered account — the start of the claim ceremony. OpenTrain emails them a verification link; once they accept, they own the account and can add billing. Follow up withopentrain_claim_status.
Requires: a valid, unexpired claim token (~24h window from registration). Wraps:
POST /api/agent/identity/claim
opentrain_claim_status
Check whether the human has completed the claim. When the claim completes, the stored API token is upgraded to the claimed account automatically. Aslow_down status means you are polling too fast — respect the poll interval from opentrain_claim_account.
Requires: a valid claim token with an active claim attempt. Wraps:
POST /api/agent/oauth/token
opentrain_auth_status
Confirm that the configured token can authenticate, and see the account’s user id, account type, claim state, and granted scopes. No parameters. Requires: any valid token. Wraps:GET /auth/me
opentrain_capabilities
Discover which job-drafting features are enabled for the account plus the full job field/enum catalog — use it to probe feature availability before drafting. No parameters. Requires: any valid token; thepublic_api_job_drafting feature must be enabled for the account. Wraps: GET /job-drafts/capabilities
Jobs
opentrain_create_job_draft
Create an unpublished job draft from a full job description or supported import payload — the primary drafting workflow. OpenTrain parses the description into structured job fields server-side; the response’s validation state lists each missing field with anask: question to relay to the human, its type, allowed enum values, and the set: field names for opentrain_update_job_draft_fields.
Requires:
jobs:write + the public_api_job_drafting feature. Wraps: POST /job-drafts
opentrain_update_job_draft_fields
Fill in or correct fields on an existing unpublished draft. Ask the human each missing field’sask: question, then patch the answers using the set: field names — never ask the human to author raw JSON. This tool never publishes; use opentrain_publish_job.
Requires:
jobs:write + the public_api_job_drafting feature. Wraps: PATCH /job-drafts/{jobId}
opentrain_publish_job
Publish a draft live on the marketplace. Runs the same validation and moderation pipeline as the in-app publish flow and is subject to per-account daily publish limits. Returns the live job URL.
Requires:
jobs:write + the public_api_job_publishing feature. Wraps: POST /jobs/{id}/publish
opentrain_update_published_job
Update fields on a live published (OPEN) job. The revised listing is re-checked by moderation inline; if blocked, the job is automatically unpublished back to draft and the response explains what to fix. For unpublished drafts use opentrain_update_job_draft_fields instead.
Requires:
jobs:write + the public_api_job_publishing feature. Wraps: PATCH /jobs/{id}
opentrain_close_job
Close (archive) a published job so it stops accepting proposals and leaves public listings. Existing contracts are unaffected. Idempotent — closing an already-archived job reportsalreadyClosed.
Requires:
jobs:write + the public_api_job_publishing feature. Wraps: POST /jobs/{id}/close
opentrain_list_jobs
List the account’s own jobs (all statuses, newest first) with pagination.
Requires:
jobs:read. Wraps: GET /jobs/mine
opentrain_search_jobs
Search the public OpenTrain job marketplace — useful for calibrating rates and seeing how similar work is scoped before posting.
Requires: nothing — tokenless public read (120 requests/minute per IP). Wraps:
GET /jobs
Proposals and Candidates
opentrain_list_proposals
List proposals/candidates for a job with statuses, bids, AI interview scores, and resume match scores — the primary tool for reviewing and ranking who to hire. Useopentrain_get_proposal for one candidate in depth.
Requires:
proposals:read; the job must be yours. Wraps: GET /jobs/{id}/proposals
opentrain_get_proposal
Read a full proposal/candidate evaluation: status, bid, masked candidate, AI-interview score and summary, location/identity verification, labeling assessment, and contract state.
Requires:
proposals:read; the proposal must be on a job you own. Wraps: GET /proposals/{proposalId} (+ GET /proposals/{proposalId}/interview when includeInterview is true)
opentrain_get_freelancer_profile
Read a masked AI trainer profile for candidate evaluation: title, bio, skills, stats (earned, billed hours, job success), work and labeling experience, education, reviews, and languages. Names are masked to first name + last initial pre-hire, and personal contact details are never returned — see Privacy and Work Email.
Requires:
proposals:read. Wraps: GET /freelancers/{idOrSlug}
opentrain_invite_freelancer
Invite an AI trainer to a published job, creating a proposal they can respond to. Idempotent: re-inviting the same person returns the existing proposal withalreadyInvited: true.
Requires:
proposals:write + the public_api_hiring feature + a claimed account. Wraps: POST /jobs/{id}/invites
opentrain_hire_proposal
Request a hire from a proposal. Never hires anyone or moves money — records a pending approval (type: "proposal_hire") and returns 202 with an approvalUrl a signed-in human must confirm in the OpenTrain app. On confirm, OpenTrain creates the contract and funds the first escrow milestone (the human picks card or credits). A 409 with details.reason: "payment_method_required" includes a billingUrl; not_fit_confirmation_required means retry with confirmNotFitOverride: true if intentional; already_accepted means the proposal was already hired. Re-requesting with the same terms returns the same pending approval.
Requires:
proposals:write + the public_api_hiring feature + a claimed account + a payment method or covering credit balance. Wraps: POST /proposals/{proposalId}/hire
Messages
opentrain_read_messages
Read authorized conversation summaries or messages. OmitconversationId to list summaries; provide it to read messages. Never creates conversations or sends messages.
Requires:
messages:read; you only see conversations you participate in. Wraps: GET /messages
opentrain_send_message
Send a plain-text message into an existing conversation the token owner participates in. Runs the same membership, rate-limit, and content-policy checks as the in-app messaging flow. This tool never creates conversations — they come from proposals, invites, and hires.
Requires:
messages:write + the public_api_messaging_writes feature + a claimed account. Wraps: POST /messages
opentrain_start_proposal_conversation
Start (or fetch) the pre-hire direct-message thread for a proposal so you can message the candidate before hiring. Idempotent get-or-create; returns theconversationId to use with opentrain_send_message. Employer side only.
Requires:
messages:write + the public_api_messaging_writes feature + a claimed account. Wraps: POST /proposals/{proposalId}/conversation
Contracts and Milestones
opentrain_list_contracts
List contracts (hired AI trainers), each with milestones, the post-hire job DMconversationId, and the masked freelancer identity (first name + last initial).
Requires:
payments:read. Wraps: GET /contracts
opentrain_get_contract
Read one contract in detail: status, milestones with funding/approval state, AI trainer identity, the post-hire job DMconversationId, and the budget snapshot (funded vs consumed, state OK/LOW/DEPLETED).
Requires:
payments:read. Wraps: GET /contracts/{contractId}
opentrain_create_milestone
Create a new unfunded milestone on an existing contract. No money moves at creation — useopentrain_request_milestone_funding afterwards.
Requires:
payments:write + the public_api_payments_write feature + a claimed account. Wraps: POST /contracts/{contractId}/milestones
opentrain_request_milestone_funding
Request escrow funding for a milestone. This does not move money: it returns a pending approval with anapprovalUrl that a signed-in human must open and confirm (expires in ~72h) — the co-sign pattern. Watch opentrain_poll_updates for approval.confirmed, or re-check with opentrain_get_approval.
Requires:
payments:write + the public_api_payments_write feature + a claimed account + a payment method on file. Wraps: POST /milestones/{milestoneId}/fund
opentrain_request_milestone_approval
Request approval (payment release) of a funded milestone. Like funding, this only creates a pending human approval with anapprovalUrl (~72h expiry) — no money moves until the human confirms.
Requires:
payments:write + the public_api_payments_write feature + a claimed account. Wraps: POST /milestones/{milestoneId}/approve
opentrain_get_approval
Check the status of a pending human co-sign approval (milestone funding, release, or contract end):pending, confirmed, declined, or expired, plus the execution result once confirmed.
Requires:
payments:read. Wraps: GET /approvals/{approvalId}
opentrain_end_contract
End a contract. With no funded milestones it ends immediately; if funded escrow is at stake, the call instead returns a pending approval with anapprovalUrl a human must confirm — no funds move until then.
Requires:
payments:write + the public_api_payments_write feature + a claimed account. Wraps: POST /contracts/{contractId}/end
Credits
opentrain_get_credits
Read the prepaid credit balance: available, reserved (escrow holds), and total. No parameters. Requires:payments:read + the public_api_credits feature. Wraps: GET /credits
opentrain_list_credit_ledger
Page through the credit ledger — top-ups, escrow holds, hold releases, captures, refunds, and adjustments, newest first. Each entry links the related top-up, proposal, contract, or milestone ids.
Requires:
payments:read + the public_api_credits feature. Wraps: GET /credits/ledger
opentrain_create_credit_top_up
Start a credit top-up. No money moves from this call: it returns a Stripe CheckoutcheckoutUrl that a signed-in human must open and pay (expires in ~24h). Once paid, the balance updates automatically.
Requires:
payments:write + the public_api_credits feature + a claimed account. Wraps: POST /credits/top-ups
opentrain_get_credit_top_up
Check a top-up’s status:pending (awaiting human payment), completed (credits added), canceled, or expired.
Requires:
payments:read + the public_api_credits feature. Wraps: GET /credits/top-ups/{topUpId}
Updates
opentrain_poll_updates
Poll the delta feed of account events (new proposals, proposal status changes, new messages, contracts, milestone changes, pending payments, confirmed approvals, budget state changes) in one cheap call instead of re-reading every resource. Payloads carry IDs only — fetch details with the matching read tool. Event visibility follows the token’s scopes.
Requires: at least one of
proposals:read, messages:read, payments:read. Wraps: GET /updates
Webhooks
opentrain_create_webhook
Subscribe an HTTPS URL to platform events (push instead of polling). Deliveries are signed with HMAC-SHA256 — see Verify Webhook Signatures. The signing secret is returned once in this response; store it immediately. The subscription only receives events created after it.
Requires:
webhooks:manage + the public_api_webhooks feature + the matching read scope for each subscribed event type. Wraps: POST /webhooks
opentrain_list_webhooks
List all webhook subscriptions with URL, event types, and status. Signing secrets are never included. No parameters. Requires:webhooks:manage + the public_api_webhooks feature. Wraps: GET /webhooks
opentrain_get_webhook
Read one webhook subscription: URL, event types, status (ACTIVE or DISABLED), and failure/disable details. The signing secret is never returned — if lost, delete and re-create the subscription.
Requires:
webhooks:manage + the public_api_webhooks feature. Wraps: GET /webhooks/{webhookId}
opentrain_delete_webhook
Delete a webhook subscription and stop its deliveries. This is also how aDISABLED subscription is resumed: delete it and create a new one (which mints a new secret).
Requires:
webhooks:manage + the public_api_webhooks feature. Wraps: DELETE /webhooks/{webhookId}
Tokens
opentrain_list_tokens
List the account’s API tokens with masked previews, scopes, status, and last-used timestamps — secrets are never shown. No parameters. Requires: any valid token — token management needs no specific scope or feature flag. Wraps:GET /tokens
opentrain_revoke_token
Revoke an API token by id. Irreversible — the token stops working immediately.
Requires: any valid token — token management needs no specific scope or feature flag. Wraps:
DELETE /tokens/{tokenId}
Team
opentrain_get_team
Read the employer team: organization, members with roles, and pending email invites. No parameters. Requires:team:read + the public_api_team feature. Wraps: GET /team
opentrain_invite_team_member
Invite a human to the employer team by email, giving them shared access to jobs and the team inbox once they accept. Inviting an existing member returnsalready_member; users with existing accounts are added directly (member_added).
Requires:
team:write + the public_api_team feature + a claimed account. Wraps: POST /team/invites
Payments
opentrain_list_pending_payments
List pending payments on the account — read-only; never releases funds. No parameters. Requires:payments:read. Wraps: GET /payments/pending