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:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token (e.g., Bearer <token>)
x-persona-idUUIDYesThe unique identifier of the Agent QA AI Employee (persona).

12.2 Upload Transcript

PropertyValue
URL{base_url}/api/v1/external/upload/transcript
HTTP MethodPOST
Content-Typeapplication/json

Body Fields

FieldTypeRequiredDescription
formatstringYesFormat of raw_transcript. Supported values: json, xml, html.
raw_transcriptstringYesFull transcript serialised as a string in the specified format. See format examples below.
agent_idstringYesIdentifier of the human agent associated with the recording.
agent_emailstringYesThe human agent's email. Used for permissioning.
resource_idstringYesExternal identifier (e.g., Call ID from your telephony provider).
languagestringNoLanguage of the transcript.
timestampstringYesCall timestamp. Values without timezone information are treated as UTC.
case_idstringNoTicket/case ID associated with the call.
customer_surveyJSONNoCustomer satisfaction/dissatisfaction survey data.
agent_tenureintegerNoTenure 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 CodeReason
400 Bad RequestMissing headers, invalid UUID format, unsupported format, or missing agent_id.
403 ForbiddenCredentials do not have permission to access the specified AI Employee.
429 Too Many RequestsRate limit exceeded. Retry with exponential backoff.
500 Internal Server ErrorUnexpected 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')}")

Last updated: Jul 3, 2026