Skip to content

HTTP API

Anything that can POST JSON can hold a conversation. Start a session:

bash
curl -X POST "$TOREN_URL/sessions" \
  -H "Authorization: Bearer $TOREN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"agent": "research_crew", "message": "Hi! What can you do?"}'

The response is {"runId": "...", "agent": "research_crew"}. The body also accepts channel (a free-form label like "cli" or "telegram" that tags each turn in the transcript), on session start and on every message. Read the transcript and state with GET /sessions/:id; the state is working, awaiting_input, completed, failed, or cancelled. Send the next turn:

bash
curl -X POST "$TOREN_URL/sessions/$RUN_ID/messages" \
  -H "Authorization: Bearer $TOREN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message": "Tell me more."}'

Turn-taking is strict: sending while the agent is mid-turn returns 409, so wait for awaiting_input. Pass {"close": true} to end the session. GET /sessions lists recent conversations across every channel.

The typed client wraps all of this:

ts
import { TorenClient } from "@toren-run/client";

const client = new TorenClient({ url: process.env.TOREN_URL, token: process.env.TOREN_TOKEN });
const { runId } = await client.startSession({ agent: "research_crew", message: "Hi!" });
const session = await client.getSession(runId);          // state + transcript
await client.sendSessionMessage(runId, { message: "Tell me more." });

Sessions are one corner of the API; runs, approvals, schedules, and keys are covered in the HTTP API guide.