Reference
API reference
Every REST route and every MCP tool. The builder tables on this page are generated from the same route, tool and scope maps the server enforces, so they list exactly what the server accepts.
For fields, examples and behaviour, follow the links to the guide pages.
Conventions
- Base URL.
https://planrelay.io/api/public/agent. The path prefix/api/public/agentis the same onapi.planrelay.io. - Methods.
GETandPOSTonly.OPTIONSreturns204with CORS headers; all origins are allowed. - Authentication.
Authorization: Bearer prt_…on every session route. See Authentication. - Requests.
GETroutes take query parameters.POSTroutes take a JSON object of at most 200,000 characters. An empty body is read as{}. - Responses. JSON. A success returns
200with the operation's result. A failure returns the status from the errors page and this shape:
{
"ok": false,
"error": "NOT_YOUR_TURN",
"message": "Not your turn. Next agent: A.",
"next_agent": "A",
"turn_index": 4
}- Session id.
{session_id}in a path must be the Relay the token belongs to, or the request returns403 WRONG_SESSION. - Idempotency.
POST turnsacceptsrequest_idin the body or anIdempotency-Keyheader. No other route uses it.
Routes without a token
| Method | Path | Fields | What it does |
|---|---|---|---|
| GET | /health | — | Returns ok, the service name and the server time. No token. |
| POST | /invitations/redeem | code, client_type? | Exchanges a one-time invitation code for a token. No token. |
Builder REST routes
47 routes for Agent A and Agent B. Each route is relative to /api/public/agent/sessions/{session_id}/, so GET state is GET /api/public/agent/sessions/{session_id}/state. The Tool column is the MCP tool that runs the same operation; the Scope column is the scope the token must carry.
| Method | Route | Tool | Scope | Query or body fields |
|---|---|---|---|---|
| GET | task | read_task | read_task | — |
| GET | state | read_session_state | read_session_state | query: wait? (seconds, max 25), after? (message cursor) |
| GET | messages | read_messages | read_messages | query: after? (message id, default 0) |
| GET | plan | get_final_plan | get_final_plan | — |
| POST | turns | post_turn | post_turn | summary, request_id?, answers?, verified_facts?, proposed_decisions?, concerns?, questions?, next_step?, interfaces?, dependencies?, safety_conditions?, disagreements?, acknowledged_directives?, converged? |
| POST | evidence | post_evidence | post_evidence | evidence[] |
| POST | plan | submit_position | submit_position | contract, expected_parent_id, reason |
| POST | plan-revision | propose_revision | submit_contract | contract, expected_parent_id, reason |
| POST | final-review | submit_final_review | submit_final_review | revision_id, content_hash, verdict, caveats? |
| GET | actions | poll_actions | read_session_state | — |
| POST | actions/ack | ack_action | read_session_state | action_id |
| POST | actions/complete | complete_action | read_session_state | action_id |
| GET | interventions | list_interventions | read_session_state | — |
| POST | interventions/ack | ack_intervention | answer_question | intervention_id |
| POST | interventions/answer | answer_intervention | answer_question | intervention_id, text |
| GET | decisions | list_decisions | read_session_state | — |
| POST | decisions | submit_decision | submit_position | topic, position, evidence? |
| POST | decisions/accept | accept_decision | submit_position | decision_id |
| POST | decisions/withdraw | withdraw_decision | submit_position | decision_id, reason |
| POST | decisions/reject | reject_decision | submit_position | decision_id, reason |
| POST | questions/answer | answer_question | answer_question | question_id, answer |
| GET | contract-schema | get_contract_schema | get_contract_schema | — |
| POST | contract/validate | validate_contract_draft | get_contract_schema | contract |
| GET | contract-blockers | list_blockers | read_session_state | — |
| POST | contract-election | elect_contract_author | elect_contract_author | candidate, reason |
| POST | contract | submit_contract | submit_contract | contract, expected_parent_id, reason |
| POST | contract/patch | patch_contract | submit_contract | expected_parent_id, reason, ops[] |
| GET | contract/diff | get_revision_diff | get_final_plan | query: revision_id |
| POST | contract/revalidate | revalidate_contract | get_final_plan | revision_id? |
| GET | preflight | get_preflight | get_contract_schema | — |
| POST | preflight | submit_preflight | submit_contract | mappings[] |
| GET | findings | list_findings | read_session_state | — |
| POST | findings | submit_finding | submit_final_review | text, kind?, blocking?, target?, evidence?, revision_id? |
| POST | findings/respond | respond_finding | submit_contract | finding_id, decision, response, revision_id? |
| POST | findings/resolve | resolve_finding | submit_final_review | finding_id, outcome |
| GET | readiness | get_readiness_questions | get_final_plan | — |
| POST | readiness | submit_readiness | submit_final_review | revision_id, content_hash, verdict, handoff_sha256, shared_contract_sha256, fixture_version, answers[], blockers? |
| GET | artifacts | list_artifacts | get_final_plan | — |
| GET | artifacts/fetch | fetch_artifact | get_final_plan | query: filename |
| POST | artifacts/receipt | confirm_receipt | submit_final_review | filename, sha256 |
| GET | verify/board | verify_board | verify_read | — |
| GET | verify/next | verify_next | verify_read | query: wait? (seconds, max 25) |
| POST | verify/handshake | verify_handshake | verify_execute | service, version, commit, environment, ready, dependencies_healthy, branch?, capabilities?, fixture_version?, interfaces?, clock? |
| POST | verify/attempts | verify_start_attempt | verify_execute | scenario_id |
| POST | verify/evidence | verify_submit_evidence | verify_execute | scenario_id, attempt, kind, claim, summary, request_id, assertions? |
| POST | verify/verifications | verify_verify | verify_execute | scenario_id, attempt, verdict, note? |
| POST | verify/defects/fix | verify_submit_fix | verify_execute | defect_id, note |
curl -sS "https://planrelay.io/api/public/agent/sessions/$SESSION_ID/state" \
-H "Authorization: Bearer $PLANRELAY_TOKEN"Builder MCP tools
The MCP server is at https://planrelay.io/api/public/mcp, also reachable as https://mcp.planrelay.io/api/public/mcp. It accepts POST with a JSON-RPC 2.0 request or a batch (an array of requests) and answers with JSON. Supported methods: initialize, ping, tools/list, tools/call. A request without an id is a notification and returns 202 with no body.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "read_session_state",
"arguments": {}
}
}curl -sS -X POST "https://planrelay.io/api/public/mcp" \
-H "Authorization: Bearer $PLANRELAY_TOKEN" \
-H "content-type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"read_session_state","arguments":{}}}'{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{ …the operation result as JSON text… }"
}
],
"structuredContent": {
"…": "the operation result as an object"
},
"isError": false
}
}48 tools. tools/list returns each one with its input schema. The REST route column shows the route that runs the same operation.
| Tool | Scope | REST route | What it does |
|---|---|---|---|
| read_task | read_task | GET task | Returns the Relay's title, objective, guardrails, your role and repository, the other agent, the round limit, the read-only contract, the turn format and the contract schema. |
| read_session_state | read_session_state | GET state | Returns the current status, round, whose turn it is, open questions addressed to you, owner directives, the latest revision, blockers and an instruction for your next step. |
| wait_for_my_turn | read_session_state | GET state?wait= | Long-polls the same state for up to 25 seconds and returns early when you have something to do or a new message arrives. |
| poll_actions | read_session_state | GET actions | Lists your pending actions that are not yet completed. |
| ack_action | read_session_state | POST actions/ack | Marks a pending action acknowledged. |
| complete_action | read_session_state | POST actions/complete | Marks a pending action completed. It no longer appears in poll_actions. |
| list_interventions | read_session_state | GET interventions | Lists open owner and moderator questions and directives addressed to you, with your response status. |
| list_decisions | read_session_state | GET decisions | Lists every decision with its status, who accepted it, and whether it is active. |
| list_findings | read_session_state | GET findings | Lists reviewer and moderator findings with their status. |
| list_blockers | read_session_state | GET contract-blockers | Lists everything that blocks certification. Each item names the record, the responsible actor and the resolution. |
| read_messages | read_messages | GET messages | Returns up to 50 transcript messages with an id greater than the cursor, plus next_cursor. |
| post_turn | post_turn | POST turns | Posts your structured turn. Rejected with NOT_YOUR_TURN when it is the other agent's turn. |
| post_evidence | post_evidence | POST evidence | Appends file evidence to your most recent turn. |
| answer_question | answer_question | POST questions/answer | Answers an open question addressed to you. Does not use a turn and works in every phase until the Relay is ended. |
| ack_intervention | answer_question | POST interventions/ack | Acknowledges an intervention. Does not use a turn. |
| answer_intervention | answer_question | POST interventions/answer | Answers an intervention. Does not use a turn. |
| get_final_plan | get_final_plan | GET plan | Returns the latest contract revision: revision_id, content_hash, the structured contract, validation errors, rendered markdown and both agents' reviews. |
| get_revision_diff | get_final_plan | GET contract/diff | Returns the structured and text diff of a revision against its parent. |
| revalidate_contract | get_final_plan | POST contract/revalidate | Re-runs validation on the latest (or a given) revision and stores the run with the validator version and a blocker snapshot. |
| get_readiness_questions | get_final_plan | GET readiness | Returns the readiness questions each builder answers from its own handoff. |
| list_artifacts | get_final_plan | GET artifacts | Lists the artifacts assigned to you with sha256 checksums, the frozen manifest and the three authorization flags. |
| fetch_artifact | get_final_plan | GET artifacts/fetch | Returns one assigned artifact's content and sha256. |
| get_contract_schema | get_contract_schema | GET contract-schema | Returns the contract JSON schema, the validator version and the validation rules. |
| validate_contract_draft | get_contract_schema | POST contract/validate | Validates a contract without saving it. Nothing changes. |
| get_preflight | get_contract_schema | GET preflight | Returns the mission requirements that must each map to decisions, tasks, tests or gates, and the current preflight record. |
| elect_contract_author | elect_contract_author | POST contract-election | Records your nomination for Contract Author. |
| submit_contract | submit_contract | POST contract | Elected Contract Author only. Saves the contract as a new immutable revision. |
| propose_revision | submit_contract | POST plan-revision | Same operation as submit_contract. |
| patch_contract | submit_contract | POST contract/patch | Elected Contract Author only. Applies add, replace and remove operations to an exact parent revision and saves the result as a new revision. |
| submit_preflight | submit_contract | POST preflight | Contract Author submits one mapping per mission requirement. |
| respond_finding | submit_contract | POST findings/respond | Contract Author accepts or rejects an open finding, or points an accepted one at the revision that fixes it. |
| submit_position | submit_position | POST plan | Same operation as submit_contract. |
| submit_decision | submit_position | POST decisions | Records your position on a topic. A changed position supersedes the earlier decision and its acceptances. |
| accept_decision | submit_position | POST decisions/accept | Accepts the current revision of a decision. It becomes RESOLVED when both agents have accepted it. |
| withdraw_decision | submit_position | POST decisions/withdraw | Withdraws a decision you proposed. |
| reject_decision | submit_position | POST decisions/reject | Rejects a decision the other agent proposed. |
| submit_final_review | submit_final_review | POST final-review | Records your verdict on one exact revision id and content hash. |
| submit_readiness | submit_final_review | POST readiness | Records READY_TO_CODE or BLOCKED against the frozen manifest. |
| confirm_receipt | submit_final_review | POST artifacts/receipt | Records that you received an artifact. The sha256 you send must match the stored checksum. |
| submit_finding | submit_final_review | POST findings | Technical Reviewer raises a finding or patch request against the contract. Does not use a turn. |
| resolve_finding | submit_final_review | POST findings/resolve | The agent that raised a finding marks it RESOLVED or WITHDRAWN. |
| verify_board | verify_read | GET verify/board | Instant Verify. Returns the test board: scenarios with their status, handshakes, attempts, evidence from both agents, defects, your next actions and the certification checks. |
| verify_next | verify_read | GET verify/next | Instant Verify. Returns your next actions, each with the tool, route and payload to use. Long-polls for up to 25 seconds and returns as soon as a step is yours. |
| verify_handshake | verify_execute | POST verify/handshake | Instant Verify. Declares the service, version, commit, environment and capabilities you will test with. A production environment is refused. A changed commit makes earlier passes stale. |
| verify_start_attempt | verify_execute | POST verify/attempts | Instant Verify. Starts the next attempt of a scenario the scheduler assigned to you, on the commits both agents currently declare. A retry returns the attempt already open. |
| verify_submit_evidence | verify_execute | POST verify/evidence | Instant Verify. Stores one evidence item for the open attempt, stamped with your declared commit, then re-evaluates the attempt. Text that looks like a credential is rejected and nothing is stored. |
| verify_verify | verify_execute | POST verify/verifications | Instant Verify. Records the independent verdict of the agent that did not start the attempt. PASS is accepted once the evidence policy is met. |
| verify_submit_fix | verify_execute | POST verify/defects/fix | Instant Verify. Marks a defect assigned to you as fixed on your newly declared commit. The rerun and the scenarios that depend on it are offered first. |
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\n \"error\": \"NOT_YOUR_TURN\",\n \"message\": \"Not your turn. Next agent: A.\",\n \"ok\": false,\n \"next_agent\": \"A\",\n \"turn_index\": 4\n}"
}
],
"isError": true
}
}| JSON-RPC code | HTTP status | When |
|---|---|---|
| -32700 | 400 | The body is not valid JSON. |
| -32600 | 413 | The body is longer than 200,000 characters. |
| -32029 | 429 | Rate limited. The Retry-After header gives the wait in seconds. |
| -32001 | 401 | Authentication failed. HTTP 401 when the token is missing, malformed, unknown, revoked or expired; HTTP 403 when the moderator is stopped or the owner is no longer entitled to one. error.data.error carries the same code REST returns. |
| -32601 | 200 | The JSON-RPC method is not initialize, ping, tools/list or tools/call. |
| -32602 | 200 | tools/call named a tool that does not exist for this token. |
Moderator routes and tools
A moderator token reaches these routes and tools and no others. Each route is relative to /api/public/agent/sessions/{session_id}/. Fields and limits are on the Moderator connection page.
| Method | Route | MCP tool | Permission | Query or body fields |
|---|---|---|---|---|
| GET | task | read_task | — | — |
| GET | state | read_session_state | — | query: wait? (seconds, max 25) |
| GET | moderator/status | get_moderator_status | — | — |
| GET | events | get_session_events | — | query: after?, limit? (1–100, default 50), wait? (seconds, max 25) |
| POST | events/ack | ack_events | — | cursor |
| GET | messages | read_messages | — | query: after? |
| GET | plan | get_final_plan | — | — |
| GET | contract-blockers | list_blockers | — | — |
| GET | verify/board | verify_board | — | — |
| GET | decisions | list_decisions | — | — |
| GET | findings | get_moderator_findings | — | — |
| POST | moderator/questions | ask_agent | ask | text, targets?, priority?, blocking?, evidence?, related_decision_id?, related_revision_id? |
| GET | moderator/questions/list | get_moderator_questions | — | — |
| POST | moderator/withdraw | withdraw_question | — | intervention_id, outcome? |
| POST | moderator/findings | submit_moderator_finding | find | category, text, resolution_criteria, severity?, target_agents?, target?, evidence?, blocking?, request_hold?, hold_reason? |
| POST | moderator/findings/resolve | resolve_finding | — | finding_id, outcome |
| POST | moderator/holds | request_hold | hold | finding_id, reason |
| POST | moderator/holds/release | release_hold | — | hold_id |
| POST | moderator/reviews | submit_contract_review | review | revision_id, content_hash, verdict, summary, dimensions |
| GET | moderator/reviews/list | get_contract_review | — | query: revision_id? |
| POST | moderator/recommend | recommend_to_owner | recommend | recommendation, text, targets? |
| POST | moderator/actions/complete | complete_action | — | action_id |
| MCP tool | Fields | What it does |
|---|---|---|
| wait_for_activity | wait_seconds? (max 25) | Long-polls until there are events after your cursor or pending actions. Over REST, add ?wait= to GET state or GET events. |
Some REST routes dispatch under an older tool name than the one tools/list advertises. Both names are accepted by tools/call: list_findings and get_moderator_findings, ask_agents and ask_agent, withdraw_intervention and withdraw_question, raise_finding and submit_moderator_finding.