Use these APIs to send conversation and voice data directly to Contentsquare Conversational Intelligence to be analyzed. They are intended for organizations using CRM, customer support, or phone systems without a native Contentsquare integration.
Overview
The APIs support the following data types:
| API | Channel | Use case |
|---|---|---|
| Conversation API | Chat, email, SMS, and other text channels | Text-based conversations where you provide the messages. |
| Voice API | Voice calls | Phone calls where Contentsquare transcribes the audio and identifies speakers. |
How it works
The Conversation API follows these steps:
- Send a conversation and its messages to the API.
- Contentsquare accepts and queues the conversation for processing.
- Use the processing status endpoint to check progress.
- Contentsquare analyzes the conversation. Results typically appear in the Contentsquare UI within 2 to 3 hours.
The Voice API follows these steps:
- Send conversation metadata and one or more audio file paths or URLs to the API.
- Contentsquare accepts and queues the conversation for processing.
- Use the processing status endpoint to check progress.
- Contentsquare transcribes the audio, identifies speakers, and analyzes the conversation. Results typically appear in the Contentsquare UI within 3 hours.
Prerequisites
Complete the following steps before using these APIs:
- Complete account setup: Contentsquare configures your integration and provides your API credentials.
- Configure audio file access for voice ingestion: Either provide access to your Amazon S3 bucket or provide publicly accessible URLs for your audio files. Contentsquare provides an S3 bucket policy file when applicable. Share this file with the person who manages your infrastructure.
- Configure customer satisfaction (CSAT), if needed: If you plan to send customer satisfaction ratings, configure CSAT normalization rules using the CSAT configuration API.
API authentication
Contentsquare APIs use OAuth 2.0 with the client credentials grant. Your application exchanges its client credentials for a bearer token and includes that token with every API request.
Get your API credentials
During onboarding, authorized users receive access to the Contentsquare onboarding portal. Use the portal to retrieve your API credentials and, when applicable, the S3 bucket policy file.
Request a bearer token
Send a POST request to the token endpoint:
POST https://live.loris.ai/ci/api/oauth/token/Use the client_credentials grant type with your client ID and secret. The response includes a bearer token. Contentsquare doesn't issue a refresh token.
Include the bearer token in the Authorization header of every API request:
Authorization: Bearer <token>Bearer tokens expire after 24 hours. When a token expires, send another request to the token endpoint with the same client ID and secret.
The API accepts the client_credentials grant type only. Other grant types, including refresh_token, are rejected.
Test requests without writing production data
To send a test conversation without writing data to the database, include this header:
Dry-Run: trueDry-run requests still run through validation, translation, and personally identifiable information (PII) redaction. This lets you test the full processing pipeline without affecting production data.
Endpoints
Use the following endpoints:
| Purpose | Method | URL |
|---|---|---|
| Conversation API |
POST
|
https://live.loris.ai/ci/api/conversation/
|
| Voice API |
POST
|
https://live.loris.ai/ci/api/voice-conversation/
|
| Check processing status |
GET
|
https://live.loris.ai/ci/api/conversation-status/
|
| CSAT configuration |
POST
|
https://live.loris.ai/ci/api/settings/csat/
|
| Delete conversation |
POST
|
https://live.loris.ai/ci/api/conversation/delete/
|
Request structure
The Conversation API and Voice API use the same top-level request structure. All conversation fields are nested inside the conversation object.
| Field | Type | Required | Description |
|---|---|---|---|
conversation
|
Object | Yes | Dictionary containing the conversation fields. |
Common fields
These fields apply to both the Conversation API and the Voice API.
Required fields
| Field | Type | Description |
|---|---|---|
source_id
|
String |
Unique conversation identifier. The maximum length is 63 characters.
Use letters, numbers, hyphens, and underscores. The value must
be unique for your account. If one ticket contains multiple conversations, append a suffix to identify the channel and conversation. For example: {ticket_id}_{channel}_{index}, such as
123456789_CHAT_0.
|
crm_user_id
|
String | Unique identifier of the customer in your CRM. |
created
|
String, ISO 8601 |
Timestamp when the conversation was created in the source system.
Use UTC and include a timezone indicator, such as
2024-01-15T09:00:00Z.
|
Optional fields
| Field | Type | Description |
|---|---|---|
related_ticket_id
|
String | ID of the parent ticket in the source system. The maximum length is 63 characters. This field is optional when one ticket maps to one conversation. It is required when one ticket maps to multiple conversations. Use the original ticket ID to link related conversations. |
csat
|
String |
Customer satisfaction rating as received from the source system,
such as 5, good, or satisfied.
CSAT normalization rules must be configured during onboarding.
|
brand_name
|
String | Brand associated with the conversation. The maximum length is 60 characters. Contentsquare creates the brand if it doesn't already exist. |
tags
|
Object |
Tags in the format {tag_name: [tag_values]}. Values
must be arrays, even when a tag has one value. For example:
{"priority": ["high"]}. Tag names can contain up
to 80 characters. Tag values can contain up to 150 characters.
Tags are available for filtering in the Contentsquare UI.
|
custom_fields
|
Object |
Custom fields in the format {field_name: value}.
Values must be strings, integers, or floats. Nested objects aren't
supported. Custom fields are available for filtering in the Contentsquare
UI.
|
csq_user_id
|
String or integer | Identifier of the user in Contentsquare. |
Conversation API
Use the Conversation API for text-based conversations (such as chat, email, and SMS) where you provide the messages.
Contentsquare enriches every ingested conversation. We recommend that if a conversation is ongoing, wait until it is closed or resolved before sending it.
If you send a conversation again with the same source_id, the new version completely replaces the previous version, including previous analysis results. Partial updates, such as metadata-only updates, aren't supported.
Messages must be sorted by created in non-decreasing order. Messages with the same timestamp are allowed and remain in their array order. A request with messages in the wrong order returns a 400 error.
Language support
The Conversation API supports English, French, Spanish, and Arabic. Non-English conversations are translated into English for analysis.
Required fields
| Field | Type | Description |
|---|---|---|
channel
|
String | Communication channel. See the supported channel values below. |
messages
|
Array | Array of message objects. See the Message object section below. |
Channel values
| Value | Description |
|---|---|
EMAIL
|
Email conversations. |
CHAT
|
Live chat or web chat. |
SMS
|
SMS or text messaging. |
WHATSAPP
|
WhatsApp messaging. |
FACEBOOK
|
Facebook Messenger. |
INSTAGRAM
|
Instagram direct messages. |
TWITTER
|
Twitter or X direct messages. |
TIKTOK
|
TikTok messages. |
MESSAGING
|
Generic messaging channel. |
WEB
|
Web-based conversations. |
MOBILE_SDK
|
Mobile app SDK conversations. |
API
|
API-initiated conversations. |
Message object
Each message represents one message in the conversation:
| Field | Type | Required | Description |
|---|---|---|---|
message_type
|
String | Yes |
Direction of the message:IN for a customer message.OUT-HUMAN for an agent message.OUT-BOT for an automated bot or AI response.OUT-AUTO-REPLY for a simple automated reply, such
as “An agent will be with you shortly.”
|
message_body
|
String | Yes |
Message content. Attachments aren't supported. To indicate that
a message includes an attachment, include [FILE_UPLOAD]
in the message text.
|
created
|
String, ISO 8601 | Yes | Timestamp when the message was sent. Use UTC and include a timezone indicator. |
author_id
|
String | Conditional |
Required for OUT-HUMAN, OUT-BOT, and
OUT-AUTO-REPLY messages.
|
author_name
|
String | Conditional |
Required for OUT-HUMAN, OUT-BOT, and
OUT-AUTO-REPLY messages.
|
author_email
|
String | Conditional |
Required for OUT-HUMAN, OUT-BOT, and
OUT-AUTO-REPLY messages.
|
Conversation request example
{ "conversation": { "source_id": "ticket-98765", "crm_user_id": "customer-123", "channel": "EMAIL", "created": "2024-01-15T09:00:00Z", "csat": "5", "brand_name": "Acme Pro", "tags": { "category": ["billing"], "priority": ["high"] }, "custom_fields": { "account_tier": "premium", "case_type": "billing_inquiry" }, "messages": [ { "message_type": "IN", "message_body": "Hi, I have a question about my recent invoice.", "created": "2024-01-15T09:00:00Z" }, { "message_type": "OUT-HUMAN", "message_body": "Hello John, I'd be happy to help you with your invoice. Could you please provide your account number?", "created": "2024-01-15T09:30:00Z", "author_id": "agent-456", "author_name": "Jane Smith", "author_email": "jane.smith@company.com" }, { "message_type": "IN", "message_body": "Sure, it's ACC-12345.", "created": "2024-01-15T09:35:00Z" }, { "message_type": "OUT-HUMAN", "message_body": "Thank you! I've reviewed your account and corrected the billing issue. You should see the adjustment within 24 hours.", "created": "2024-01-15T14:25:00Z", "author_id": "agent-456", "author_name": "Jane Smith", "author_email": "jane.smith@company.com" } ] } }Conversation API limits
- Text from non-English conversations cannot exceed 100 KB in UTF-8 format.
- A single message cannot exceed 5 KB.
- A request cannot exceed 2.5 MB.
- Each conversation must contain at least one message and no more than 300 messages.
- Contentsquare stores the agent name and email address the first time they are received. You can't update these values through the API.
Voice API
Use the Voice API for voice conversations where Contentsquare transcribes the audio and identifies the speakers.
Required fields
| Field | Type | Description |
|---|---|---|
is_inbound_call
|
Boolean |
Use true when the customer called your organization.
Use false when an agent called the customer.
|
audio_files
|
Array | One or more audio file objects. See the Audio files section below. |
Optional timing field
| Field | Type | Description |
|---|---|---|
audio_start_time
|
String, ISO 8601 |
Time when the audio recording started. Contentsquare uses this
value to calculate message timestamps in the transcript. Defaults
to created.
|
Optional call metrics
| Field | Type | Description |
|---|---|---|
audio_duration_seconds
|
Float | Total duration of the audio recording in seconds. |
call_talk_time
|
Integer | Conversation time in seconds, excluding hold and wrap-up time. |
call_hold_time
|
Integer | Total customer hold time in seconds. |
call_wrap_up_time
|
Integer | Agent after-call work time in seconds. |
call_consultation_time
|
Integer | Time the agent spent consulting with others in seconds. |
Audio files
A voice conversation can contain one or more audio segments. Contentsquare merges multiple segments into one audio file before transcription and orders messages by their timestamps across all segments.
Stereo files with separate channels are preferred because they improve speaker identification. Use the optional agent_channel field to identify the agent's channel.
| Field | Type | Required | Description |
|---|---|---|---|
file_path
|
String | Yes |
Path to the audio file in Amazon S3, such as
recordings/2024/01/call-12345.mp3, or a publicly
accessible URL.
|
audio_start_time
|
String, ISO 8601 | Conditional |
Time when the audio segment started. Defaults to the conversation-level
audio_start_time. Required for multi-segment calls.
|
agent_id
|
String | Yes | Identifier of the agent for the segment. |
agent_name
|
String | Yes | Name of the agent for the segment. |
agent_email
|
String | Yes | Email address of the agent for the segment. |
agent_channel
|
Integer | No |
Identifies the agent's audio channel:null means Contentsquare performs speaker identification.1 means the agent is on channel 1 and the customer
is on channel 2.2 means the agent is on channel 2 and the customer
is on channel 1.
|
Supported audio formats
The API supports the following audio formats:
- MP3
- WAV
- Other formats supported by FFmpeg
Single audio file example
{ "audio_files": [ { "file_path": "recordings/2024/01/call-12345.mp3", "agent_id": "agent-123", "agent_name": "John Smith", "agent_email": "john.smith@company.com" } ] }Multiple audio segments example
{ "audio_files": [ { "file_path": "recordings/2024/01/call-12345-seg1.mp3", "audio_start_time": "2024-01-15T10:30:00Z", "agent_id": "agent-123", "agent_name": "John Smith", "agent_email": "john.smith@company.com" }, { "file_path": "recordings/2024/01/call-12345-seg2.mp3", "audio_start_time": "2024-01-15T10:33:00Z", "agent_id": "agent-456", "agent_name": "Jane Doe", "agent_email": "jane.doe@company.com" } ] }Voice language support
Voice transcription supports English.
Speaker identification
Contentsquare uses AI to identify speakers and determine whether each speaker is an agent or customer. Stereo files with separate channels improve speaker identification.
The process includes the following steps:
- Transcription: Contentsquare transcribes the audio and identifies speakers.
- Speaker identification: Contentsquare determines speaker roles using pattern matching and language-model-based identification.
Voice processing requirements
The following requirements apply to voice conversations:
- Each audio segment must contain one customer and one agent.
- Calls with only one detected speaker, such as voicemails, are skipped.
- Interactive voice response, conference, and consultation segments aren't supported as standalone segments.
- Processing fails if Contentsquare can't identify an agent, can't identify a customer, or attributes too many words to unknown speakers.
- Processing failures appear in the status response with
"status": "failed"and an error message. - Audio file download failures aren't retried.
Voice audio limits
- Audio must contain one or two channels.
- MP3, WAV, and other FFmpeg-supported formats are supported.
- Very long calls may have transcripts truncated for speaker identification. This can reduce accuracy for calls with more than approximately 30 minutes of continuous speech.
Voice request example
{ "conversation": { "source_id": "call-98765", "crm_user_id": "customer-456", "created": "2024-01-15T10:30:00Z", "is_inbound_call": true, "csat": "5", "tags": { "category": ["billing"], "resolution": ["resolved"] }, "custom_fields": { "call_reason": "billing_inquiry", "account_tier": "premium" }, "audio_files": [ { "file_path": "recordings/2024/01/call-98765.mp3", "agent_id": "agent-456", "agent_name": "Jane Smith", "agent_email": "jane.smith@company.com" } ] } }Response format
Each request contains one conversation and returns one outcome. The API doesn't return a partial-success list.
| Code | Meaning | Response body |
|---|---|---|
200
|
Success | Empty body. |
400
|
Schema validation failure |
The request doesn't match the schema. The response uses the standard
Pydantic ValidationError.errors() structure.
|
401
|
Authentication failure | The bearer token is invalid, missing, or expired. Request a new token from the token endpoint. |
429
|
Rate limit exceeded | Reduce the request rate and try again. |
500
|
Processing failure |
Translation or PII redaction failed while processing an otherwise
valid request. The response body uses the format
{"error": "<message>"}.
|
400 response example
{ "errors": [ { "loc": ["conversation", "messages", 0, "author_id"], "msg": "Field required", "type": "missing" }, { "loc": ["conversation", "channel"], "msg": "Input should be 'EMAIL', 'CHAT', ...", "type": "enum" } ] }The loc value identifies the field path. Nested fields include the conversation envelope in the path.
Processing status
Use the processing status endpoint to check whether a conversation has finished processing.
Send a GET request to:
GET https://live.loris.ai/ci/api/conversation-status/Response example
{ "source_id": "ticket-12345", "status": "complete", "error": null }Status values
| Status | API | Description |
|---|---|---|
pending
|
Conversation and Voice | Conversation is waiting to be processed or actively being processed. |
transcribing
|
Voice only | Audio was received. Transcription and PII redaction are in progress. |
complete
|
Conversation and Voice | Processing is complete, and the conversation is available in the Contentsquare UI. |
failed
|
Conversation and Voice |
Processing failed. Check the error field for details.
|
Failed status example
{ "source_id": "call-12345", "status": "failed", "error": "Failed to download audio file: file not found" }Rate limits
Both APIs accept up to 100 requests per minute.