Studio API

Author Ellinor Niklasson

Last updated: 21.05.2026 by Ellinor Niklasson

Studio API

What is Studio API?

Think of Studio API as a data pipeline that sends raw call data out of Telavox so customers can plug it into their own systems - like their own dashboards, BI tools (Power BI, Tableau), CRMs, or custom reports.

It's not a tool with a user interface. It's a way for customers who want their own statistics setup to get the raw numbers and build whatever they want with them.

Studio API – Live

Sends call data to your system the moment something happens — a call starts, enters a queue, is answered, or ends. This makes it a good fit for live wallboards, real-time dashboards, and anything where you want to see what's happening right now. How it works: Studio API – Live uses a technology called WebSockets, which keeps an open connection between Telavox and your system so new data can be pushed through instantly.

Studio API – Historic

Lets you pull call data for a specific time period whenever you need it — for example, "all calls from October 1 to 10." This option is best for reports, trend analysis, and looking back at what's already happened. How it works: Studio API – Historic uses a technology called GraphQL, which lets you ask for exactly the information you need — nothing more, nothing less.

Requirements

To track/receive data on users

  • The user must have the feature "Stats Tracked User". 

Access and visibility

Stats Tracked User (User level)

  • User will be tracked in the report.
  • No access to Stats UI via the Web and Desktop app.

Introducing the Telavox Studio API. Discover more by clicking the tabs below: Studio API - Live and Studio API - Historic.

Part 1: Concepts

1. Concepts

1.1 Datasources

Stats Studio exposes two complementary data layers, with five data sources between them. The live layer streams events over WebSockets the moment they happen. The historic layer lets you query a date range over GraphQL whenever you want.

Datasource

Live (WebSocket)

Historic (GraphQL)

Call Overview

/calls

calls

Queue Overview

/queues

queues

Agent Overview

/agents

agents

Profile Live

/profile_live

none

Profile History

/profile_history

profile_history


Both layers authenticate with the same Statistics Token — only the way you attach it to a request differs (see § 1.3).


1.2 Perspectives

The same call can be told from several angles. Stats Studio organises five data sources around three perspectives of a call, plus two views of agent state. Pick the perspective that matches the question you are trying to answer.

Example. One incoming call enters the IVR, lands in the first queue, is offered to Agent 1 (no answer), then to Agent 2 (no answer), jumps to a second queue, and is finally offered to Agent 3, who answers. How many records does that single call produce?

Perspective

Records

Detail

Call Overview

1

1 answered

Queue Overview

2

1 not answered (first queue), 1 answered (second queue)

Agent Overview

3

2 not answered (Agent 1, Agent 2), 1 answered (Agent 3)


Two additional data sources don’t follow this per-call grouping:

Profile Live: fires one event per agent every time their presence changes (Available, Lunch, In a call…).

Profile History: one record per agent profile slot, summarised once an hour.


1.3 Authentication

Both layers use the same Statistics Token.

  1. Sign in to the Telavox webagent.

  2. Open Settings → My Account → Username and password.

  3. Under Integration, click Manage Token.

  4. Click Create new Statistics Token and copy the value.

The token is shown once. Treat it like a password. Rotate it from the same page if it leaks.


How the token is attached differs by layer:

Live: pass an Authorization: Bearer <token> header during the WebSocket handshake. A successful upgrade returns HTTP 101 Switching Protocols. See Part 2.

Historic: pass an Authorization: Bearer <token> header on every HTTP POST. See Part 3.

1.4 Field-naming convention

The same concept appears in both layers under different casings:

Layer

Style

Example

Live (WebSocket)

snake_case

id_call`, `call_direction`, `customer_target.number

Historic (GraphQL)

camelCase

idCall`, `callDirection`, `customerTarget { number }


Each datasource page in Parts 2 and 3 lists its full field reference in the casing of that layer.


1.5 Identifiers — id vs accountId

Each agent, queue and IVR has two numeric IDs. Use the right one for the job:

id. Internal to Stats Studio. Use it when you are working only inside Stats Studio.

accountId. The same ID Telavox exposes in CAPI (Customer API) and PAPI (Partner API). Use it whenever you need to match a Stats Studio record to the same agent, queue or IVR in another Telavox system or in your own database.

The live WebSocket stream always includes account_id in the payload. The historic GraphQL filters accept agentAccountIdqueueAccountId and ivrAccountId as inputs.


1.6 When to use which layer

  • Need it now? Use the live WebSocket of the relevant datasource.

  • Need it for a date range (yesterday, last week, last quarter)? Use the GraphQL query of the same datasource.

  • Building a wallboard? Open the WebSocket for delta updates and seed the initial state with a GraphQL query.

  • Building a daily report? GraphQL only.

Watching agent presence in real time? /profile_live.

Reporting on per-hour agent productivity? profile_history (historic) or /profile_history (live, hourly).

Delete

Part 2: Studio API - Live (WebSocket)

2. Live (WebSocket)

The live layer pushes events as they happen, one WebSocket per datasource. Every endpoint accepts the same Statistics Token (see § 1.3) as a handshake header.

2.0 Connecting

Node.js

// Node.js — npm i ws

import WebSocket from "ws";

 

const ws = new WebSocket("wss://statistics-webhook.telavox.se/calls", {

  headers: { Authorization: `Bearer ${process.env.TELAVOX_TOKEN}` },

});

 

ws.on("message", (buf) => {

  const evt = JSON.parse(buf.toString("utf8"));

  console.log(evt);

});

 

ws.on("close", (code, reason) =>

  console.log("closed", code, reason.toString())

);


Python

# Python — pip install websocket-client

import json, os, websocket

 

def on_message(ws, msg):

    print(json.loads(msg))

 

ws = websocket.WebSocketApp(

    "wss://statistics-webhook.telavox.se/calls",

    header={"Authorization"f"Bearer {os.environ['TELAVOX_TOKEN']}"},

    on_message=on_message,

)

ws.run_forever()


A successful handshake returns HTTP 101 Switching Protocols. A WSS path that returns HTTP 101 followed immediately by a text frame “Invalid path.” is an unknown datasource. HTTP 401 means the token is missing, expired, or revoked.


2.1 Call Overview

One document per call journey: the full path of a call across transfers, queues, agents and IVRs.

Field

Value

Endpoint

wss://statistics-webhook.telavox.se/calls

Cadence

Event-driven. Pushes as the call progresses (call started, entered queue, agent answered, call ended).

Casing

snake_case


Sample payload

{

  "id_call""4d9c10dc-3f9f-41c7-a091-91d5fc746692",

  "answered"0,

  "active"1,

  "call_direction""incoming",

  "time": {

    "start"1779099997234

  },

  "offered_and_answered"0,

  "offered_and_not_answered"0,

  "customer_telavox": {

    "id"43,

    "name""Telavox AB"

  },

  "customer_target": {

    "number""0032470624609"

  },

  "agent_list": ["Jennifer Symoens"]

}


Field reference

{

  "active""Int",

  "agent_first": {

    "account_id""Int",

    "answered""DateTime",

    "avatar""String",

    "email""String",

    "from_transfer""Int",

    "id""Int",

    "is_admin""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    },

    "name""String",

    "phone""String",

    "to_transfer""Int",

    "username""String"

  },

  "agent_last": {

    "account_id""Int",

    "answered""DateTime",

    "avatar""String",

    "email""String",

    "from_transfer""Int",

    "id""Int",

    "is_admin""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    },

    "name""String",

    "phone""String",

    "to_transfer""Int",

    "username""String"

  },

  "agent_list""String",

  "agent_list_answer""String",

  "agent_list_no_answer""String",

  "answered""Int",

  "call_direction""String",

  "customer_target": {

    "number""String"

  },

  "customer_telavox": {

    "id""Int",

    "name""String"

  },

  "duration": {

    "before_queue""Int",

    "on_hold""Int",

    "queue": {

      "first""Int",

      "last""Int",

      "total""Int"

    },

    "ring": {

      "first""Int",

      "last""Int",

      "total""Int"

    },

    "talk": {

      "first""Int",

      "last""Int",

      "total""Int"

    },

    "total""Int",

    "wait""Int"

  },

  "id_call""String",

  "inactive_number""Int",

  "internal""Int",

  "ivr_first": {

    "account_id""Int",

    "id""Int",

    "name""String",

    "phone""String",

    "timestamp""DateTime"

  },

  "ivr_last": {

    "account_id""Int",

    "id""Int",

    "name""String",

    "phone""String",

    "timestamp""DateTime"

  },

  "ivr_list""String",

  "menu_digit": {

    "destination""String",

    "dialed_number""String",

    "type""String"

  },

  "offered_and_answered""Int",

  "offered_and_not_answered""Int",

  "ohw_ordered""Boolean",

  "on_hooked_calls": {

    "answer_wait_request""Int",

    "customer_no_answer""Int",

    "no_wait_request""Int"

  },

  "queue_first": {

    "account_id""Int",

    "fail_reason""String",

    "id""Int",

    "name""String",

    "phone""String",

    "strategy""String",

    "timestart""DateTime"

  },

  "queue_last": {

    "account_id""Int",

    "fail_reason""String",

    "id""Int",

    "name""String",

    "phone""String",

    "strategy""String",

    "timestart""DateTime"

  },

  "queue_list""String",

  "queue_pickup""Int",

  "recorded""Int",

  "redirected": {

    "no_answer""Int",

    "no_reason""Int",

    "not_reachable""Int",

    "total""Int",

    "unconditional""Int",

    "user_busy""Int"

  },

  "save_key_input": {

    "input""String",

    "variable_name""String"

  },

  "simultaneous_device_calls""Int",

  "terminated_call_reason""String",

  "time": {

    "end""DateTime",

    "start""DateTime"

  },

  "transfer_first": {

    "answered""Int",

    "type""String"

  },

  "transfer_last": {

    "answered""Int",

    "type""String"

  },

  "transfers""Int",

  "voicemail""Int"

}


2.2 Queue Overview

One document per (call, queue) pair. A call that traverses three queues emits three records; calls that never enter a queue emit none.

Field

Value

Endpoint

wss://statistics-webhook.telavox.se/queues

Cadence

Event-driven. Fires when a call enters or exits a queue.

Casing

snake_case

Field reference

{

  "account_id""Int",

  "active""Int",

  "agent_first": {

    "account_id""Int",

    "answered""DateTime",

    "avatar""String",

    "email""String",

    "id""Int",

    "is_admin""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    },

    "name""String",

    "phone""String",

    "username""String"

  },

  "agent_last": {

    "account_id""Int",

    "answered""DateTime",

    "avatar""String",

    "email""String",

    "id""Int",

    "is_admin""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    },

    "name""String",

    "phone""String",

    "username""String"

  },

  "agent_list""String",

  "agent_list_answer""String",

  "agent_list_no_answer""String",

  "answered""Int",

  "call_direction""String",

  "customer_target": {

    "number""String"

  },

  "customer_telavox": {

    "id""Int",

    "name""String"

  },

  "duration": {

    "hold""Int",

    "queue""Int",

    "ring": {

      "first""Int",

      "last""Int",

      "total""Int"

    },

    "talk""Int",

    "total""Int",

    "wait""Int"

  },

  "id_call""String",

  "internal""Int",

  "ivr": {

    "account_id""Int",

    "id""Int",

    "name""String",

    "phone""String",

    "timestamp""DateTime"

  },

  "on_hooked_calls""Int",

  "queue": {

    "account_id""Int",

    "free_agents""Int",

    "id""Int",

    "name""String",

    "not_answer_risk""Int",

    "phone""String",

    "queue_talking_agents""Int",

    "strategy""String",

    "timestart""DateTime",

    "total_talking_agents""Int"

  },

  "recorded""Int",

  "time": {

    "end""DateTime",

    "start""DateTime"

  },

  "transfer""Int",

  "voicemail""Int"

}

2.3 Agent Overview

One document per (call, agent) offer. An agent rung but who does not answer still produces a record; calls that never reach an agent emit nothing.

Field

Value

Endpoint

wss://statistics-webhook.telavox.se/agents

Cadence

Event-driven. Fires when a call is offered to an agent (answered or not).

Casing

snake_case


Sample payload

{

  "id_call""4d9c10dc-3f9f-41c7-a091-91d5fc746692",

  "call_direction""incoming",

  "active"0,

  "answered"0,

  "agent": {

    "account_type_id"1,

    "account_id"3467672,

    "id"924328,

    "name""Jennifer Symoens",

    "phone""003228979411",

    "username""003228979411",

    "email""jennifer.symoens@telavox.com",

    "avatar""https://flow.telavox.com/api/internal/contacts/contact-3934178/avatar",

    "is_admin"0,

    "licence": {

      "type""Flow Mobile Custom 10",

      "ccpro"1

    }

  },

  "customer_telavox": {

    "id"43,

    "name""Telavox AB"

  },

  "customer_target": {

    "number""0032470624609"

  },

  "time": {

    "start"1779099997234,

    "end":   1779100016445

  },

  "duration": {

    "total"19211,

    "ring":  19211

  },

  "simultaneous_device_calls"1,

  "agent_end_reason""NO_ANSWER"

}



Field reference

Field names use snake_case. 

{

  "account_id""Int",

  "active""Int",

  "agent": {

    "account_id""Int",

    "avatar""String",

    "email""String",

    "id""Int",

    "is_admin""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    },

    "name""String",

    "phone""String",

    "username""String"

  },

  "agent_end_reason""String",

  "answered""Int",

  "call_direction""String",

  "customer_target": {

    "number""String"

  },

  "customer_telavox": {

    "id""Int",

    "name""String"

  },

  "duration": {

    "hold""Int",

    "ring""Int",

    "talk""Int",

    "total""Int"

  },

  "id_call""String",

  "internal""Int",

  "ivr": {

    "account_id""Int",

    "id""Int",

    "name""String",

    "phone""String",

    "timestamp""DateTime"

  },

  "on_hooked_calls""Int",

  "queue": {

    "account_id""Int",

    "id""Int",

    "name""String",

    "phone""String",

    "strategy""String",

    "timestart""DateTime"

  },

  "recorded""Int",

  "simultaneous_device_calls""Int",

  "time": {

    "answered""DateTime",

    "end""DateTime",

    "start""DateTime"

  },

  "transfer""Int",

  "voicemail""Int"

}


2.4 Profile Live

Streams the current profile of each agent (Available, Lunch, Meeting…), queue-login state, and active-call indicators. Live only — no historic equivalent.

Field

Value

Endpoint

wss://statistics-webhook.telavox.se/profile_live

Cadence

State-change driven. Fires whenever an agent changes profile, queue-login state or active-call state.

Historic equivalent

None. For aggregated history, use `profile_history`.

Casing

snake_case


Sample payload

{

  "customer_telavox": {

    "id"43,

    "name""Telavox AB"

  },

  "agent": {

    "account_type_id"1,

    "account_id"3083293,

    "id"846851,

    "name""Patrik Hilvéus",

    "phone""0406200552",

    "username""0406200552",

    "email""patrik.hilveus@telavox.se",

    "is_admin"1,

    "licence": {

      "type""Flow Mobile Arms",

      "ccpro"1

    }

  },

  "profile": {

    "active": {

      "id"4969080,

      "name""Tillgänglig",

      "status""available",

      "status_message""Tillgänglig",

      "start_date"1779099033656,

      "default_duration"1779116400000,

      "is_wrapup"false

    },

    "not_active": [

      { "id"4969081"name""Lunch",  "status""unavailable""start_date"1779099030867"is_wrapup"false },

      { "id"4969082"name""Möte",   "status""available",   "start_date"1779084010014"is_wrapup"false },

      { "id"4969083"name""Slutat för dagen""status""unavailable""start_date"1779084113000"is_wrapup"false }

    ]

  },

  "queue_login": {

    "logged_in": [

      { "id"111834"name""Jour-Customer Support""start_date"1779099033642 },

      { "id":  19843"name""Telavox Support",       "start_date"1779099033644 }

    ],

    "logged_out": [

      { "id"137266"name""SOHO""start_date"1779084113000 }

    ]

  },

  "active_call": {

    "id_call""89913fac-a038-4fff-b9bd-a183014dc794",

    "answered"0,

    "queue_id"111834,

    "queue_description""Jour-Customer Support",

    "call_direction""incoming",

    "time": { "start"1779100022081 }

  },

  "mobile_active"0,

  "web_active"1,

  "admin_active"1

}


Truncated for readability — Profile Live publishes the full list of all profiles for each agent in profile.not_active. The full schema is shown in the field reference below.


Field reference

{

  "active""Object",

  "active_call": {

    "answered""Int",

    "call_direction""String",

    "id_call""String",

    "internal""Int",

    "ivr_description""String",

    "ivr_id""Int",

    "on_hooked_calls""Int",

    "queue_description""String",

    "queue_id""Int",

    "recorded""Int",

    "time": {

      "answered""Int",

      "start""Int"

    },

    "transfer""Int"

  },

  "admin_active""Int",

  "agent": {

    "account_id""Int",

    "avatar""String",

    "email""String",

    "id""Int",

    "is_admin""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    },

    "name""String",

    "phone""String",

    "username""String"

  },

  "customer_telavox": {

    "id""Int",

    "name""String"

  },

  "last_call_update""Int",

  "last_call_update_sec""Int",

  "mobile_active""Int",

  "profile": {

    "active": {

      "default_duration""Int",

      "id""Int",

      "is_wrapup""Boolean",

      "name""String",

      "start_date""Int",

      "status""String",

      "status_message""String"

    },

    "not_active": {

      "default_duration""Int",

      "id""Int",

      "is_wrapup""Boolean",

      "name""String",

      "start_date""Int",

      "status""String",

      "status_message""String"

    }

  },

  "queue_login": {

    "logged_in": {

      "id""Int",

      "name""String",

      "start_date""Int"

    },

    "logged_out": {

      "id""Int",

      "name""String",

      "start_date""Int"

    }

  },

  "web_active""Int"

}


2.5 Profile History

Per-agent profile slot timeline. Each record covers one continuous period of an agent in a given profile, plus a summary of the calls they handled inside that slot.

Field

Value

Endpoint

wss://statistics-webhook.telavox.se/profile_history

Cadence

Cron-style. The aggregation runs once per hour at the top of the hour (HH:00 UTC) and pushes the whole hourly batch to all connected clients.

Behaviour

Between hourly ticks the socket is silent — leave the connection open through the next HH:00 to receive data.

Historic equivalent

`profile_history` GraphQL root query — see § 3.5.

Casing

snake_case


Field reference

{

  "agent": {

    "account_id""Int",

    "id""Int",

    "name""String",

    "phone""String"

  },

  "call_summary": {

    "active_calls""String",

    "answered_calls""String",

    "completed_calls""String",

    "duration": {

      "talk""Int"

    },

    "id_calls""String",

    "total_answered""Int",

    "total_calls""Int"

  },

  "customer_telavox": {

    "id""Int",

    "name""String"

  },

  "extra_profile_available_1..10": {

    "id""Int",

    "name""String",

    "usage""Int"

  },

  "extra_profile_not_available_1..20": {

    "id""Int",

    "name""String",

    "usage""Int"

  },

  "profile_available": {

    "active""Boolean",

    "available""Boolean",

    "busy""Int",

    "id""Int",

    "is_wrapup""Boolean",

    "name""String",

    "time_start""String",

    "times_in_profile""Int",

    "usage""Int"

  },

  "profile_not_available": {

    "active""Boolean",

    "available""Boolean",

    "busy""Int",

    "id""Int",

    "is_wrapup""Boolean",

    "name""String",

    "time_start""String",

    "times_in_profile""Int",

    "usage""Int"

  },

  "queue_summary": {

    "logged_in": {

      "account_id""Int",

      "active""Boolean",

      "number_times_logged_in""Int",

      "queue_id""Int",

      "queue_name""String",

      "time_start""Int",

      "usage""Int"

    },

    "logged_out": {

      "account_id""Int",

      "active""Boolean",

      "number_times_logged_out""Int",

      "queue_id""Int",

      "queue_name""String",

      "time_start""Int",

      "usage""Int"

    }

  },

  "slot": {

    "busy""Int",

    "end_date""Int",

    "start_date""Int",

    "time_range""Int"

  }

}




Delete

Part 3: Studio API - Historic (GraphQL)

3. Historic (GraphQL)

The historic layer is a single GraphQL endpoint that exposes one root query per perspective (calls, agents, queues, profile_history). Use it for any question that needs a date range — yesterday, last week, last quarter.

Endpoint: https://statistics-api.telavox.se/graphql

Method: HTTP POST

Casing: camelCase (mirror of the snake_case live fields).

3.0 Connecting

Node.js

// Node.js — native fetch (Node 18+)

const res = await fetch("https://statistics-api.telavox.se/graphql", {

  method: "POST",

  headers: {

    "Content-Type""application/json",

    Authorization: `Bearer ${process.env.TELAVOX_TOKEN}`,

  },

    body: JSON.stringify({

      query: `query($s:DateTime,$e:DateTime){

  calls(filter:{startDate:$s,endDate:$e}, first:1){ totalCount } }`,

      variables: { s: "2025-10-01T00:00:00Z", e: "2025-10-01T01:00:00Z" },

    }),


});

 

const { data, errors } = await res.json();

if (errors) console.error(errors);

console.log(data);


Python

# Python — pip install requests

import os, requests

 

res = requests.post(

    "https://statistics-api.telavox.se/graphql",

    headers={

        "Content-Type""application/json",

        "Authorization"f"Bearer {os.environ['TELAVOX_TOKEN']}",

    },

     json={

          "query": "query($s:DateTime,$e:DateTime){

  calls(filter:{startDate:$s,endDate:$e}, first:1){ totalCount } }",

          "variables": {"s": "2025-10-01T00:00:00Z", "e":

  "2025-10-01T01:00:00Z"},

      },


)

print(res.json())


HTTP 401 means the token is missing or invalid. A 200 with an errors array

  ▎ in the body means the request was authenticated but the query is malformed

  ▎ or asks for fields that don't exist. Note: every root query (calls, queues,

  ▎ agents, agentHistory) requires a filter with startDate and endDate — calling

  ▎  them without it returns too_long_http_line_exception.



3.1 Filtering and pagination

All four root queries accept the same wrapping shape:

<root>(

  filter: OverviewFilter

  first: Int!

  after: String

) {

  data { ... }

  totalCount

  cursor

  hasNextPage

}


Use cursor from one response as the after argument of the next request to paginate.

OverviewFilter fields

Field

Type

Meaning

startDate

DateTime

Start of the window (ISO 8601 UTC).

endDate

DateTime

End of the window (ISO 8601 UTC).

queueId

Int

Stats-system queue ID.

queueAccountId

Int

Queue ID shared with CAPI/PAPI. Use this for cross-system joins.

queueName

String

Exact queue display name.

ivrId

Int

Stats-system IVR ID.

ivrAccountId

Int

IVR ID shared with CAPI/PAPI.

ivrName

String

Exact IVR display name.

agentId

Int

Stats-system agent ID.

agentAccountId

Int

Agent ID shared with CAPI/PAPI. Use this for cross-system joins.

agentName

String

Exact agent display name.

callId

String

Exact call UUID.


totalCount is the count for the date window only — it does not shrink when you add agentId, queueId or other filters. To know how many records a filter actually matched, look at the size of data or paginate with cursor / hasNextPage.


Need accountId for a CAPI/PAPI join? Read account_id from the live WebSocket stream — that's the reliable source (see § 1.5).



3.2 Call Overview

One document per call journey: the full path of a call across transfers, queues, agents and IVRs.

Field

Value

Root query

calls

Return type

CallOverviewConnection!

Record type

CallOverviewRecord

Live counterpart

`/calls`  (§ 2.1)

Casing

camelCase


Example query

query Calls($startDate: DateTime, $endDate: DateTime) {

  calls(filter: { startDate: $startDate, endDate: $endDate }, first25) {

    data {

      idCall

      callDirection

      answered

      duration { total talk { total } ring { total } }

      agentFirst { id name }

      queueFirst { id name }

    }

    totalCount cursor hasNextPage

  }

}


Run it from Node.js

const res = await fetch("https://statistics-api.telavox.se/graphql", {

  method: "POST",

  headers: {

    "Content-Type""application/json",

    Authorization: `Bearer ${process.env.TELAVOX_TOKEN}`,

  },

  body: JSON.stringify({

    query: `query Calls($startDate: DateTime, $endDate: DateTime) {

  calls(filter: { startDate: $startDate, endDate: $endDate }, first: 25) {

    data { idCall callDirection answered }

    totalCount cursor hasNextPage

  }

}`,

    variables: {

      startDate: "2025-10-01T00:00:00Z",

      endDate:   "2025-10-06T23:59:59Z",

    },

  }),

});

const { data } = await res.json();

console.log(data.calls);


Run it from Python

import os, requests

 

QUERY = """query Calls($startDate: DateTime, $endDate: DateTime) {

  calls(filter: { startDate: $startDate, endDate: $endDate }, first: 25) {

    data { idCall callDirection answered }

    totalCount cursor hasNextPage

  }

}"""

 

res = requests.post(

    "https://statistics-api.telavox.se/graphql",

    headers={

        "Content-Type""application/json",

        "Authorization"f"Bearer {os.environ['TELAVOX_TOKEN']}",

    },

    json={

        "query": QUERY,

        "variables": {

            "startDate""2025-10-01T00:00:00Z",

            "endDate":   "2025-10-06T23:59:59Z",

        },

    },

)

print(res.json()["data"]["calls"])


Field reference

Field names use camelCase. Source: GraphQL schema introspection of CallOverviewRecord.

{

  "idCall""String",

  "customerTarget": {

    "number""String"

  },

  "callDirection""String",

  "offeredAndAnswered""Int",

  "offeredAndNotAnswered""Int",

  "onHookedCalls": {

    "noWaitRequest""Int",

    "answerWaitRequest""Int",

    "customerNoAnswer""Int"

  },

  "simultaneousDeviceCalls""Int",

  "inactiveNumber""Int",

  "duration": {

    "ring": {

      "first""Int",

      "last""Int",

      "total""Int"

    },

    "queue": {

      "first""Int",

      "last""Int",

      "total""Int"

    },

    "talk": {

      "first""Int",

      "last""Int",

      "total""Int"

    },

    "total""Int",

    "onHold""Int",

    "wait""Int"

  },

  "answered""Int",

  "active""Int",

  "agentFirst": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "email""String",

    "answered""DateTime",

    "toTransfer""Int",

    "fromTransfer""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    }

  },

  "agentLast": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "email""String",

    "answered""DateTime",

    "toTransfer""Int",

    "fromTransfer""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    }

  },

  "agentList""[String!]",

  "agentListAnswer""[String!]",

  "agentListNoAnswer""[String!]",

  "queueFirst": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "strategy""String",

    "timestart""DateTime",

    "failReason""String"

  },

  "queueLast": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "strategy""String",

    "timestart""DateTime",

    "failReason""String"

  },

  "queueList""[String!]",

  "ivrFirst": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "timestamp""DateTime"

  },

  "ivrLast": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "timestamp""DateTime"

  },

  "ivrList""[String!]",

  "queuePickup""Int",

  "time": {

    "start""DateTime",

    "end""DateTime"

  },

  "transferFirst": {

    "type""String",

    "answered""Int"

  },

  "transferLast": {

    "type""String",

    "answered""Int"

  },

  "transfers""Int",

  "redirected": {

    "total""Int",

    "noReason""Int",

    "noAnswer""Int",

    "notReachable""Int",

    "userBusy""Int",

    "unconditional""Int"

  },

  "recorded""Int",

  "menuDigit": {

    "dialedNumber""String",

    "destination""String",

    "type""String"

  },

  "terminatedCallReason""String",

  "internal""Int",

  "saveKeyInput": [

      {

        "variableName": "String",

        "input": "String"

      }

    ],

  "timestamp""DateTime"

}


3.3 Queue Overview

One document per (call, queue) pair. A call that traverses three queues emits three records; calls that never enter a queue emit none.

Field

Value

Root query

queues

Return type

QueueOverviewConnection!

Record type

QueueOverviewRecord

Live counterpart

`/queues`  (§ 2.2)

Casing

camelCase


Example query

query Queues($startDate: DateTime, $endDate: DateTime) {

  queues(filter: { startDate: $startDate, endDate: $endDate }, first25) {

    data {

      idCall

      queue { id name strategy }

      duration { queue wait talk }

      answered

      agentFirst { id name }

    }

    totalCount cursor hasNextPage

  }

}


Run it from Node.js

const res = await fetch("https://statistics-api.telavox.se/graphql", {

  method: "POST",

  headers: {

    "Content-Type""application/json",

    Authorization: `Bearer ${process.env.TELAVOX_TOKEN}`,

  },

  body: JSON.stringify({

    query: `query Queues($startDate: DateTime, $endDate: DateTime) {

  queues(filter: { startDate: $startDate, endDate: $endDate }, first: 25) {

    data { idCall queue { id name } duration { queue wait talk } answered }

    totalCount cursor hasNextPage

  }

}`,

    variables: {

      startDate: "2025-10-01T00:00:00Z",

      endDate:   "2025-10-06T23:59:59Z",

    },

  }),

});

const { data } = await res.json();

console.log(data.queues);


Run it from Python

import os, requests

 

QUERY = """query Queues($startDate: DateTime, $endDate: DateTime) {

  queues(filter: { startDate: $startDate, endDate: $endDate }, first: 25) {

    data { idCall queue { id name } duration { queue wait talk } answered }

    totalCount cursor hasNextPage

  }

}"""

 

res = requests.post(

    "https://statistics-api.telavox.se/graphql",

    headers={

        "Content-Type""application/json",

        "Authorization"f"Bearer {os.environ['TELAVOX_TOKEN']}",

    },

    json={

        "query": QUERY,

        "variables": {

            "startDate""2025-10-01T00:00:00Z",

            "endDate":   "2025-10-06T23:59:59Z",

        },

    },

)

print(res.json()["data"]["queues"])


Field reference

Field names use camelCase. Source: GraphQL schema introspection of QueueOverviewRecord.

{

  "idCall""String",

  "callDirection""String",

  "active""Int",

  "answered""Int",

  "agentFirst": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "email""String",

    "answered""DateTime",

    "toTransfer""Int",

    "fromTransfer""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    }

  },

  "agentLast": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "email""String",

    "answered""DateTime",

    "toTransfer""Int",

    "fromTransfer""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    }

  },

  "ivr": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "timestamp""DateTime"

  },

  "queue": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "strategy""String",

    "timestart""DateTime",

    "failReason""String"

  },

  "customerTarget": {

    "number""String"

  },

  "onHookedCalls""Int",

  "transfer""Int",

  "recorded""Int",

  "time": {

    "start""DateTime",

    "end""DateTime"

  },

  "duration": {

    "total""Int",

    "queue""Int",

    "ring": {

      "first""Int",

      "last""Int",

      "total""Int"

    },

    "talk""Int",

    "hold""Int",

    "wait""Int"

  },

  "simultaneousDeviceCalls""Int",

  "agentEndReason""String",

  "voicemail""Int",

  "internal""Int"

}


3.4 Agent Overview

One document per (call, agent) offer. An agent rung but who does not answer still produces a record; calls that never reach an agent emit nothing.

Field

Value

Root query

agents

Return type

AgentOverviewConnection!

Record type

AgentOverviewRecord

Live counterpart

`/agents`  (§ 2.3)

Casing

camelCase


Example query

query Agents($startDate: DateTime, $endDate: DateTime) {

  agents(filter: { startDate: $startDate, endDate: $endDate }, first25) {

    data {

      idCall

      agent { id name }

      queue { id name }

      duration { total talk hold }

      agentEndReason

    }

    totalCount cursor hasNextPage

  }

}


Run it from Node.js

const res = await fetch("https://statistics-api.telavox.se/graphql", {

  method: "POST",

  headers: {

    "Content-Type""application/json",

    Authorization: `Bearer ${process.env.TELAVOX_TOKEN}`,

  },

  body: JSON.stringify({

    query: `query Agents($startDate: DateTime, $endDate: DateTime) {

  agents(filter: { startDate: $startDate, endDate: $endDate }, first: 25) {

    data { idCall agent { id name } duration { total talk hold } agentEndReason }

    totalCount cursor hasNextPage

  }

}`,

    variables: {

      startDate: "2025-10-01T00:00:00Z",

      endDate:   "2025-10-06T23:59:59Z",

    },

  }),

});

const { data } = await res.json();

console.log(data.agents);


Run it from Python

import os, requests

 

QUERY = """query Agents($startDate: DateTime, $endDate: DateTime) {

  agents(filter: { startDate: $startDate, endDate: $endDate }, first: 25) {

    data { idCall agent { id name } duration { total talk hold } agentEndReason }

    totalCount cursor hasNextPage

  }

}"""

 

res = requests.post(

    "https://statistics-api.telavox.se/graphql",

    headers={

        "Content-Type""application/json",

        "Authorization"f"Bearer {os.environ['TELAVOX_TOKEN']}",

    },

    json={

        "query": QUERY,

        "variables": {

            "startDate""2025-10-01T00:00:00Z",

            "endDate":   "2025-10-06T23:59:59Z",

        },

    },

)

print(res.json()["data"]["agents"])


Field reference

Field names use camelCase. Source: GraphQL schema introspection of AgentOverviewRecord.

{

  "idCall""String",

  "callDirection""String",

  "active""Int",

  "answered""Int",

  "agent": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "email""String",

    "answered""DateTime",

    "toTransfer""Int",

    "fromTransfer""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    }

  },

  "ivr": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "timestamp""DateTime"

  },

  "queue": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "strategy""String",

    "timestart""DateTime",

    "failReason""String"

  },

  "customerTarget": {

    "number""String"

  },

  "onHookedCalls""Int",

  "transfer""Int",

  "recorded""Int",

  "time": {

    "start""DateTime",

    "end""DateTime",

    "answered""DateTime"

  },

  "duration": {

    "total""Int",

    "ring""Int",

    "talk""Int",

    "hold""Int"

  },

  "simultaneousDeviceCalls""Int",

  "agentEndReason""String",

  "voicemail""Int",

  "internal""Int"

}


3.5 Profile History

Per-agent profile slot timeline. Each record covers one continuous period of an agent in a given profile, plus a summary of the calls they handled inside that slot.

Field

Value

Root query

profile_history

Return type

ProfileHistoryOverviewConnection!

Record type

ProfileHistoryOverviewRecord

Live counterpart

`/profile_history`  (§ 2.5)

Casing

camelCase


Example query

query ProfileHistory($startDate: DateTime, $endDate: DateTime) {

  profile_history(filter: { startDate: $startDate, endDate: $endDate }, first25) {

    data {

      agent { id name }

      slot { startDate endDate timeRange busy }

      profileAvailable { name usage busy isWrapup }

      callSummary { totalCalls totalAnswered duration { talk } }

    }

    totalCount cursor hasNextPage

  }

}


Run it from Node.js

const res = await fetch("https://statistics-api.telavox.se/graphql", {

  method: "POST",

  headers: {

    "Content-Type""application/json",

    Authorization: `Bearer ${process.env.TELAVOX_TOKEN}`,

  },

  body: JSON.stringify({

    query: `query ProfileHistory($startDate: DateTime, $endDate: DateTime) {

  profile_history(filter: { startDate: $startDate, endDate: $endDate }, first: 25) {

    data { agent { id name } slot { startDate endDate } callSummary { totalCalls } }

    totalCount cursor hasNextPage

  }

}`,

    variables: {

      startDate: "2025-10-01T00:00:00Z",

      endDate:   "2025-10-06T23:59:59Z",

    },

  }),

});

const { data } = await res.json();

console.log(data.profile_history);


Run it from Python

import os, requests

 

QUERY = """query ProfileHistory($startDate: DateTime, $endDate: DateTime) {

  profile_history(filter: { startDate: $startDate, endDate: $endDate }, first: 25) {

    data { agent { id name } slot { startDate endDate } callSummary { totalCalls } }

    totalCount cursor hasNextPage

  }

}"""

 

res = requests.post(

    "https://statistics-api.telavox.se/graphql",

    headers={

        "Content-Type""application/json",

        "Authorization"f"Bearer {os.environ['TELAVOX_TOKEN']}",

    },

    json={

        "query": QUERY,

        "variables": {

            "startDate""2025-10-01T00:00:00Z",

            "endDate":   "2025-10-06T23:59:59Z",

        },

    },

)

print(res.json()["data"]["profile_history"])


Field reference

{

  "agent": {

    "id""Int",

    "accountId""Int",

    "name""String",

    "phone""String",

    "email""String",

    "answered""DateTime",

    "toTransfer""Int",

    "fromTransfer""Int",

    "licence": {

      "ccpro""Int",

      "type""String"

    }

  },

  "slot": {

    "startDate""Float",

    "endDate""Float",

    "timeRange""Int",

    "busy""Int"

  },

  "profileAvailable": {

    "id""Int",

    "name""String",

    "usage""Int",

    "busy""Int",

    "available""Boolean",

    "active""Boolean",

    "isWrapup""Boolean",

    "timesInProfile""Int",

    "timeStart""Float"

  },

  "callSummary": {

    "totalCalls""Int",

    "totalAnswered""Int",

    "duration": {

      "talk""Int"

    },

    "idCalls""[String!]",

    "answeredCalls""[String!]",

    "completedCalls""[String!]",

    "activeCalls""[String!]"

  }

}

Delete