Athos Developer Docs

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 platformAgencyId or the Athos agencyId — 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 (and callId): the Athos ids the roster calls returned. Always present. Pass them back as ?agentId= / ?agencyId= on GET /v1/calls, agentId on the mint, and agencyId on POST /v1/agents.
  • Yours — platformAgentId / platformAgencyId: the ids you registered, echoed back on every object — platformAgencyId is the id you created the agency with, platformAgentId the one you registered the rep under. Either is null when you never gave one (a rep registered without platformAgentId) — join on agentId / agencyId in that case.

Your own ids may not begin with athos_agent_ or athos_agency_, and each is unique within your tenant.

Identifiers

IdLooks likeWhat it is
agencyIdathos_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=.
agentIdathos_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=.
callIdathos_call_GZ1DjOkZv_…A call. Use it for GET /v1/calls/:callId; it is the callId in webhooks and in the SDK ended event.
requestIdreq_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.

On this page