Get Your API Key
An API key is required to use BizCrush APIs. You can create up to 5 keys from your account settings.
Speech-to-Text API
FeaturedSpeech-to-Text API for audio transcription with speaker diarization. Supports file-based (batch) and real-time (streaming) transcription.
Build Your Own STT Service
Use the BizCrush STT API to build your own speech-to-text service. Integrate real-time transcription into your apps, process audio files at scale, or create custom voice-powered workflows — all with speaker diarization and multi-language support.
Automatic language detection across 15 languages — no configuration required. Just send audio and get results.
Overview
Authentication
All STT requests require an API key passed as a query parameter:
?api_key=YOUR_API_KEY
You can issue your API key at bizcru.sh/settings.
File STT
Send an audio file URL and receive the full transcript with speaker diarization.
/stt
Auth: ?api_key
Transcribe an audio file URL and return the full transcript with speaker diarization.
Request Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
| audio_url | string | required | Public audio file URL (signed URL, CDN URL, etc.) |
| session_id | string | optional | Session identifier. Auto-generated if omitted |
| enable_diarization | boolean | optional | Enable speaker diarization (default: true) |
| language_hints | string[] | optional | Language codes, e.g. ["ko","en"] or "ko,en". Up to 3; extras dropped. Omit for auto-detection. Legacy `language_hint` (single string) also accepted. |
Response Fields
| Field | Type | Description |
|---|---|---|
| text | string | Full transcript text |
| detected_language | string | Detected language code |
| confidence | float | Average confidence (0~1) |
| utterances | array | Speaker-diarized utterance segments |
| utterances[].speaker | string | Speaker number ("0", "1", "2", ...) |
| utterances[].text | string | Utterance text |
| utterances[].start_ms | integer | Start time (milliseconds) |
| utterances[].end_ms | integer | End time (milliseconds) |
| utterances[].confidence | float | Utterance confidence |
| utterances[].language | string | Utterance language |
Response Example
{
"text": "Could you introduce yourself and tell us about your role?",
"detected_language": "en",
"confidence": 0.961,
"utterances": [
{
"speaker": "1",
"text": "Could you introduce yourself and tell us about your role?",
"start_ms": 960,
"end_ms": 5400,
"confidence": 0.94,
"language": "en"
},
{
"speaker": "2",
"text": "Sure. My name is Ethan Kim, and I'm CTO of BizCrush.",
"start_ms": 5820,
"end_ms": 9600,
"confidence": 0.96,
"language": "en"
}
]
}
cURL Example
curl -X POST \
"https://extapi.bizcrush.ai/v1/stt?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"audio_url": "https://example.com/audio.oga", "enable_diarization": true}'
Note: Response time depends on audio length — may take up to several minutes. Set timeout to 600+ seconds.
Live STT (WebSocket)
Real-time audio streaming transcription via WebSocket. Send audio chunks and receive interim/final results in real time.
wss://extapi.bizcrush.ai/v1/stt/stream
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| api_key | string | required | API key |
| format | string | optional | "json" for JSON text frames, omit for protobuf binary |
| reduce_noise | string | optional | "true" to enable DeepFilter real-time noise reduction |
| language_hints | string[] | optional | Language codes as comma-separated (?language_hints=ko,en) or repeated (?language_hints=ko&language_hints=en). Up to 3; extras dropped. Omit for auto-detection. |
Protocol
Send a JSON text frame with encoding and optional session_id
| Field | Type | Description |
|---|---|---|
| encoding | string | "pcm16" or "opus" (default: "pcm16") |
| session_id | string | Session identifier (optional, auto-generated if omitted) |
| language_hints | string[] | Optional language codes, e.g. ["ko","en"] or "ko,en". Up to 3 entries; extras dropped. Overrides query param. Omit for auto-detection. |
{"encoding": "pcm16", "session_id": "optional-session-id"}
Server responds with connection status
{"connected": true}
Send raw audio as binary WebSocket frames
| Encoding | Format | Chunk Size |
|---|---|---|
| pcm16 | 16kHz, mono, 16-bit little-endian | 640 bytes (20ms) recommended |
| opus | 16kHz, mono. Raw Opus packets or OGG/Opus container | Opus frame unit |
Server sends interim and final results as JSON text frames
| Field | Type | Description |
|---|---|---|
| chunk.id | string | Chunk ID — same across interim/final for one utterance, new ID after final |
| chunk.session_id | string | Session ID |
| chunk.text | string | Transcribed text (cumulative — each interim contains full text so far) |
| chunk.is_final | boolean | false: interim result, true: final confirmed result |
{"chunk": {"id": "01KMCHP57H31XYZABC", "session_id": "my-session", "text": "Hello, how are you?", "is_final": true}}
Examples
Python
import asyncio
import json
import websockets
async def live_stt(api_key: str):
url = f"wss://extapi.bizcrush.ai/v1/stt/stream?api_key={api_key}&format=json"
async with websockets.connect(url) as ws:
await ws.send(json.dumps({"encoding": "pcm16"}))
resp = json.loads(await ws.recv())
assert resp["connected"], f"Connection failed: {resp}"
async def send_audio():
with open("audio.pcm", "rb") as f:
while chunk := f.read(640):
await ws.send(chunk)
await asyncio.sleep(0.02)
await asyncio.sleep(3)
await ws.close()
async def receive_results():
try:
async for msg in ws:
data = json.loads(msg)
if "chunk" in data:
chunk = data["chunk"]
status = "FINAL" if chunk["is_final"] else "interim"
print(f"[{status}] {chunk['text']}")
except websockets.exceptions.ConnectionClosed:
pass
await asyncio.gather(send_audio(), receive_results())
asyncio.run(live_stt("YOUR_API_KEY"))
JavaScript (Browser)
const ws = new WebSocket(
"wss://extapi.bizcrush.ai/v1/stt/stream?api_key=YOUR_API_KEY&format=json"
);
ws.onopen = () => {
ws.send(JSON.stringify({ encoding: "pcm16" }));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.connected) {
console.log("Connected! Start sending audio...");
}
if (data.chunk) {
const { id, text, is_final } = data.chunk;
console.log(`[${is_final ? "FINAL" : "interim"}] ${text}`);
}
};
function sendAudioChunk(pcmData) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(pcmData);
}
}
Text-to-Speech (TTS)
Convert text to natural-sounding speech and receive a signed download URL (audio uploaded to Firebase Storage).
/tts
Auth: ?api_key
Generate speech audio from text and return a signed download URL (audio uploaded to Firebase Storage at tts/{session_id}/{message_id}.ogg).
Request Body (Protobuf)
application/x-protobuf (request and response are protobuf-encoded SessionTTSRequest / SessionTTSResponse)
| Name | Type | Required | Description |
|---|---|---|---|
| session_id | string | required | Session identifier |
| message_id | string | required | Message identifier (used in storage path) |
| text | string | required | Text to convert to speech |
Response Fields
| Field | Type | Description |
|---|---|---|
| audio_url | string | Signed download URL (Opus / OGG) — valid for several days |
| error | string | Set on failure; audio_url empty |
Supported Languages
Automatic language detection is built in — no configuration needed. The STT engine detects and transcribes across 15 languages seamlessly, even when speakers switch languages mid-conversation. Optionally use language_hint for faster detection.
| Code | Language |
|---|---|
| en | English |
| zh | 中文 |
| hi | हिन्दी |
| es | Español |
| ar | العربية |
| fr | Français |
| pt | Português |
| ru | Русский |
| id | Bahasa Indonesia |
| de | Deutsch |
| ja | 日本語 |
| vi | Tiếng Việt |
| it | Italiano |
| ko | 한국어 |
| th | ภาษาไทย |
STT Error Codes
| Status | Error | Description |
|---|---|---|
| 401 | Missing authorization | API key not provided |
| 401 | Invalid API key | Invalid API key |
| 400 | Empty request body | Request body is empty |
| 400 | Missing audio_url | audio_url field missing (File STT) |
| 400 | Missing session_id, message_id, or text | Required TTS field missing |
| 400 | Invalid JSON | JSON parsing failed |
| 500 | TTS generation failed | OpenAI TTS call failed |
| 500 | Storage upload failed | Firebase Storage upload failed |
| 500 | (varies) | Internal server error (transcription failure, etc.) |
| WS 1008 | Auth failure | WebSocket closed with code 1008 on authentication failure |
Meeting REST API
Authentication
All API requests require an X-API-Key header.
curl -X POST https://extapi.bizcrush.ai/v1/get-meetings \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{}'
You can issue your API key at bizcru.sh/settings.
Quick Start
Create a meeting and invite a participant in one request:
curl -X POST https://extapi.bizcrush.ai/v1/create-meeting \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"participant_ids": ["em:john@example.com"],
"title": "Weekly Standup"
}'
Response:
{
"meeting": {
"id": "01KNGVN84KR7T5CVDY9TTW7FFW",
"host_user_id": "0J56UlxXAS",
"participant_ids": ["0J56UlxXAS", "em:john@example.com"],
"status": "MS_LIVE",
"title": "Weekly Standup",
"language": "ko",
"translation_languages": ["ko", "en"]
}
}
Meetings
Create, delete, and list meetings.
/v1/create-meeting
Create a new meeting and optionally invite participants.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| participant_ids | list[str] | optional | Participant IDs. Formats: userId (no prefix), em:email@example.com |
| title | str | optional | Meeting title |
/v1/delete-meeting
Delete a meeting by ID.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID to delete |
/v1/get-meetings
List the authenticated user's meetings, newest first.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| last_updated_at | str | optional | Pagination cursor: fetch meetings updated before this time (RFC 3339) |
| limit | int | optional | Max results per page (default: 50, max: 50) |
Meeting Messages
Send, delete, and list meeting messages (text, summaries, etc.).
/v1/send-meeting-message
Send a text message to a meeting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_message | dict | required | Meeting message object with meeting_id and text fields |
/v1/delete-meeting-message
Delete a message from a meeting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| message_id | str | required | Message ID to delete |
/v1/get-meeting-messages
Get messages for a meeting (summaries, user messages, etc.).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| last_updated_at | str | optional | Pagination cursor (RFC 3339) |
| limit | int | optional | Max results per page (default: 50) |
Meeting AI
AI-powered meeting summarization and Q&A.
/v1/summarize-meeting
Generate an AI summary of a meeting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID to summarize |
| send_email_to_participants | bool | optional | Send summary email to participants (default: false) |
| user_prompt | str | optional | Custom prompt to guide summarization |
/v1/ask-ai-for-meeting
Ask AI a question about a meeting's content.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| message | dict | required | User question as {text: '...'} object |
| model | int | optional | LLM model enum value (0 = default) |
| attachment_urls | list[str] | optional | Attachment URLs (PDF, images, etc.) |
| source_content | str | optional | Existing markdown to edit (edit mode) |
| source_document_id | str | optional | Document ID for version chaining |
Meeting Cached Data
Retrieve cached meeting summaries and transcripts.
/v1/get-meeting-summary
Get the AI-generated summary of a meeting (cached).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| force_refresh | bool | optional | Force refresh from DB instead of cache |
/v1/get-meeting-transcripts
Get the full transcripts of a meeting (cached).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| force_refresh | bool | optional | Force refresh from DB instead of cache |
Meeting Participants
Add/remove participants and manage co-host roles.
/v1/add-meeting-participants
Add participants to a meeting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| participant_ids | list[str] | required | Participant IDs. Formats: userId, em:email@example.com |
/v1/remove-meeting-participants
Remove participants from a meeting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| participant_ids | list[str] | required | Participant IDs to remove |
/v1/assign-co-host
Assign co-host role to users in a meeting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| user_ids | list[str] | required | User IDs to assign as co-host |
/v1/remove-co-host
Remove co-host role from users in a meeting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| user_ids | list[str] | required | User IDs to remove co-host from |
Meeting Settings
Get and update default meeting settings (languages, keywords).
/v1/get-user-default-meeting-setting
Get the user's default meeting settings.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| device_language_code | str | optional | IETF BCP-47 language code (default: 'en') |
/v1/update-user-default-meeting-setting
Update the user's default meeting settings.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| original_languages | list[str] | optional | STT input languages (IETF BCP-47) |
| view_language | str | optional | Document generation language (default: 'en') |
| translation_languages | list[str] | optional | Translation target languages |
| contextual_keywords | list[str] | optional | Keywords to help AI understand meeting context |
Transcription
Access live transcription chunks, finalized utterances, and corrections.
/v1/get-live-transcription-chunks
Get real-time transcription chunks for a meeting.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| last_updated_at | str | required | Pagination cursor (RFC 3339). Use '1970-01-01T00:00:00Z' for first page |
| message_id | str | optional | Filter by message ID |
| limit | int | optional | Max results (default: 100) |
/v1/get-transcript-utterances
Get finalized transcript utterances with confidence scores.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| meeting_id | str | required | Meeting ID |
| last_updated_at | str | required | Pagination cursor (RFC 3339). Use '1970-01-01T00:00:00Z' for first page |
| message_id | str | optional | Filter by message ID |
| limit | int | optional | Max results (default: 100) |
/v1/update-transcript-utterance
Correct a transcribed utterance's text.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | str | required | Utterance document ID |
| meeting_id | str | required | Meeting ID |
| transcript | str | required | Corrected transcript text |
Notion
Upload meeting summaries to Notion.
/v1/upload-meeting-to-notion
Upload a meeting summary to a Notion workspace.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| user_id | str | required | User ID (for retrieving Notion access token) |
| meeting_id | str | required | Meeting ID to upload |
People
List contacts and people.
/v1/get-my-people
List the authenticated user's contacts.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| cursor | str | optional | Pagination cursor (name:email format) |
| limit | int | optional | Results per page (default: 20) |
Error Handling
The API returns standard HTTP status codes with JSON error bodies:
| Status | Description |
|---|---|
| 401 | Invalid or missing API key |
| 400 | Invalid request body (validation error) |
| 404 | Resource not found (invalid meeting/message ID) |
| 500 | Internal server error |
{
"success": false,
"error": "Meeting not found",
"code": "NOT_FOUND"
}
Zapier Integration
Overview
Connect BizCrush with your favorite tools through our Zapier integration. Automatically capture meeting summaries, generate AI documents, and push insights to Slack, Notion, Google Docs, and more.
Triggers
4 polling triggers that detect new meetings, summaries, contacts, and follow-up emails.
Actions
2 actions to retrieve meeting details and generate AI documents with custom prompts.
Authentication
Zapier uses OAuth 2.0 (Authorization Code flow). The token lifecycle is managed automatically by Zapier.
OAuth 2.0 Flow
| Step | Description | Endpoint |
|---|---|---|
| 1 | Authorization — User is redirected to BizCrush to grant access | GET /oauth/zapier/authorize |
| 2 | Token Exchange — Authorization code is exchanged for access and refresh tokens | POST /api/oauth/zapier/token |
| 3 | API Requests — Access token is sent as a Bearer token | Authorization: Bearer <access_token> |
Test Connection
/api/zapier/me
Auth: Bearer Token
curl https://bizcru.sh/api/zapier/me \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response Example
{
"user_id": "abc123",
"email": "user@example.com",
"display_name": "John Doe"
}
Triggers
Polling-based triggers. Zapier calls these periodically to detect new data. All triggers return arrays sorted by date (newest first), max 50 items.
/api/zapier/triggers/meeting-ended
Auth: Bearer Token
Meeting Ended
Fires when a meeting you participated in has ended. Returns up to 50 recent ended meetings.
Response Fields
| Field | Type | Description |
|---|---|---|
| id | string | Meeting ID (deduplication key) |
| title | string | Meeting title |
| start_at | ISO 8601 | Meeting start time |
| end_at | ISO 8601 | Meeting end time |
| language | string | Meeting language (e.g., "ko", "en") |
| host_user_id | string | Host user ID |
| participant_count | number | Number of participants |
| tags | string[] | Meeting tags |
Response Example
[
{
"id": "01KMHVN8JX62M7HPS2H4GNXVR8",
"title": "Weekly Standup",
"start_at": "2025-01-15T09:00:00.000Z",
"end_at": "2025-01-15T10:30:00.000Z",
"language": "en",
"host_user_id": "abc123",
"participant_count": 3,
"tags": ["standup", "weekly"]
}
]
/api/zapier/triggers/summary-ready
Auth: Bearer Token
Summary Ready
Fires when an AI-generated summary is ready for one of your meetings.
Response Fields
| Field | Type | Description |
|---|---|---|
| id | string | Summary message ID (deduplication key) |
| meeting_id | string | Meeting ID |
| meeting_title | string | Meeting title |
| ai_model | string | AI model used for generation |
| markdown_body | string | Summary content in Markdown |
| created_at | ISO 8601 | Summary creation time |
Response Example
[
{
"id": "summary_msg_id",
"meeting_id": "01KMHVN8JX62M7HPS2H4GNXVR8",
"meeting_title": "Weekly Standup",
"ai_model": "gpt-4o",
"markdown_body": "## Meeting Summary\n- Discussed project updates...",
"created_at": "2025-01-15T10:35:00.000Z"
}
]
/api/zapier/triggers/contact-discovered
Auth: Bearer Token
Contact Discovered
Fires when a new contact (guest profile) is discovered from a meeting.
Response Fields
| Field | Type | Description |
|---|---|---|
| id | string | Contact message ID (deduplication key) |
| meeting_id | string | Meeting ID |
| meeting_title | string | Meeting title |
| name | string | Contact name |
| string | Contact email | |
| company_name | string | Company name |
| company_position | string | Job title / position |
| linkedin_id | string | LinkedIn profile ID |
| created_at | ISO 8601 | Discovery time |
Response Example
[
{
"id": "contact_msg_id",
"meeting_id": "01KMHVN8JX62M7HPS2H4GNXVR8",
"meeting_title": "Sales Call",
"name": "John Doe",
"email": "john@example.com",
"company_name": "Acme Inc",
"company_position": "CEO",
"linkedin_id": "johndoe",
"created_at": "2025-01-15T11:00:00.000Z"
}
]
/api/zapier/triggers/followup-email-ready
Auth: Bearer Token
Follow-up Email Ready
Fires when an AI-generated follow-up email is ready for a meeting.
Response Fields
| Field | Type | Description |
|---|---|---|
| id | string | Email message ID (deduplication key) |
| meeting_id | string | Meeting ID |
| meeting_title | string | Meeting title |
| subject | string | Email subject line |
| body_html | string | Email body in HTML |
| created_at | ISO 8601 | Email generation time |
Response Example
[
{
"id": "email_msg_id",
"meeting_id": "01KMHVN8JX62M7HPS2H4GNXVR8",
"meeting_title": "Sales Call",
"subject": "Follow up from our meeting",
"body_html": "<p>Thank you for the meeting.</p>",
"created_at": "2025-01-15T11:10:00.000Z"
}
]
Actions
Actions that Zapier users can trigger in their Zaps.
/api/zapier/meetings/{id}
Auth: Bearer Token
Get Meeting Details
Retrieve detailed information about a specific meeting, including its latest AI summary.
Path Parameters
| Parameter | Required | Description |
|---|---|---|
| id | required | Meeting ID |
Response Example
{
"id": "01KMHVN8JX62M7HPS2H4GNXVR8",
"title": "Q1 Planning Meeting",
"start_at": "2025-01-15T09:00:00.000Z",
"end_at": "2025-01-15T10:30:00.000Z",
"language": "en",
"host_user_id": "abc123",
"participant_count": 4,
"tags": ["planning", "q1"],
"latest_summary": {
"ai_model": "gpt-4o",
"markdown_body": "## Key Decisions\n- Approved Q1 budget...",
"created_at": "2025-01-15T10:35:00.000Z"
}
}
/api/zapier/meetings/{id}/generate-document
Auth: Bearer Token
Generate AI Document
Generate an AI document from a meeting using a custom prompt. Supports asynchronous callback delivery for long-running generations.
Path Parameters
| Parameter | Required | Description |
|---|---|---|
| id | required | Meeting ID |
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| prompt | str | required | — | Custom prompt for document generation (e.g., "Summarize key decisions and action items") |
| model | str | optional | gpt-4o | AI model — gpt-4o (default) or claude |
| callback_url | str | optional | — | URL to receive async results (used by Zapier automatically) |
Response Example
// Sync response (no callback)
{
"success": true,
"meeting_id": "01KMHVN8...",
"document_text": "## Summary\n...",
"message": "AI document generation requested."
}
Async Callback Response
// Async: initial response (immediate)
{
"success": true,
"meeting_id": "01KMHVN8...",
"message": "AI document generation started. Result will be delivered via callback."
}
// Async: callback POST to callback_url (after AI completes)
{
"status": "success",
"meeting_id": "01KMHVN8...",
"document_text": "# Detailed AI Document\n\n## Key Decisions\n- ...",
"created_at": "2025-01-15T10:40:00.000Z"
}