Core concepts
Tenancy, identifiers, drills and personas, the call lifecycle, and call sources.
A few ideas show up everywhere in this API. Read this once and the rest of the docs will read faster.
Tenancy: you, your agencies, your agents
Your Athos account is a single tenant. Everything you create — agencies, agents, calls, scores, usage — belongs to your tenant, and the API only ever returns your tenant's data. Your API key is the tenant boundary.
Within your tenant, Athos keeps a roster, maintained entirely through this API:
- An agency is one of your customers — a group of reps. You create it first, under your own
id for it (
platformAgencyId), and the same call renames it later. - An agent is a rep. Each agent belongs to exactly one agency — named at registration by your
platformAgencyIdor the AthosagencyId— and is registered once, with at least one handle: their NPN (National Producer Number), their email, or your own id for them (platformAgentId). Registration never creates an agency.
Every call is attributed to one agent and one agency, so you can read calls back by agency and by rep. A rep must be registered before their first roleplay: a session token is only minted for a registered agent. See Managing agencies and agents.
Scoping by agencyId or agentId is checked against your roster (someone else's id is a
404), but that is tenant isolation, not per-agency access control: anyone with your API key can
read every call in your tenant. If you run a multi-agency product, enforce per-agency access
in your own backend.
Two id families
Every agent, agency, call and call.scored delivery carries two families of id for the same rep
and agency, under the same names everywhere:
- Ours —
agentId/agencyId(andcallId): the Athos ids the roster calls returned. Always present. Pass them back as?agentId=/?agencyId=onGET /v1/calls,agentIdon the mint, andagencyIdonPOST /v1/agents. - Yours —
platformAgentId/platformAgencyId: the ids you registered, echoed back on every object —platformAgencyIdis the id you created the agency with,platformAgentIdthe one you registered the rep under. Either isnullwhen you never gave one (a rep registered withoutplatformAgentId) — join onagentId/agencyIdin that case.
Your own ids may not begin with athos_agent_ or athos_agency_, and each is unique within your
tenant.
Identifiers
| Id | Looks like | What it is |
|---|---|---|
agencyId | athos_agency_V1StGXR8… | An agency of yours. Returned by POST /v1/agencies (and echoed at registration); use it to register agents into the agency (or use your own platformAgencyId) and for GET /v1/calls?agencyId=. |
agentId | athos_agent_bR4kQ2wZ… | A rep. Returned at registration; look the rep up with GET /v1/agents?agentId=, mint with it, and list their calls with GET /v1/calls?agentId=. |
callId | athos_call_GZ1DjOkZv_… | A call. Use it for GET /v1/calls/:callId; it is the callId in webhooks and in the SDK ended event. |
requestId | req_2f8c1e94-… | Returned on every API response as the X-Athos-Request-Id header. Quote it in support tickets. |
All four are opaque and stable. A resource returns its own id as id and refers to another
resource as <resource>Id (an agent's agencyId, for example).
Every timestamp in the API and the webhook is ISO 8601 in UTC (2026-06-05T18:09:14.000Z).
from / to bounds are inclusive.
Drills and personas
A drill is the scenario a rep practices — a full Medicare Advantage enrollment
(ma-full-sale), a Final Expense close (fe-closing), a Hospital Indemnity cross-sell
(hi-crosssell), and so on across six product lines. You pass its key as drillKey when you
create a session. A persona is the AI customer the rep talks to on that call; Athos picks one
for the drill, and you can nudge the choice with difficulty and filters. The full catalog is
on Drills.
The call lifecycle
created ──▶ live (rep + AI persona talk) ──▶ ended ──▶ scoring
│
┌─────────────────────────────────┴───┐
▼ ▼
scored not scored
│ │
┌───────────┴───────────────┐ ▼
▼ ▼ call.scored (success: false)
call.scored (success: true) GET /v1/calls[/:callId]Every call that ends reaches one of two outcomes, and the call.scored webhook fires for both:
success: true when Athos scored the call, success: false when it could not be scored. Only
scored calls are readable over REST — a success: false call answers 404 CALL_NOT_FOUND and
never appears in GET /v1/calls, so the webhook is the only signal you get for it. See
when success is false.
Call sources
Every call carries a source:
roleplay— a practice call your rep ran through the SDK.real_call— a real call one of your agencies' reps made on their dialer, ingested and scored by Athos once that agency has been switched on. See Real-call analysis.
Both fire the same call.scored webhook, carry the same ids, and are read from the same endpoints
in the same shape. GET /v1/calls takes a required source, so one request is an agency's practice
history and another is its real-call history, each newest first. A real call has no drillKey.