Quickstart
From your credentials to a live, scored roleplay call in about 15 minutes.
This walks through the entire loop: create an agency, register a rep into it, mint a token, start a
live call from the browser, receive the call.scored webhook, and read the score. Every REST call is server-to-server —
keep your API key on your backend.
Base URL: https://app.useathos.ai/api/external/v1. Paths in these docs are written /v1/…
— POST /v1/session means POST https://app.useathos.ai/api/external/v1/session. You'll get an
API key from your Athos contact — see Authentication.
Get your credentials
There's no self-serve signup — setup is a quick coordination with the Athos team. You give us one thing, and we send you two:
You provide: your HTTPS webhook URL (where call.scored events should be delivered).
Athos sends you (each shown once — store both as backend secrets):
- an API key (
ath_live_…) →ATHOS_API_KEY - a webhook signing secret (
whsec_…) →ATHOS_WHSEC
We register your webhook URL on our side and start delivering events to it. Keep both secrets server-side — the API key never goes near a browser.
Developing on a laptop? Expose your local handler with a tunnel (ngrok, cloudflared) and give
us that URL — you can change it later. No URL yet? Skip the webhook for now and read the score
with GET /v1/calls/:callId in the last step; events are not queued for later delivery. See
Registering your endpoint.
Your key is a live key: every call runs against the real service and is billed. Keep test data apart by creating a dedicated test agency and registering test reps into it.
Create the agency (backend, once per customer)
An agency is one of your customers — a group of reps. Create it under your own id for it
before you register its first rep. The same call renames it later (200 instead of 201), so it
is safe to repeat.
curl -X POST https://app.useathos.ai/api/external/v1/agencies \
-H "Authorization: Bearer $ATHOS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"platformAgencyId":"acme-7731","name":"Acme Senior Solutions"}'
# → 201 { "id": "athos_agency_…", "name": "Acme Senior Solutions", "platformAgencyId": "acme-7731", … }Register the rep (backend, once per person)
A session token is only minted for a registered agent, so register each rep once — with your
own id for them, into the agency you just created — before their first practice call. Registration
never creates an agency: a platformAgencyId you have not created is 404 AGENCY_NOT_FOUND.
curl -X POST https://app.useathos.ai/api/external/v1/agents \
-H "Authorization: Bearer $ATHOS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"firstName":"Dana","lastName":"Reyes","platformAgentId":"rep_8842","platformAgencyId":"acme-7731"}'
# → 201 { "agent": { "id": "athos_agent_…", … }, "agency": { "id": "athos_agency_…", … } }Registering twice is a 409 AGENT_ALREADY_EXISTS whose error.details carries the existing ids.
Details on Managing agencies and agents.
Mint a session token (backend)
Your backend exchanges its API key for a short-lived, single-use session token scoped to one
registered rep — minted by the rep's platformAgentId or Athos agentId. Expose this as your own
endpoint (e.g. POST /athos/token) that your frontend can call.
curl -X POST https://app.useathos.ai/api/external/v1/session \
-H "Authorization: Bearer $ATHOS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"platformAgentId":"rep_8842"}'
# → { "token": "eyJhbGci…", "expiresAt": "2026-06-05T18:05:00.000Z" }Node and Python versions of that endpoint are on Minting session tokens.
Mint the token at the moment the rep clicks "start practice", not on page load. It's single-use and lives ~5 minutes.
Install the SDK
npm install @useathos/sdkStart the call (frontend)
Roleplay calls run on desktop Chromium-based browsers (Chrome, Edge, Brave, Opera, …) and
desktop Firefox only — create() throws BROWSER_NOT_SUPPORTED on anything else, so call it
on the client and check first. The page must be served over HTTPS (or localhost), or the
browser withholds the microphone. See Requirements.
drillKey picks the scenario — ma-full-sale here is a full Medicare Advantage enrollment; the
catalog covers Medicare Advantage, Medicare Supplement, Final Expense, under-65 health, Hospital
Indemnity and Critical Illness, see Drills. create() is synchronous, so
register handlers before connect() — nothing is missed.
import { AthosRoleplay } from '@useathos/sdk';
const r = await fetch('/athos/token', { method: 'POST' });
if (!r.ok) throw new Error((await r.json()).error.code); // e.g. TENANT_QUOTA_EXCEEDED
const { token } = await r.json();
const session = AthosRoleplay.create({ token, drillKey: 'ma-full-sale' });
session.on('ready', ({ persona }) => console.log(`${persona.name} is ready`));
session.on('ended', ({ callId, durationSec }) => console.log('ended', callId, durationSec));
session.on('error', ({ code, message }) => console.error(code, message));
await session.connect(); // joins the call; the AI persona starts speaking
endCallButton.onclick = () => session.disconnect();The persona never hangs up — build an "End call" button. A call runs until you call
disconnect(), until the two-hour ceiling, or until the network drops, so an abandoned tab runs
(and bills) the full two hours. See How a call ends.
Talk to the persona for a minute or two before you hang up — a call on which the rep never speaks
is not scored (the webhook arrives with success: false).
That's the whole frontend. See the SDK guide for events, microphone control, and browser detection.
Receive the call.scored webhook (backend)
call.scored typically arrives within a minute or two of the call ending. Athos POSTs a small,
signed payload to your registered URL:
{
"event": "call.scored",
"success": true,
"callId": "athos_call_GZ1DjOkZv_VEPoE-CJ8mp",
"source": "roleplay",
"agentId": "athos_agent_bR4kQ2wZ9Lp0nH3xVq1Yt",
"agencyId": "athos_agency_V1StGXR8Z5jdHi6B-myT",
"platformAgentId": "rep_8842",
"platformAgencyId": "acme-7731",
"occurredAt": "2026-06-05T18:09:14.000Z",
"requestId": "req_b1f0…"
}Your handler does three things: verify the signature over the raw request body (parsing and
re-serializing changes the bytes and breaks the check), answer 2xx fast, then fetch the score
afterwards. Copy a verifier — Node or Python — from
Webhooks.
success is false when the call could not be scored — there is no score to fetch for it. Retries
reuse the same X-Athos-Webhook-Id, so treat that header as your idempotency key. If nothing has
arrived 30 minutes after the call ended, read GET /v1/calls/:callId directly.
Read the score (backend)
curl https://app.useathos.ai/api/external/v1/calls/athos_call_GZ1DjOkZv_VEPoE-CJ8mp \
-H "Authorization: Bearer $ATHOS_API_KEY"The response includes the transcript (a list of speaker-labelled turns) and the score object
(overallScore, summary, and feedback). See Reading calls.
You're done
You've run the full loop. Next: