Skip to content

Operators ​

14 endpoints. Every path below is relative to the API base URL and already includes the /api/v1 prefix — see conventions for authentication, pagination, errors and idempotency.

Endpoint
GET/contact-center/operatorsList contact-centre operators with presence and current state, filterable by state, online and name search
POST/contact-center/operatorsCreate an operator profile bound to an existing user and return its detailed representation
GET/contact-center/operators/{id}Fetch one operator with presence, routing settings, skills and queue memberships
PATCH/contact-center/operators/{id}Update an operator's profile and routing settings; state is not editable here
DELETE/contact-center/operators/{id}Delete an operator, refusing while they are in a productive state such as on a call
POST/contact-center/operators/{id}/calls/{queueCallId}/acceptAccept a ringing queue offer and bridge the media, reporting connection success separately from acceptance
POST/contact-center/operators/{id}/calls/{queueCallId}/rejectDecline a ringing queue offer, requeue the caller and auto-pause the operator after too many misses
POST/contact-center/operators/{id}/heartbeatRefresh an operator's presence and return how many seconds until the next heartbeat is due
POST/contact-center/operators/{id}/loginOpen an operator session, force the operator to available and return the new session id
POST/contact-center/operators/{id}/logoutForce an operator offline, close their open sessions and clear their presence entry
POST/contact-center/operators/{id}/stateMove an operator into a self-selectable state through the state machine, recording the reason
GET/contact-center/operators/{id}/statisticsReturn an operator's live snapshot, or a rolled-up daily summary when from and to are given
POST/contact-center/operators/{id}/wrap-upClose wrap-up with a disposition, note and callback details, and release the operator back to available
GET/contact-center/queue-calls/{queueCallId}/briefing§14: the pre-answer briefing

Endpoints ​

List contact-centre operators with presence and current state, filterable by state, online and name search ​

GET/contact-center/operators
  • No scope is enforced in the handler — any valid key may call it.

Query parameters

NameTypeRequiredNotes
statestring—
onlineboolean—default false
searchstring—
bash
curl -X GET "$CALLAGENT_API_URL/contact-center/operators?state=string&online=false" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators?state=string&online=false`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators?state=string&online=false');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators?state=string&online=false",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped array

Example response, generated from the schema:

json
{
  "data": {},
  "meta": {
    "page": 1,
    "limit": 25,
    "total": 1,
    "pages": 1
  }
}

Create an operator profile bound to an existing user and return its detailed representation ​

POST/contact-center/operators
  • Requires operator.write.
  • Returns 201, not 200. user_id must reference an existing user row.

Request body

FieldTypeRequiredNotes
user_idstringyes
display_namestringyesmax 255 chars
emailstring | null—email. max 255 chars
operator_numberstring | null—max 24 chars
extension_idstring | null—
supervisor_idstring | null—
priorityinteger | null—min 0. max 1000
max_concurrent_callsinteger | null—min 1. max 10
wrap_up_secondsinteger | null—min 0. max 900
no_answer_timeout_secondsinteger | null—min 5. max 120
auto_pause_after_missedinteger | null—min 0. max 20
auto_answerboolean | null—
can_receive_inboundboolean | null—
can_place_outboundboolean | null—
is_supervisorboolean | null—
languagestring | null—max 16 chars
languagesstring[] | null—
timezonestring | null—max 64 chars
is_activeboolean | null—
bash
curl -X POST "$CALLAGENT_API_URL/contact-center/operators" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
       "user_id": "01JQ0000000000000000000000",
       "display_name": "Support Line",
       "email": "ops@example.com",
       "operator_number": "+40712345678",
       "extension_id": "01JQ0000000000000000000000",
       "supervisor_id": "01JQ0000000000000000000000",
       "priority": 1
     }'
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "user_id": "01JQ0000000000000000000000",
    "display_name": "Support Line",
    "email": "ops@example.com",
    "operator_number": "+40712345678",
    "extension_id": "01JQ0000000000000000000000",
    "supervisor_id": "01JQ0000000000000000000000",
    "priority": 1
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'user_id' => '01JQ0000000000000000000000',
    'display_name' => 'Support Line',
    'email' => 'ops@example.com',
    'operator_number' => '+40712345678',
    'extension_id' => '01JQ0000000000000000000000',
    'supervisor_id' => '01JQ0000000000000000000000',
    'priority' => 1,
]),
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    json={
      "user_id": "01JQ0000000000000000000000",
      "display_name": "Support Line",
      "email": "ops@example.com",
      "operator_number": "+40712345678",
      "extension_id": "01JQ0000000000000000000000",
      "supervisor_id": "01JQ0000000000000000000000",
      "priority": 1
    },
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200JSON object

Errors

StatusWhen it happens
403Session user lacks the operator.write permission
422Validation failed; user_id and display_name are required

Fetch one operator with presence, routing settings, skills and queue memberships ​

GET/contact-center/operators/{id}
  • No scope is enforced in the handler — any valid key may call it.

Path parameters

NameTypeRequiredNotes
idstringyes
bash
curl -X GET "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
404No operator with this id in the caller's tenant

Example response, generated from the schema:

json
{
  "data": {}
}

Update an operator's profile and routing settings; state is not editable here ​

PATCH/contact-center/operators/{id}
  • Requires operator.write.
  • state is deliberately rejected as an input: it moves only through the state machine, via /state or a supervisor force.

Path parameters

NameTypeRequiredNotes
idstringyes

Request body

FieldTypeRequiredNotes
display_namestring—max 255 chars
emailstring | null—email. max 255 chars
extension_idstring | null—
supervisor_idstring | null—
priorityinteger | null—min 0. max 1000
max_concurrent_callsinteger | null—min 1. max 10
wrap_up_secondsinteger | null—min 0. max 900
no_answer_timeout_secondsinteger | null—min 5. max 120
auto_pause_after_missedinteger | null—min 0. max 20
auto_answerboolean | null—
can_receive_inboundboolean | null—
can_place_outboundboolean | null—
is_supervisorboolean | null—
languagestring | null—max 16 chars
languagesstring[] | null—
timezonestring | null—max 64 chars
is_activeboolean | null—
bash
curl -X PATCH "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
       "display_name": "Support Line",
       "email": "ops@example.com",
       "extension_id": "01JQ0000000000000000000000",
       "supervisor_id": "01JQ0000000000000000000000",
       "priority": 1,
       "max_concurrent_calls": 1,
       "wrap_up_seconds": 30
     }'
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "display_name": "Support Line",
    "email": "ops@example.com",
    "extension_id": "01JQ0000000000000000000000",
    "supervisor_id": "01JQ0000000000000000000000",
    "priority": 1,
    "max_concurrent_calls": 1,
    "wrap_up_seconds": 30
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'display_name' => 'Support Line',
    'email' => 'ops@example.com',
    'extension_id' => '01JQ0000000000000000000000',
    'supervisor_id' => '01JQ0000000000000000000000',
    'priority' => 1,
    'max_concurrent_calls' => 1,
    'wrap_up_seconds' => 30,
]),
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.patch(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    json={
      "display_name": "Support Line",
      "email": "ops@example.com",
      "extension_id": "01JQ0000000000000000000000",
      "supervisor_id": "01JQ0000000000000000000000",
      "priority": 1,
      "max_concurrent_calls": 1,
      "wrap_up_seconds": 30
    },
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200JSON object

Errors

StatusWhen it happens
403Session user lacks the operator.write permission
404No operator with this id in the caller's tenant
422Validation failed on the operator payload

Delete an operator, refusing while they are in a productive state such as on a call ​

DELETE/contact-center/operators/{id}
  • Requires operator.write.
  • This response is not data-wrapped.

Path parameters

NameTypeRequiredNotes
idstringyes
bash
curl -X DELETE "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000`, {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.delete(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200Bare JSON object, not data-wrapped

Errors

StatusWhen it happens
403Session user lacks the operator.write permission
404No operator with this id in the caller's tenant
409The operator is currently on a call

Accept a ringing queue offer and bridge the media, reporting connection success separately from acceptance ​

POST/contact-center/operators/{id}/calls/{queueCallId}/accept
  • No scope is enforced in the handler — any valid key may call it.
  • Always 200 even on failure: if the offer is no longer held by this operator the body carries connected=false and connection_error=offer_no_longer_held.

Path parameters

NameTypeRequiredNotes
idstringyes
queueCallIdstringyes
bash
curl -X POST "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000/calls/01JQ0000000000000000000000/accept" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000/calls/01JQ0000000000000000000000/accept`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000/calls/01JQ0000000000000000000000/accept');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000/calls/01JQ0000000000000000000000/accept",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
404The operator or the queue call does not exist in this tenant

Example response, generated from the schema:

json
{
  "data": {
    "queue_call_id": null,
    "status": "string",
    "connected": "string",
    "connection_error": "string",
    "briefing": {}
  }
}

Decline a ringing queue offer, requeue the caller and auto-pause the operator after too many misses ​

POST/contact-center/operators/{id}/calls/{queueCallId}/reject
  • No scope is enforced in the handler — any valid key may call it.
  • Rejecting an offer held by someone else is not an error: it returns status=skipped with reason=not_offered_to_operator.

Path parameters

NameTypeRequiredNotes
idstringyes
queueCallIdstringyes
bash
curl -X POST "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000/calls/01JQ0000000000000000000000/reject" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000/calls/01JQ0000000000000000000000/reject`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000/calls/01JQ0000000000000000000000/reject');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000/calls/01JQ0000000000000000000000/reject",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
404The operator or the queue call does not exist in this tenant

Example response, generated from the schema:

json
{
  "data": {
    "status": "string",
    "reason": "string"
  }
}

Refresh an operator's presence and return how many seconds until the next heartbeat is due ​

POST/contact-center/operators/{id}/heartbeat
  • No scope is enforced in the handler — any valid key may call it.
  • Optional body fields source (default 'api') and connection_id are accepted but never validated.

Path parameters

NameTypeRequiredNotes
idstringyes

Request body

FieldTypeRequiredNotes
connection_idstring—
bash
curl -X POST "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000/heartbeat" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
       "connection_id": "01JQ0000000000000000000000"
     }'
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000/heartbeat`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "connection_id": "01JQ0000000000000000000000"
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000/heartbeat');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'connection_id' => '01JQ0000000000000000000000',
]),
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000/heartbeat",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    json={
      "connection_id": "01JQ0000000000000000000000"
    },
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
404No operator with this id in the caller's tenant

Example response, generated from the schema:

json
{
  "data": {
    "ok": true,
    "next_heartbeat_seconds": 30
  }
}

Open an operator session, force the operator to available and return the new session id ​

POST/contact-center/operators/{id}/login
  • No scope is enforced in the handler — any valid key may call it.
  • Any stale open session is closed first. Optional body field device (default 'api') is unvalidated.

Path parameters

NameTypeRequiredNotes
idstringyes
bash
curl -X POST "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000/login" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000/login`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000/login');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000/login",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
404No operator with this id in the caller's tenant

Example response, generated from the schema:

json
{
  "data": {
    "session_id": null,
    "operator": {}
  }
}

Force an operator offline, close their open sessions and clear their presence entry ​

POST/contact-center/operators/{id}/logout
  • No scope is enforced in the handler — any valid key may call it.

Path parameters

NameTypeRequiredNotes
idstringyes
bash
curl -X POST "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000/logout" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000/logout`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000/logout');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000/logout",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
404No operator with this id in the caller's tenant

Example response, generated from the schema:

json
{
  "data": {}
}

Move an operator into a self-selectable state through the state machine, recording the reason ​

POST/contact-center/operators/{id}/state
  • No scope is enforced in the handler — any valid key may call it.
  • Engine-owned states such as ringing and on_call are rejected with 422; an illegal but self-selectable transition is 409.

Path parameters

NameTypeRequiredNotes
idstringyes

Request body

FieldTypeRequiredNotes
stateoffline · available · busy · ringing · on_call · wrap_up …yes
reason_codestring | null—max 64 chars
reason_notestring | null—max 255 chars
bash
curl -X POST "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000/state" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
       "state": "offline"
     }'
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000/state`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "state": "offline"
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000/state');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'state' => 'offline',
]),
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000/state",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    json={
      "state": "offline"
    },
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
404No operator with this id in the caller's tenant
409The state machine refused the transition
422Unknown state, or a state only the routing engine may set

Example response, generated from the schema:

json
{
  "data": {}
}

Return an operator's live snapshot, or a rolled-up daily summary when from and to are given ​

GET/contact-center/operators/{id}/statistics
  • No scope is enforced in the handler — any valid key may call it.
  • The response shape changes with the query: passing from switches it from the realtime snapshot to the historical rollup.

Path parameters

NameTypeRequiredNotes
idstringyes

Query parameters

NameTypeRequiredNotes
fromstringyesdate-time
tostringyesdate-time
bash
curl -X GET "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000/statistics?from=%2B40712345678&to=%2B40712345678" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000/statistics?from=%2B40712345678&to=%2B40712345678`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000/statistics?from=%2B40712345678&to=%2B40712345678');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000/statistics?from=%2B40712345678&to=%2B40712345678",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200JSON object

Errors

StatusWhen it happens
404No operator with this id in the caller's tenant
422from was supplied without a valid to

Example response, generated from the schema:

json
{
  "data": {
    "operator_id": null,
    "name": "Support Line",
    "state": "string",
    "state_label": "string",
    "state_reason": "string",
    "state_since": "string",
    "seconds_in_state": {},
    "online": true,
    "offered_today": 1,
    "answered_today": 1,
    "missed_today": 1
  }
}

Close wrap-up with a disposition, note and callback details, and release the operator back to available ​

POST/contact-center/operators/{id}/wrap-up
  • No scope is enforced in the handler — any valid key may call it.
  • Side effect: a disposition flagged schedules_callback writes callback fields onto the queue call.

Path parameters

NameTypeRequiredNotes
idstringyes

Request body

FieldTypeRequiredNotes
queue_call_idstring | null—
disposition_idstring | null—
notestring | null—max 5000 chars
tagsstring[] | null—
quality_scoreinteger | null—min 0. max 100
first_contact_resolutionboolean | null—
callback_numberstring | null—max 32 chars
callback_scheduled_forstring | null—date-time
bash
curl -X POST "$CALLAGENT_API_URL/contact-center/operators/01JQ0000000000000000000000/wrap-up" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
       "queue_call_id": "01JQ0000000000000000000000",
       "disposition_id": "01JQ0000000000000000000000",
       "quality_score": 1,
       "first_contact_resolution": true,
       "callback_number": "+40712345678",
       "callback_scheduled_for": "2026-01-01T12:00:00+00:00"
     }'
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/operators/01JQ0000000000000000000000/wrap-up`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "queue_call_id": "01JQ0000000000000000000000",
    "disposition_id": "01JQ0000000000000000000000",
    "quality_score": 1,
    "first_contact_resolution": true,
    "callback_number": "+40712345678",
    "callback_scheduled_for": "2026-01-01T12:00:00+00:00"
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/operators/01JQ0000000000000000000000/wrap-up');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'queue_call_id' => '01JQ0000000000000000000000',
    'disposition_id' => '01JQ0000000000000000000000',
    'quality_score' => 1,
    'first_contact_resolution' => true,
    'callback_number' => '+40712345678',
    'callback_scheduled_for' => '2026-01-01T12:00:00+00:00',
]),
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/operators/01JQ0000000000000000000000/wrap-up",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    json={
      "queue_call_id": "01JQ0000000000000000000000",
      "disposition_id": "01JQ0000000000000000000000",
      "quality_score": 1,
      "first_contact_resolution": True,
      "callback_number": "+40712345678",
      "callback_scheduled_for": "2026-01-01T12:00:00+00:00"
    },
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
404No operator with this id in the caller's tenant
422Payload invalid, or the queue requires a disposition or the disposition requires a note

Example response, generated from the schema:

json
{
  "data": {
    "call_disposition_id": null,
    "operator": {}
  }
}

§14: the pre-answer briefing ​

GET/contact-center/queue-calls/{queueCallId}/briefing
  • No scope is enforced in the handler — any valid key may call it.
  • Not read-only: the first call freezes the assembled caller_history onto the queue call row.

Path parameters

NameTypeRequiredNotes
queueCallIdstringyes
bash
curl -X GET "$CALLAGENT_API_URL/contact-center/queue-calls/01JQ0000000000000000000000/briefing" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/contact-center/queue-calls/01JQ0000000000000000000000/briefing`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/contact-center/queue-calls/01JQ0000000000000000000000/briefing');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/contact-center/queue-calls/01JQ0000000000000000000000/briefing",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped array

Errors

StatusWhen it happens
404No queue call with this id in the caller's tenant

Example response, generated from the schema:

json
{
  "data": {}
}

Documented against the code. Anything not yet implemented is labelled, never described as working.