pk_live_… key from your Widget (API) channel authorizes direct calls to the agent’s sessions API — durable conversations with an event stream, questions and approvals the agent can raise, and session controls. The web widget uses exactly this API under the hood.
- Base:
https://agents.juryo.ai - Authentication:
Authorization: Bearer pk_live_…header
Which API?
Both use the same key. Pick by what your integration needs:
If you don’t need the session controls, use the Chat API.
The key identifies your firm as the tenant. Any system presenting it can start conversations with your agent — the same way any visitor to your site can open the widget.
Routes
The session routes use only durable session IDs. Create a session explicitly, then put its returned ID in every follow-up, control, and stream path.
Start a session
sessionIdis the session’s permanent handle. Store it — it goes in the URL path of every later call. The same id is also echoed in thex-eve-session-idresponse header.status: "accepted"means the message was durably queued. The agent’s reply is not in this response — read it from the event stream.
Send a follow-up message
When the session is waiting for the next user message:message or inputResponses. Use inputResponses to answer a pending question or approval request the agent raised (an input.requested event on the stream):
409 with {"code": "session_not_active", "error": "The session is no longer active.", "ok": false}. The route never creates a replacement session — start a new one explicitly with POST /eve/v1/session.
Stream the reply
The session emits newline-delimited JSON events (application/x-ndjson) while the agent works — one JSON object per line:
message.completed— the agent’s full reply for that turn.session.waiting— the turn is finished and the session is ready for your next follow-up.input.requested— the agent is asking the caller a question or requesting an approval; answer it withinputResponseson the follow-up route.turn.failed/session.failed— the turn or session errored;data.messagecarries the reason.
*.appended events and rely on the *.completed ones.
For backwards compatibility, the
session.waiting event still carries a data.continuationToken field. It is simply the session ID — ignore it and keep using the sessionId you already have.Manage a session
All control routes are asynchronous:"accepted" means the request was durably queued, and the outcome is confirmed on the event stream. They never create sessions — an inactive session ID returns "no_active_session" (or "no_active_turn" for cancel).
Cancel the in-flight turn (empty body, or pass the turnId from that turn’s stream events to scope it):
Errors
Error bodies follow
{"code": "...", "error": "...", "ok": false} with a stable code for programmatic handling.
Migrating from continuation tokens
Integrations built before August 2026 used acontinuationToken returned by the start route. The mapping to the current API:
In short: keep the
sessionId from the start response, put it in the URL path, and remove continuationToken from every request body.
