Appearance
For clean Markdown of any page, append .md to the page URL. For a complete documentation index, see For full documentation content, see For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at
Custom Formatting
Automatically format dates, phone numbers, emails, and more in your transcripts
For the complete documentation index, see llms.txt
cURL quickstart — Custom Formatting
bash
# Method 1: Transcribe and format in one request
curl \
--header "Authorization: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"audio_url": "",
"speech_models": ["universal-3-pro", "universal-2"],
"language_detection": true,
"speaker_labels": true,
"speech_understanding": {
"request": {
"custom_formatting": {
"date": "mm/dd/yyyy",
"phone_number": "(xxx)xxx-xxxx",
"email": "username@domain.com",
"format_utterances": true
}
}
}
}'
# Poll for result (replace TRANSCRIPT_ID)
curl \
--header "Authorization: YOUR_API_KEY"The response includes speech_understanding.response.custom_formatting with a mapping of original-to-formatted values and formatted_text.
US & EU
Overview
The Custom Formatting feature automatically standardizes and formats specific types of information in your transcripts, ensuring consistency across dates, phone numbers, emails, and other data types. This eliminates the need for post-processing and provides clean, formatted output ready for your application.
Key capabilities:
- Format dates in your preferred style (US, European, ISO, etc.)
- Standardize phone number formats with custom patterns
- Control currency and decimal precision
- Convert spelled-out text into formatted patterns
- Format URLs as hyperlinks
- Apply multiple formatting rules simultaneously
Common use cases:
- Standardizing contact information in customer service transcripts
- Formatting financial data in earnings calls
- Preparing transcripts for CRM systems with specific format requirements
- Creating consistent documentation from meetings
- Processing legal or medical transcripts with strict formatting standards
Quickstart
There are two ways to use Custom Formatting:
- Transcribe and format in one request - Best when you're starting a new transcription and want to automatically format the transcript text as part of that process
- Transcribe and format in separate requests - Best when you already have text that you would like to format or for more complicated workflows where you want to separate the transcription and formatting tasks
Method 1: Transcribe and format in one request
This method is ideal when you're starting fresh and want both transcription and formatting in a single workflow.
python
import requests
import time
base_url = ""
headers = {
"authorization": "<YOUR_API_KEY>"
}
# Need to transcribe a local file? Learn more here:
audio_url = ""
# Configure transcription with custom formatting
data = {
"audio_url": audio_url,
"speech_models": ["universal-3-pro", "universal-2"],
"language_detection": True,
"speaker_labels": True,
"speech_understanding": {
"request": {
"custom_formatting": {
"date": "mm/dd/yyyy",
"phone_number": "(xxx)xxx-xxxx",
"email": "username@domain.com",
"format_utterances": True
}
}
}
}
# Submit transcription request
response = requests.post(base_url + "/v2/transcript", headers=headers, json=data)
transcript_id = response.json()["id"]
polling_endpoint = base_url + f"/v2/transcript/{transcript_id}"
# Poll for transcription results
while True:
transcript = requests.get(polling_endpoint, headers=headers).json()
if transcript["status"] == "completed":
break
elif transcript["status"] == "error":
raise RuntimeError(f"Transcription failed: {transcript['error']}")
else:
time.sleep(3)
# Access and display results
print("\n--- Formatting Details ---")
mapping = transcript['speech_understanding']['response']['custom_formatting']['mapping']
for original, formatted in mapping.items():
print(f"Original: {original}")
print(f"Formatted: {formatted}\n")javascript
const baseUrl = "";
const headers = {
authorization: "<YOUR_API_KEY>",
"content-type": "application/json",
};
// Need to transcribe a local file? Learn more here:
const audioUrl = "";
// Configure transcription with custom formatting
const data = {
audio_url: audioUrl,
speech_models: ["universal-3-pro", "universal-2"],
language_detection: true,
speaker_labels: true,
speech_understanding: {
request: {
custom_formatting: {
date: "mm/dd/yyyy",
phone_number: "(xxx)xxx-xxxx",
email: "username@domain.com",
format_utterances: true,
},
},
},
};
// Submit transcription request
const response = await fetch(`${baseUrl}/v2/transcript`, {
method: "POST",
headers: headers,
body: JSON.stringify(data),
});
const { id: transcriptId } = await response.json();
const pollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}`;
// Poll for transcription results
while (true) {
const pollingResponse = await fetch(pollingEndpoint, { headers });
const transcript = await pollingResponse.json();
if (transcript.status === "completed") {
// Access and display results
console.log("\n--- Formatting Details ---");
const mapping =
transcript.speech_understanding.response.custom_formatting.mapping;
for (const [original, formatted] of Object.entries(mapping)) {
console.log(`Original: ${original}`);
console.log(`Formatted: ${formatted}\n`);
}
break;
} else if (transcript.status === "error") {
throw new Error(`Transcription failed: ${transcript.error}`);
} else {
await new Promise((resolve) => setTimeout(resolve, 3000));
}
}python
import assemblyai as aai
aai.settings.api_key = "<YOUR_API_KEY>"
audio_url = ""
config = aai.TranscriptionConfig(
speech_models=["universal-3-pro", "universal-2"],
language_detection=True,
speaker_labels=True,
speech_understanding=aai.SpeechUnderstandingRequest(
request=aai.SpeechUnderstandingFeatureRequests(
custom_formatting=aai.CustomFormattingRequest(
phone_number="(XXX) XXX-XXXX",
)
)
)
)
transcriber = aai.Transcriber()
transcript = transcriber.transcribe(audio_url, config)
# Print the formatted text
su = transcript.speech_understanding
if su and su.response and su.response.custom_formatting:
fmt = su.response.custom_formatting
print("Mapping:", fmt.mapping)
print("\nFormatted text:", fmt.formatted_text)javascript
import { AssemblyAI } from "assemblyai";
const client = new AssemblyAI({
apiKey: "<YOUR_API_KEY>"
});
const audioUrl = "";
const params = {
audio: audioUrl,
speech_models: ["universal-3-pro", "universal-2"],
language_detection: true,
speaker_labels: true,
speech_understanding: {
request: {
custom_formatting: {
phone_number: "(XXX) XXX-XXXX",
}
}
}
};
const transcript = await client.transcripts.transcribe(params);
// Print the formatted text
const fmt = transcript.speech_understanding?.response?.custom_formatting;
if (fmt) {
console.log("Mapping:", fmt.mapping);
console.log("\nFormatted text:", fmt.formatted_text);
}Method 2: Transcribe and format in separate requests
This method is useful when you already have text that you would like to format or for more complicated workflows where you want to separate the transcription and formatting tasks.
python
import requests
import time
base_url = ""
headers = {
"authorization": "<YOUR_API_KEY>"
}
# Need to transcribe a local file? Learn more here:
audio_url = ""
# Submit transcription request (without formatting)
data = {
"audio_url": audio_url,
"speech_models": ["universal-3-pro", "universal-2"],
"language_detection": True,
"speaker_labels": True
}
response = requests.post(base_url + "/v2/transcript", headers=headers, json=data)
transcript_id = response.json()["id"]
polling_endpoint = base_url + f"/v2/transcript/{transcript_id}"
# Poll for transcription completion
while True:
transcript = requests.get(polling_endpoint, headers=headers).json()
if transcript["status"] == "completed":
print("Transcription completed!")
break
elif transcript["status"] == "error":
raise RuntimeError(f"Transcription failed: {transcript['error']}")
else:
time.sleep(3)
# Add custom formatting configuration to the completed transcript
understanding_body = {
"transcript_id": transcript_id,
"speech_understanding": {
"request": {
"custom_formatting": {
"date": "mm/dd/yyyy",
"phone_number": "(xxx)xxx-xxxx",
"email": "username@domain.com",
"format_utterances": True
}
}
}
}
# Send to Speech Understanding API for formatting
result = requests.post(
"",
headers=headers,
json=understanding_body
).json()
print("Formatting completed!")
# Access and display results
print("\n--- Formatting Details ---")
mapping = result['speech_understanding']['response']['custom_formatting']['mapping']
for original, formatted in mapping.items():
print(f"Original: {original}")
print(f"Formatted: {formatted}\n")javascript
const baseUrl = "";
const headers = {
authorization: "<YOUR_API_KEY>",
"content-type": "application/json",
};
// Need to transcribe a local file? Learn more here:
const audioUrl = "";
// Submit transcription request (without formatting)
const data = {
audio_url: audioUrl,
speech_models: ["universal-3-pro", "universal-2"],
language_detection: true,
speaker_labels: true,
};
async function transcribeAndFormat() {
// Start transcription
const response = await fetch(`${baseUrl}/v2/transcript`, {
method: "POST",
headers: headers,
body: JSON.stringify(data),
});
const { id: transcriptId } = await response.json();
const pollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}`;
// Poll for transcription completion
while (true) {
const pollingResponse = await fetch(pollingEndpoint, { headers });
const transcript = await pollingResponse.json();
if (transcript.status === "completed") {
console.log("Transcription completed!");
break;
} else if (transcript.status === "error") {
throw new Error(`Transcription failed: ${transcript.error}`);
} else {
await new Promise((resolve) => setTimeout(resolve, 3000));
}
}
// Add custom formatting configuration to the completed transcript
const understandingBody = {
transcript_id: transcriptId,
speech_understanding: {
request: {
custom_formatting: {
date: "mm/dd/yyyy",
phone_number: "(xxx)xxx-xxxx",
email: "username@domain.com",
format_utterances: true,
},
},
},
};
// Send to Speech Understanding API for formatting
const understandingResponse = await fetch(
"",
{
method: "POST",
headers: headers,
body: JSON.stringify(understandingBody),
}
);
const result = await understandingResponse.json();
// Access and display results
console.log("\n--- Formatting Details ---");
const mapping =
result.speech_understanding.response.custom_formatting.mapping;
for (const [original, formatted] of Object.entries(mapping)) {
console.log(`Original: ${original}`);
console.log(`Formatted: ${formatted}\n`);
}
}
transcribeAndFormat();Expected output:
--- Formatting Details ---
Original: Yes, I would appreciate it if you could call me back. My phone number is 555-679-3466. Also, my cell phone number is 555-679-8244. Once again, if you could call me back, I'd appreciate it. My phone number is 555-679-3466. Thanks.
Formatted: Yes, I would appreciate it if you could call me back. My phone number is (555)679-3466. Also, my cell phone number is (555)679-8244. Once again, if you could call me back, I'd appreciate it. My phone number is (555)679-3466. Thanks.Output format
Data from the Custom Formatting API will be returned in the custom_formatted object, which is contained in the speech_understanding object. The formatted_text key will included a formatted version of the transcript text.
If Speaker Diarization is used in the request a formatted_utterances key will be returned containing formatted utterances with preserved timestamps.
Example response structure:
json
{
"id": "2accd7f2-445b-4d08-b10b-1bafdd5906ed",
"status": "completed",
"text": "Yes, I would appreciate it if you could call me back. My phone number is 555-679-3466...",
"speech_understanding": {
"request": {
"custom_formatting": {
"date": "mm/dd/yyyy",
"phone_number": "(xxx)xxx-xxxx",
"email": "username@domain.com",
"format_utterances": true
}
},
"response": {
"custom_formatting": {
"formatted_text": "Yes, I would appreciate it if you could call me back. My phone number is (555)679-3466...",
"formatted_utterances": [
{
"confidence": 0.9920061471354167,
"end": 26000,
"speaker": "A",
"start": 1920,
"text": "Yes, I would appreciate it if you could call me back. My phone number is (555)679-3466...",
"words": [
{
"speaker": "A",
"start": 1920,
"end": 2160,
"text": "Yes,",
"confidence": 0.808349609375
}
// ... more words
]
}
],
"mapping": {
"555-679-3466": "(555)679-3466",
"555-679-8244": "(555)679-8244"
},
"status": "success"
}
}
}
}Key features of the output:
- Formatted Text: Formatted text can be found in the
formatted_textkey - Formatted utterances: When
format_utterancesis enabled, speaker-separated segments in theformatted_utteranceskey include formatted text - Preserved timestamps: All word-level timestamps in
formatted_utterancesremain intact after formatting, allowing you to maintain temporal alignment with the audio - Mapping object: Shows exactly what transformations were applied (original → formatted)
Understanding the custom_formatting parameter
The custom_formatting parameter accepts an object with specific formatting rules for different data types in your transcript. Each property in the object defines how a particular type of information should be formatted.
Available formatting options
| Parameter | Type | Description | Example Values |
|---|---|---|---|
date | string | Specifies the format pattern for dates in the transcript | "mm/dd/yyyy", "dd/mm/yyyy", "yyyy-mm-dd" |
phone_number | string | Specifies the format pattern for phone numbers | "(xxx)xxx-xxxx", "xxx-xxx-xxxx", "xxx.xxx.xxxx" |
email | string | Specifies the format pattern for email addresses | "username@domain.com", "firstname.lastname@domain.com" |
format_utterances | boolean | When true, applies formatting to utterances in addition to the main text field. Preserves all word-level timestamps. | true, false (default: false) |
Example configuration:
json
{
"custom_formatting": {
"date": "mm/dd/yyyy",
"phone_number": "(xxx)xxx-xxxx",
"email": "username@domain.com",
"format_utterances": true
}
}When you include this configuration in your transcription request, the API will automatically detect and format dates, phone numbers, and emails in your transcript according to the specified patterns. With format_utterances enabled, the formatting is applied to both the main transcript text and individual speaker utterances while preserving all timing information.
Common formatting patterns
Date formats
| Pattern | Example Output | Description |
|---|---|---|
mm/dd/yyyy | 09/19/1991 | US format (month/day/year) |
dd/mm/yyyy | 19/09/1991 | European format (day/month/year) |
yyyy-mm-dd | 1991-09-19 | ISO 8601 format |
mm-dd-yyyy | 09-19-1991 | US format with dashes |
dd.mm.yyyy | 19.09.1991 | European format with dots |
Phone number formats
| Pattern | Example Output | Description |
|---|---|---|
(xxx)xxx-xxxx | (555)679-3466 | Parentheses and dash |
xxx-xxx-xxxx | 555-679-3466 | Dashes only |
xxx.xxx.xxxx | 555.679.3466 | Dots separator |
+x(xxx)xxx-xxxx | +1(555)679-3466 | International format |
Email formats
| Pattern | Example Output |
|---|---|
username@domain.com | john.doe@example.com |
firstname.lastname@domain.com | john.doe@company.com |
Best practices
Choose appropriate formats: Select formatting patterns that match your application's requirements and regional standards.
Combine formatting rules: You can apply multiple formatting rules simultaneously for comprehensive text standardization.
Test with sample data: Verify your formatting patterns work correctly with representative audio samples before processing large batches.
Review the mapping: Check the
mappingobject in the response to see exactly what was changed and verify the results.Consider regional differences: Be mindful of date and phone number format differences when processing international content.
API reference
Request
Method 1: Transcribe and format in one request
When creating a new transcription, include the speech_understanding parameter directly in your transcription request:
bash
curl -X POST \
"" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"audio_url": "",
"speaker_labels": true,
"speech_understanding": {
"request": {
"custom_formatting": {
"date": "mm/dd/yyyy",
"phone_number": "(xxx)xxx-xxxx",
"email": "username@domain.com",
"format_utterances": true
}
}
}
}'Method 2: Add formatting to existing transcripts
For existing transcripts, retrieve the completed transcript and send it to the Speech Understanding API:
bash
# Step 1: Get the completed transcript
transcript=$(curl -s -X GET \
"" \
-H "Authorization: YOUR_API_KEY")
# Step 2: Add custom formatting and send to Speech Understanding API
curl -X POST \
"" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transcript_id": "{transcript_id}",
"speech_understanding": {
"request": {
"custom_formatting": {
"date": "mm/dd/yyyy",
"phone_number": "(xxx)xxx-xxxx",
"email": "username@domain.com",
"format_utterances": true
}
}
}
}'| Key | Type | Required? | Description |
|---|---|---|---|
speech_understanding | object | Yes | Container for speech understanding requests. |
speech_understanding.request | object | Yes | The understanding request configuration. |
speech_understanding.request.custom_formatting | object | Yes | Custom formatting configuration. |
custom_formatting.date | string | No | Date format pattern. Common patterns: mm/dd/yyyy (US), dd/mm/yyyy (European), yyyy-mm-dd (ISO). |
custom_formatting.phone_number | string | No | Phone number format pattern. Examples: (xxx)xxx-xxxx, xxx-xxx-xxxx, xxx.xxx.xxxx. |
custom_formatting.email | string | No | Email format pattern. Example: username@domain.com. |
custom_formatting.format_utterances | boolean | No | When true, applies formatting to speaker utterances in addition to the main text. Preserves word-level timestamps. Default: false. |
Response
The Custom Formatting API returns your original transcript response with formatting applied to the text field and additional formatting details in the speech_understanding object. When format_utterances is enabled, formatted utterances with preserved timestamps are also included.
json
{
"id": "2accd7f2-445b-4d08-b10b-1bafdd5906ed",
"status": "completed",
"text": "Yes, I would appreciate it if you could call me back. My phone number is (555)679-3466...",
"speech_understanding": {
"request": {
"custom_formatting": {
"date": "mm/dd/yyyy",
"phone_number": "(xxx)xxx-xxxx",
"email": "username@domain.com",
"format_utterances": true
}
},
"response": {
"custom_formatting": {
"formatted_text": "Yes, I would appreciate it if you could call me back. My phone number is (555)679-3466...",
"formatted_utterances": [
{
"confidence": 0.9920061471354167,
"end": 26000,
"speaker": "A",
"start": 1920,
"text": "Yes, I would appreciate it if you could call me back. My phone number is (555)679-3466...",
"words": [
{
"speaker": "A",
"start": 1920,
"end": 2160,
"text": "Yes,",
"confidence": 0.808349609375
}
// ... more words
]
}
],
"mapping": {
"555-679-3466": "(555)679-3466",
"555-679-8244": "(555)679-8244"
},
"status": "success"
}
}
}
}| Key | Type | Description |
|---|---|---|
text | string | The transcript text with custom formatting applied. |
speech_understanding | object | Container for speech understanding request and response information. |
speech_understanding.request | object | The original custom formatting request configuration that was submitted. |
speech_understanding.request.custom_formatting | object | The formatting parameters that were used. |
speech_understanding.response | object | The response information from the formatting process. |
speech_understanding.response.custom_formatting | object | Details about the formatting operation. |
speech_understanding.response.custom_formatting.formatted_text | string | The complete transcript with custom formatting applied. Identical to the text field. |
speech_understanding.response.custom_formatting.formatted_utterances | array | Array of speaker utterances with formatting applied. Only present when format_utterances is true. Each utterance includes speaker label, timestamps, confidence scores, formatted text, and word-level details with preserved timestamps. |
speech_understanding.response.custom_formatting.mapping | object | An object showing the original text segments and their formatted versions. Keys are original text, values are formatted text. |
speech_understanding.response.custom_formatting.status | string | The status of the formatting operation. Will be "success" when formatting completes successfully. |
Understanding formatted_utterances
When format_utterances is enabled, each object in the formatted_utterances array contains:
| Field | Type | Description |
|---|---|---|
speaker | string | Speaker identifier (e.g., "A", "B") |
start | integer | Start time of the utterance in milliseconds |
end | integer | End time of the utterance in milliseconds |
text | string | The utterance text with custom formatting applied |
confidence | number | Confidence score for the utterance (0-1) |
words | array | Array of word objects with individual timestamps, text (formatted), confidence scores, and speaker labels |
Important: All timestamps in both utterances and words are preserved exactly as they appear in the original transcription, ensuring perfect temporal alignment with the audio even after formatting is applied.
Key differences from standard transcription
| Field | Standard Transcription | With Custom Formatting | With format_utterances=true |
|---|---|---|---|
text | Transcribed text with default formatting | Transcribed text with your custom formatting rules applied | Same as custom formatting |
speech_understanding | Not present | Object containing formatting request, response, and mapping | Same, plus formatted_text and formatted_utterances |
utterances | Speaker-separated segments with original text | Unchanged | Unchanged (original utterances remain) |
| Word timestamps | Original timestamps | Preserved exactly | Preserved exactly in formatted_utterances |
All other fields from the original transcript (words, utterances, confidence, etc.) remain unchanged. The formatted_utterances field provides an additional view of the data with formatting applied while maintaining complete timestamp fidelity.