API reference

The API channel is one more messaging platform alongside Slack and Microsoft Teams: you authenticate with an API key, send the agent a message, and get her reply. The message runs through the same pipeline as a Slack message — the only difference is that the reply comes back on this HTTP surface.

Base URL and authentication

https://platform-gateway-3124114101.europe-west1.run.app/api/v1/api-channel

Every request passes your key as a bearer token. The person you act as is fixed by the key; the agent a conversation reaches is chosen when the conversation starts.

Authorization: Bearer ak_<keyId>_<secret>

Send the agent a message

POST/api/v1/api-channel/messages

Runs a normal agent turn — the same thing as messaging her in a channel. The reply is returned in the response when the turn finishes within the request's wait ceiling.

Request body

FieldRequiredMeaning
textrequiredWhat you want to say to the agent.
session_idoptionalConversation to continue — pass the session_id from a previous response and the agent sees the conversation's history, like a Slack thread. Omit to start a new conversation.
agent_idoptionalWhich agent a new conversation is with. Only needed when your account can message more than one agent — GET /api/v1/api-channel/agents lists your choices. A continued conversation keeps its agent.

Example

curl -X POST https://platform-gateway-3124114101.europe-west1.run.app/api/v1/api-channel/messages \
  -H "Authorization: Bearer ak_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "What is the status of the Q3 board update?"
  }'

Response

{
  "session_id": "3f9c2a1b8d",
  "status": "completed",
  "reply": "The Q3 board update is with finance for sign-off…"
}
StatusMeaning
completedThe reply is in this response, in reply.
processingThe agent is still working; poll the session messages for the reply.
queuedThe agent is busy with something else and will pick this up next; the reply will appear on the session messages.
duplicateThis exact message was just received and is already being handled.

Long-running turns

Turns can run long. If the agent is still working when the request's wait ceiling hits, the response comes back with status: "processing" and no reply — nothing is lost. The run continues, the reply lands on the session transcript, and you retrieve it with the endpoint below.

List the agents you can message

GET/api/v1/api-channel/agents

The valid values for agent_id — the agents your account can hold a conversation with. An account with exactly one agent never needs this: new conversations reach it automatically.

Response

{
  "agents": [
    { "agent_id": "324cd102-…", "name": "Ayven", "workspace_id": "ws_94ba9c…" }
  ]
}

Read a conversation's transcript

GET/api/v1/api-channel/sessions/{session_id}/messages

The transcript is the durable record of every turn — this is how a long-running reply is retrieved.

Query parameters

ParameterRequiredMeaning
afteroptionalA turn's ts; returns only newer turns, so a poller reads forward without re-downloading the whole conversation.
limitoptionalMaximum number of turns to return. Default 50.

Response

{
  "session_id": "3f9c2a1b8d",
  "status": "idle",
  "messages": [
    { "role": "user",  "text": "What is the status of the Q3 board update?", "ts": "…" },
    { "role": "agent", "text": "The Q3 board update is with finance for sign-off…", "ts": "…" }
  ]
}
StatusMeaning
idleThe latest turn is finished; the transcript holds the reply.
processingThe agent is still working on the latest message.
queuedThe latest message waits for the agent to free up.

Sessions are bound to their owner — a session id created by a different account returns 404, the same as a nonexistent one. Each session remembers which agent it is with.

Settle what the agent is waiting on

The agent gets blocked on you in two ways, and stays blocked until it is settled: an action she has drafted and needs permission for, and a question she is waiting on an answer to. Each has one endpoint to see it and one to settle it. Both settle endpoints take a list, so one call clears a queue; each entry reports its own outcome, so one invalid id does not fail the other entries.

GET/api/v1/api-channel/approvals

Actions awaiting your permission. Each carries the operation_id a decision names.

POST/api/v1/api-channel/approvals/decide
[
  { "operation_id": "op_1c4e…", "decision": "approve" },
  { "operation_id": "op_77af…", "decision": "reject", "reason": "wrong audience" }
]

decision is approve, approve_same_type (this one and every pending action of the same kind), or reject. A rejection re-plans the mission around your refusal, so a reason redirects the work where a bare no only stops it.

GET/api/v1/api-channel/asks

Open questions you can answer — ones put to you, and any on a mission you own, whoever she asked. Each carries the request_id an answer names.

POST/api/v1/api-channel/asks/answer
[
  { "request_id": "req_9b21…", "text": "Five thousand pounds, all in." }
]

The agent judges whether each reply answers what she asked. An answer can come back accepted: false with a reason naming what is still missing, and the question stays open — say the missing part rather than repeating yourself.

Read and move a ticket

Read and move any ticket in a tracker open to you, with your API key. An agent Ayven handed a ticket to uses its own two routes instead.

GET/api/v1/api-channel/tickets/{ticket_key}

One ticket in full — description, state, assignee, due date — from whichever tracker holds it.

POST/api/v1/api-channel/tickets/state/propose
{
  "ticket_key": "WEB-14",
  "target_state": "Done",
  "reason": "Pull request merged.",
  "comment": "Shipped in #482."
}

Nothing moves on this call. The move becomes an action awaiting the key owner's approval, settled under Settle what the agent is waiting on. target_state is a state the ticket's project has; any other is refused with the states it does have. comment is optional and is posted when the move runs.

Report back on a handed-over ticket

An agent Ayven handed a ticket to reports back on these two routes, with the token its call carried in report.token rather than an API key: Authorization: Bearer dt_…. The token opens only that ticket, and only while it stays handed to the agent, so neither route names a ticket.

GET/api/v1/api-channel/delegations/ticket

The handed-over ticket: summary, description, state, priority, due date and link, with states, every state it can move to, and last_proposal, the agent's last proposed move (null before the first):

"last_proposal": {
  "operation_id": "STATE_…",
  "target_state": "In Review",
  "proposed_at": "2026-11-02T14:05:00Z",
  "outcome": "rejected",
  "rejection_reason": "Tests are still red on main."
}

outcome is waiting_for_approval, approved (being made), applied, rejected (with the approver's rejection_reason), failed (approved, but the tracker refused it), closed (expired or withdrawn with no decision) or unreadable. A rejected move leaves the ticket handed to the agent.

POST/api/v1/api-channel/delegations/ticket/state/propose
{
  "target_state": "In Review",
  "reason": "Pull request opened.",
  "comment": "See #482."
}

Nothing moves on this call. The move waits for the approval of the person who approved the ticket (or who made it on the board, or the agent's owner), and the answer says whether it is still waiting. target_state is a state the ticket's project has; any other is refused with the states it does have. reason and comment are each at most 2,000 characters; a longer one is refused with 422. comment is optional and is posted under your agent's name when the move runs.

A token that is malformed, unknown, revoked, expired, or whose ticket is no longer handed over gets the same 401. An approved move out of In Progress ends the hand-over, so after an approval that 401 means the move landed. Each hand-over has its own rate limit; past it, calls get 429.

Create an agent

POST/api/v1/api-channel/agents

For an account that does not have one yet — nothing can be messaged until it does. Takes agent_name, and optionally a workspace_id to add the agent to a workspace you own or administer. Free accounts include one agent.

Rate limits and errors

Each key has its own per-minute rate limit, set when the key is created and shown on its row in the app.

CodeMeaning
401Missing, malformed, unknown, revoked, expired, or inactive API key.
404The session doesn't exist or belongs to a different account; or the chosen agent isn't available to you.
422The message text is empty, or your account can message several agents and no agent_id was given.
429The key's per-minute rate limit was exceeded.
502The agent could not process the message.