Download OpenAPI specification:
Public REST API for our customers.
Every endpoint accepts authentication via either:
Authorization: Bearer <token> header, or?user=<token> query parameter.Tokens are issued by reaching out to our support email.
Requests are limited using a sliding-window algorithm, meaning every request decays on it's own, we prefer you be consistent sending requests rather than a sudden brust. Every 2xx response includes the current state of the window:
| Header | Meaning |
|---|---|
X-RateLimit-Limit |
Requests allowed in the current window |
X-RateLimit-Remaining |
Requests remaining in the current window |
When the limit is exceeded, any endpoint may return 429 Too Many Requests with an empty body and a Retry-After header indicating how many
seconds to wait before retrying. This is not listed individually on each
endpoint — assume it applies everywhere.
Every request must include a meaningful User-Agent header. Clients
that repeatedly fail to send one will receive an empty 418 response from
any endpoint until they comply.
Returns all companies in your account, ordered by company_name ascending.
If your access is restricted to specific companies, only those are returned.
{- "status": "success",
- "message": null,
- "data": [
- {
- "company_id": 12,
- "company_name": "Testselskap Norge AS",
- "created_at": "2024-01-15T09:00:00Z",
- "updated_at": "2024-03-22T14:30:00Z"
}
]
}Returns a single company by ID, including soft-deleted records
(the removed_at and removed_by fields are populated when applicable).
If your access is restricted to specific companies, you can only fetch those companies.
| id required | integer Example: 12 The company's numeric ID |
{- "status": "success",
- "message": null,
- "data": {
- "company_id": 12,
- "company_name": "Testselskap Norge AS",
- "created_at": "2024-01-15T09:00:00Z",
- "updated_at": "2024-03-22T14:30:00Z",
- "removed_at": null,
- "removed_by": null
}
}Returns all active agents in your account (excludes those that have been removed).
Results are filtered by your access scope:
Each agent is returned with its department and company joined in.
{- "status": "success",
- "message": null,
- "data": [
- {
- "agent_id": 4711,
- "name": "Ada Lovelace",
- "login": "ada",
- "email": "ada@test.no",
- "location": "Kristiansand",
- "department_id": 9,
- "department_name": "Sales",
- "company_id": 12,
- "company_name": "Testselskap Norge AS",
- "created_at": "2024-01-15T09:00:00Z",
- "updated_at": "2024-03-22T14:30:00Z",
- "multi_factor": false,
- "mfa_method": null
}
]
}Returns up to 50 call-recording files matching the given filters,
ordered by activity_id descending (newest first).
from_date and to_date accept RFC 3339 timestamps. Defaults:
from_date → start of yesterdayto_date → end of todayPagination is cursor-style via the origin parameter — pass the smallest
activity_file_id from the previous page to fetch the next 50.
The total field is always 0 on this endpoint; the response message
reflects this.
The endpoint internally restricts results to:
activity_type_id ∈ {1, 2}outcome_id ∈ {1, 2, 3, 4, 5, 11}| from_date | string <date-time> Example: from_date=2025-04-26T00:00:00Z Start of the time range (defaults to start of yesterday). |
| to_date | string <date-time> Example: to_date=2025-04-27T23:59:59Z End of the time range (defaults to end of today). |
| search_client | integer Example: search_client=7 Filter by |
| search_outcome_id | integer Example: search_outcome_id=2 Filter by |
| search_phone | string = 8 characters ^\d{8}$ Example: search_phone=98765432 Filter by exact match on the contact's |
| search_order_id | integer Example: search_order_id=90210 Filter by an associated order ID. |
| search_campaign | integer Example: search_campaign=33 Filter by |
| search_segment | integer Example: search_segment=5 Filter by |
| origin | integer Example: origin=1048576 Pagination cursor — return only rows with |
{- "status": "success",
- "message": [
- "Paginator disabled"
], - "data": {
- "rows": [
- {
- "created_at": "2025-04-27T10:42:11Z",
- "activity_file_detail_id": 0,
- "activity_file_id": 1048575,
- "activity_id": 7654321,
- "customer_id": 42,
- "client_id": 7,
- "contact_id": 999111,
- "login_name": "ada",
- "client_name": "Some Client AS",
- "campaign_type_name": "Outbound",
- "campaign_name": "Spring 2025 Sales",
- "outcome_name": "Sale",
- "segment_id": 5,
- "segment_name": "Premium",
- "seconds": 184.5
}
], - "total": 0
}
}Returns the raw audio file for the given activity_file_id as
audio/mpeg. The response is not wrapped in the standard JSON
envelope.
If drc=1 is passed, the post-processed variant is preferred. If a
post-processed variant does not exist on disk, the server falls back to
the original file. The drc name is historical — it originally referred
to dynamic-range compression, but the flag now selects whichever
post-processed variant is available (which may include compression,
noise reduction, normalisation, or a combination).
The response is sent with Content-Disposition: attachment, so browsers
will offer it as a download rather than playing it inline.
| activity_file_id required | integer Example: activity_file_id=1048575 The activity file's numeric ID. |
| drc | integer Default: 0 Enum: 0 1 Set to |
{- "status": "failed",
- "message": "Invalid company",
- "data": null
}Returns the stored transcript for an activity_file_id converted into a
WebVTT string in the data field.
Returns 204 No Content when no transcript exists for the file or
the stored value is unparsable.
| activity_file_id required | integer Example: activity_file_id=1048575 The activity file's numeric ID. |
{- "status": "success",
- "message": null,
- "data": "WEBVTT\n\n00:00:00.000 --> 00:00:02.500\nHello, this is Ada speaking.\n\n00:00:02.500 --> 00:00:05.000\nHow can I help you today?\n"
}Uploads a transcript for an activity file. Two formats are accepted, detected by the client-supplied file extension:
| Extension | Source format |
|---|---|
.vtt |
WebVTT subtitle file |
.json |
OpenAI Whisper response (verbose_json) |
The uploaded JSON must contain a top-level segments array, as
produced by Whisper's verbose_json response format. Plain json
output (which contains only a flat text field) is not sufficient.
Each segment is expected to include at least its start, end, and
text fields.
The file is converted to the internal storage format and upserted —
any existing transcript for the same file_id is replaced.
| file required | string <binary> Transcript file. Filename must end in |
| file_id required | integer The |
{- "status": "success",
- "message": null,
- "data": "Uploaded!"
}