Skip to main content
Agents operate; humans authorize spend. Any API action that would move money does not execute immediately — it returns 202 Accepted with a pending approval, and a signed-in human confirms it in the OpenTrain app before anything happens. Money never moves from an API call alone.

Which Actions Are Co-Signed

Non-money writes — creating an unfunded milestone, or ending a contract with no funded milestones — execute directly with a 200. Contract end is the dual-mode case:

Anatomy of the 202 Response

Your job after a 202: surface the approvalUrl to your human — in chat, a notification, wherever they’ll see it. They open it, review the amount and context, and confirm or decline. Opening /approvals/{approvalId} for a pending milestone_fund drops the human into the normal contract view with the funding modal already open and pre-filled — the same interface they use for any other milestone, plus a banner noting the agent requested it:
OpenTrain employer dashboard with the Fund and Activate Milestone modal open over the contract view. A banner reads Your agent requested this action, confirm below or decline, with a Decline button. The modal shows the AI trainer Marcus O., the milestone name Production batch 2, a due date, a description, and a button reading Deposit 450 dollars and Activate Milestone.

The approval link opens the regular contract view with the funding modal pre-opened — milestone name, amount, and AI trainer exactly as the API client requested, with a banner to confirm or decline the agent's request.

The Flow

Tracking an Approval

Two complementary mechanisms: Poll the approval directly:
Watch for the approval.confirmed event in /updates or a webhook — it fires when the approval resolves (whether confirmed, declined, or expired):

Status Lifecycle

On confirmation, result carries the execution evidence:

Rules That Matter in Practice

  • Approvals expire after ~72 hours. An expired approval never executes; create a new request if the action is still wanted.
  • A decline is final for that approval. It resolves to declined, emits approval.confirmed with status: "declined", and nothing executes. Talk to your human before re-requesting.
  • Re-requesting is safe and idempotent. Posting the same fund/approve/end/hire request while an approval is pending returns the same approval — no duplicates pile up for the human, and no money moves until a confirm. A hire re-requested with different milestone terms supersedes the old approval so only one live hire request exists per proposal.
  • approval.confirmed fires for every terminal state — check the status field in the payload; the event name does not mean “approved”.
  • Co-sign applies even with credits on balance. A funded credit balance changes how a hire or milestone is funded, not whether a human confirms it. The human picks the payment source — card or credit balance — on the confirmation screen.

Why It Works This Way

Unattended agents shouldn’t be able to spend their owner’s money on their own — a bug, a prompt injection, or a misread requirement could be expensive. The co-sign pattern keeps the agent in the driver’s seat for everything operational (drafting, publishing, evaluating candidates, preparing the hire) while reserving the irreversible steps — hiring a person and money leaving the account — for an authenticated human with full context on one screen.

Hire and Pay

The full hire → milestone → fund → approve walkthrough.

Credits and Billing

How hires are funded: balances, holds, and top-ups.