Transcript Ingestion API
The Transcript Ingestion API uploads a pre-existing text transcript for processing by the Agent QA AI Employee. Use this endpoint when audio is not available and you already have the conversation transcript in JSON, XML, or HTML format.
If you have an audio file instead, use the Audio Ingestion API.
12.1 Authentication & Headers
All requests require the same headers as the Audio Ingestion API:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer token (e.g., Bearer <token>) |
x-persona-id | UUID | Yes | The unique identifier of the Agent QA AI Employee (persona). |
12.2 Upload Transcript
| Property | Value |
|---|---|
| URL | {base_url}/api/v1/external/upload/transcript |
| HTTP Method | POST |
| Content-Type | application/json |
Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
format | string | Yes | Format of raw_transcript. Supported values: json, xml, html. |
raw_transcript | string | Yes | Full transcript serialised as a string in the specified format. See format examples below. |
agent_id | string | Yes | Identifier of the human agent associated with the recording. |
agent_email | string | Yes | The human agent's email. Used for permissioning. |
resource_id | string | Yes | External identifier (e.g., Call ID from your telephony provider). |
language | string | No | Language of the transcript. |
timestamp | string | Yes | Call timestamp. Values without timezone information are treated as UTC. |
case_id | string | No | Ticket/case ID associated with the call. |
customer_survey | JSON | No | Customer satisfaction/dissatisfaction survey data. |
agent_tenure | integer | No | Tenure of the associated agent in days. |
json format
A JSON array where each element is one utterance. The time field is optional and accepts ISO 8601, HH:MM:SS, HH:MM, and common date-time variants. When omitted, all utterances are assigned a timestamp of 0.
[
{
"time": "09:15:00",
"role": "Agent",
"text": "Hello, how can I help you?"
},
{
"time": "09:15:05",
"role": "Customer",
"text": "I have an issue with my account."
}
]
xml or html format
An XML chat document. The time attribute is optional.
<chat>
<message time="09:15:00" role="Agent">Hello, how can I help you?</message>
<message time="09:15:05" role="Customer">I have an issue with my account.</message>
</chat>
Success Response (200 OK)
{
"file_id": "550e8400-e29b-41d4-a716-446655440000",
"file_name": "resource_id_123",
"status": "UPLOAD_COMPLETED"
}
12.3 Error Codes
| HTTP Code | Reason |
|---|---|
400 Bad Request | Missing headers, invalid UUID format, unsupported format, or missing agent_id. |
403 Forbidden | Credentials do not have permission to access the specified AI Employee. |
429 Too Many Requests | Rate limit exceeded. Retry with exponential backoff. |
500 Internal Server Error | Unexpected server-side error. |
12.4 Rate Limits
A rate limit of 10 queries per second is enforced on the data upload API.
12.5 Sample Python
import requests
import time
import json
BASE_URL = "https://api.<region>.ema.co" # replace with your domain
AUTH_TOKEN = "YOUR_BEARER_TOKEN"
AI_EMPLOYEE_ID = "YOUR_AI_EMPLOYEE_UUID"
headers = {
"Authorization": f"Bearer {AUTH_TOKEN}",
"x-persona-id": AI_EMPLOYEE_ID,
}
def upload_transcript(transcript, agent_id, agent_email, resource_id,
timestamp, max_retries=3):
"""Uploads a text transcript for a specific AI Employee.
transcript: list of dicts with keys: time (optional), role, text.
"""
url = f"{BASE_URL}/api/v1/external/upload/transcript"
payload = {
"format": "json",
"raw_transcript": json.dumps(transcript),
"agent_id": agent_id,
"agent_email": agent_email,
"resource_id": resource_id,
"timestamp": timestamp,
}
for attempt in range(max_retries + 1):
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
return response.json()
if response.status_code == 429 and attempt < max_retries:
retry_after = int(response.headers.get("Retry-After", 2 ** attempt))
time.sleep(retry_after)
continue
print(f"Failed! Status: {response.status_code}")
print(f"Error: {response.text}")
return None
if __name__ == "__main__":
result = upload_transcript(
transcript=[
{"time": "09:15:00", "role": "Agent", "text": "Hello, how can I help you?"},
{"time": "09:15:05", "role": "Customer", "text": "I have an issue with my account."},
{"time": "09:15:10", "role": "Agent", "text": "I'd be happy to help with that."},
],
agent_id="human_agent_001",
agent_email="[email protected]",
resource_id="resource_id_456",
timestamp=time.strftime("%Y-%m-%d %H:%M:%S"),
)
if result:
print(f"New File ID: {result.get('file_id')}")