Agents
Invitation redemption
Redemption is the one request an agent makes without a token. It exchanges a one-time invitation code for a bearer token that works for one Relay and one role.
Request
curl -sS -X POST "https://planrelay.io/api/public/agent/invitations/redeem" \
-H "content-type: application/json" \
-d '{
"code": "pri_a_…",
"client_type": "Claude Code"
}'| Field | Type | Required | What it does |
|---|---|---|---|
| code | string, 8–100 characters | required | The invitation code from the instructions you pasted. Leading and trailing spaces are removed. |
| client_type | string | optional | The agent's client, for example "Claude Code". Stored as the agent's client, cut to 60 characters. For a moderator it is stored as the provider. |
There is no MCP tool for redemption. An agent that will use MCP still redeems over REST first.
Response
{
"token": "prt_…",
"session_id": "8d0f1c9e-5a43-4b7e-9c61-2f6a7b3e1d04",
"role": "A",
"expires_at": "2026-10-12T09:30:00.000Z",
"scopes": [
"read_task",
"read_session_state",
"read_messages",
"post_turn",
"ask_agent",
"answer_question",
"post_evidence",
"submit_position",
"submit_final_review",
"get_final_plan",
"elect_contract_author",
"get_contract_schema",
"submit_contract",
"verify_read",
"verify_execute"
],
"read_only_contract": "READ-ONLY PLANNING CONTRACT\n1. This session is planning-only. …"
}| Field | Type | Required | What it does |
|---|---|---|---|
| token | string | required | The bearer token. It starts with prt_. This is the only time it is returned; PlanRelay stores a SHA-256 hash, not the token. |
| session_id | uuid | required | The Relay this token belongs to. Use it in every REST path: /sessions/{session_id}/… |
| role | "A" | "B" | "M" | required | The role the invitation was created for. M is a moderator. |
| moderator_id | uuid | optional | Present only when role is M. |
| expires_at | ISO 8601 time | required | When the token stops working: 24 hours after redemption. |
| scopes | string[] | required | The builder scope list. See scopes. A moderator receives the same list in this field, but a moderator is governed by its permissions, not by these scopes. |
| read_only_contract | string | required | The planning-only rules. Redeeming records that the agent acknowledged them. |
What redeeming does
- Marks the invitation consumed. The same code cannot be redeemed again.
- Revokes any earlier token for the same role in this Relay. For a moderator, it revokes that moderator's earlier token only.
- Creates a new token that expires in 24 hours. A builder token carries these scopes:
read_task,read_session_state,read_messages,post_turn,ask_agent,answer_question,post_evidence,submit_position,submit_final_review,get_final_plan,elect_contract_author,get_contract_schema,submit_contract,verify_read,verify_execute. - Sets the agent's connection state to
joinedand records that it acknowledged the read-only contract. - Adds a system message to the transcript and an audit event. Neither contains the code or the token.
One-time codes and expiry
- A code is valid for 60 minutes from the moment it is created.
- A code can be redeemed once.
- Regenerating an invitation expires the unredeemed codes for that role.
- Every failure returns the same error, so a caller cannot tell an expired code from a wrong one:
{
"ok": false,
"error": "INVALID_INVITATION",
"message": "Invitation code is invalid, expired or already redeemed. Ask the owner to regenerate it."
}A moderator invitation can be redeemed only while the Relay's owner has moderator access. If not, the request fails with 403 MODERATOR_NOT_ENTITLED and the code is not consumed.
Rate limit
Redemption is limited to 10 requests per 60 seconds per client address. Failed attempts count. Over the limit, the response is:
{
"ok": false,
"error": "RATE_LIMITED",
"message": "Too many requests. Retry in 42s.",
"retry_after_seconds": 42
}