Dropbox AI: transcribe and analyze every audio and video file
Speak AI watches your Dropbox folder, transcribes every audio and video file in 100+ languages, and pushes structured results to your CRM, BI, or back into Dropbox as a text file. Set up a Dropbox webhook in minutes or drag a share link into Speak. No manual downloads, no re-uploads.
What you can do
Once Dropbox files flow into Speak AI, every audio and video file becomes searchable, analyzable, and shareable. Legal teams get depositions auto-transcribed. Podcast teams get episode transcripts and summaries. Research teams turn field recordings into structured Notion writeups. Customer success teams route call recordings by sentiment to the right channel.
Auto-transcribe every Dropbox file
Connect a Dropbox webhook to your handler and every new audio or video file that lands in a folder is automatically downloaded and sent to Speak for transcription. Or paste a Dropbox share link directly into Speak’s uploader. Works for MP3, MP4, WAV, M4A, MOV, WEBM, and dozens more formats.
Speaker-labeled transcript in 100+ languages
Auto-detected language. Typical processing: under 2 minutes per hour of audio. Document and sentence-level VADER sentiment scoring. Speaker diarization across the full file. Output is editable, exportable to DOCX/SRT/PDF/JSON, and queryable through the Speak app.
Write transcripts and summaries back to Dropbox
After Speak processes a file, push the transcript or AI summary back as a .txt or .md file to the same Dropbox folder. Use POST https://content.dropboxapi.com/2/files/upload from your media.analyzed webhook handler. Your team gets a transcript alongside the original without leaving Dropbox.
One-click push to HubSpot, Salesforce, or Zoho
Verified webhook recipe: receive Speak’s media.analyzed event, fetch the insight, create a CRM activity. Same pattern across HubSpot Meetings, Salesforce Tasks, and Zoho Calls. Source-tagged with dropbox so reports can split Dropbox-sourced files vs live calls.
Set up in 3 steps
The fastest path takes 30 seconds: paste a Dropbox share link into Speak’s uploader. The webhook automation path takes about 5 minutes: create a Dropbox App, register a webhook callback, and handle the notification payload. The cron folder scan path requires no webhook handler at all.
Sign up for Speak AI
Create a free account at app.speakai.co. You get a 7-day trial with full access. No credit card needed. Once you are in, go to Settings > API and copy your API key.
Pick your integration path
Open any Dropbox file, click Share, and copy the share link. Append ?dl=1 to force a direct download URL. Paste the URL into Speak’s uploader field. Speak fetches the file, transcribes it, and lands the result in your library. Zero configuration – works for any file in any Dropbox folder.
Create a Dropbox App at dropbox.com/developers/apps, scope it to the target folder (recommended: Files and folders – Single folder or Full Dropbox), and register a webhook URI in the App Console under Webhooks. When a file is added, Dropbox POSTs a thin notification to your handler: {"list_folder": {"accounts": ["dbid:..."]}, "delta": {...}}. Your handler then calls POST /2/files/list_folder/continue with the cursor, downloads the new file via POST https://content.dropboxapi.com/2/files/download, and sends it to Speak’s POST /v1/media/upload. Full recipe in Tab 1 below.
For teams that do not want to run a webhook handler: set up a cron job that calls POST /2/files/list_folder/continue using a stored cursor. Compare the file list to what has been processed, download new files, and upload to Speak. Simpler to operate; latency is the cron interval rather than near-real-time.
Already have Dropbox files in Speak? Connect Claude Desktop with npx @speakai/mcp-server init, or add the remote MCP URL to Claude.ai or ChatGPT. Search and synthesize the entire Dropbox-sourced library through conversation.
Subscribe to media.analyzed
Speak fires a signed webhook when transcription and AI analysis complete (usually within 60 seconds for a 10-minute file). Register your endpoint via POST /v1/webhook and act on transcripts as they land – write them back to Dropbox, push to your CRM, or route by sentiment to the right Slack channel.
Real workflows, real results
Four production patterns Speak customers ship with Dropbox. Pick the one that fits your team and copy the recipe.
Auto-transcribe every file that lands in a Dropbox folder
Create a Dropbox App, register a webhook callback URI, and let Dropbox notify your handler whenever a file is added. Your handler downloads the file from Dropbox and sends it to Speak. Near-real-time: typically processed within 60-90 seconds of the file landing in Dropbox.
# 1. Go to https://www.dropbox.com/developers/apps
# 2. Click "Create app" -> "Scoped access" -> "Single folder" (recommended) or "Full Dropbox"
# 3. Name your app, e.g. "speak-transcriber"
# 4. Under "Permissions" tab: enable files.content.read (and files.content.write if writing back)
# 5. Under "Webhooks" tab: add your callback URL, e.g. https://your-app.example.com/dropbox/webhook
# 6. Dropbox sends a GET challenge first -- your handler must echo back the "challenge" query param
# 7. Store the app secret as DROPBOX_APP_SECRET and the access token as DROPBOX_TOKEN in your .env
import express from "express";
import fetch from "node-fetch";
const app = express();
app.use(express.json());
// Dropbox webhook verification challenge (GET)
app.get("/dropbox/webhook", (req, res) => {
res.send(req.query.challenge);
});
// Dropbox webhook notification (POST) - thin payload, just account IDs
app.post("/dropbox/webhook", async (req, res) => {
res.sendStatus(200); // Respond immediately
const accounts = req.body?.list_folder?.accounts ?? [];
for (const account of accounts) {
await processDropboxAccount(account);
}
});
async function processDropboxAccount(account) {
// 1. List changed files using stored cursor (or "" for first run)
const cursor = await getCursor(account); // implement storage lookup
const listRes = await fetch(
"https://api.dropboxapi.com/2/files/list_folder/continue",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DROPBOX_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ cursor }),
}
).then(r => r.json());
await storeCursor(account, listRes.cursor); // store new cursor
const audioVideoExts = /\.(mp3|mp4|wav|m4a|mov|webm|aac|ogg|flac)$/i;
for (const entry of listRes.entries ?? []) {
if (entry[".tag"] !== "file" || !audioVideoExts.test(entry.name)) continue;
// 2. Download file from Dropbox
const fileBuffer = await fetch(
"https://content.dropboxapi.com/2/files/download",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DROPBOX_TOKEN}`,
"Dropbox-API-Arg": JSON.stringify({ path: entry.path_display }),
},
}
).then(r => r.buffer());
// 3. Upload to Speak AI
const form = new FormData();
form.append("name", entry.name);
form.append("tags", "dropbox");
form.append("file", new Blob([fileBuffer]), entry.name);
await fetch("https://api.speakai.co/v1/media/upload", {
method: "POST",
headers: { "x-speakai-key": process.env.SPEAK_API_KEY },
body: form,
});
}
}
app.listen(3000);
import os, hmac, hashlib, requests
from fastapi import FastAPI, Request, Response
app = FastAPI()
AUDIO_VIDEO_EXTS = {".mp3", ".mp4", ".wav", ".m4a", ".mov", ".webm", ".aac", ".ogg", ".flac"}
# Dropbox webhook verification challenge (GET)
@app.get("/dropbox/webhook")
async def verify(request: Request):
return Response(content=request.query_params["challenge"], media_type="text/plain")
# Dropbox webhook notification (POST)
@app.post("/dropbox/webhook")
async def webhook(request: Request):
body = await request.json()
accounts = body.get("list_folder", {}).get("accounts", [])
for account in accounts:
process_dropbox_account(account)
return {"ok": True}
def process_dropbox_account(account: str):
headers = {"Authorization": f"Bearer {os.environ['DROPBOX_TOKEN']}",
"Content-Type": "application/json"}
cursor = get_cursor(account) # implement storage lookup
list_res = requests.post(
"https://api.dropboxapi.com/2/files/list_folder/continue",
headers=headers, json={"cursor": cursor}, timeout=30
).json()
store_cursor(account, list_res["cursor"])
for entry in list_res.get("entries", []):
if entry.get(".tag") != "file":
continue
ext = os.path.splitext(entry["name"])[1].lower()
if ext not in AUDIO_VIDEO_EXTS:
continue
# Download from Dropbox
file_bytes = requests.post(
"https://content.dropboxapi.com/2/files/download",
headers={
"Authorization": f"Bearer {os.environ['DROPBOX_TOKEN']}",
"Dropbox-API-Arg": f'{{"path": "{entry["path_display"]}"}}'
},
timeout=120
).content
# Upload to Speak AI
requests.post(
"https://api.speakai.co/v1/media/upload",
headers={"x-speakai-key": os.environ["SPEAK_API_KEY"]},
files={"file": (entry["name"], file_bytes)},
data={"name": entry["name"], "tags": "dropbox"},
timeout=300,
)
Dropbox sends a GET challenge before activating your webhook URL. Your handler must respond with req.query.challenge (Node) or request.query_params["challenge"] (Python) and return HTTP 200. Scope your Dropbox App token to files.content.read only unless you also need write-back (Tab 2).
Push the transcript back to Dropbox as a text file
After Speak finishes processing a Dropbox file, write the transcript and AI summary back to Dropbox alongside the original. Your team gets a .txt or .md file in the same folder without switching tools.
media.analyzed webhookcurl -X POST https://api.speakai.co/v1/webhook \
-H "x-speakai-key: $SPEAK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"callbackUrl": "https://your-app.example.com/speak/dropbox-writeback",
"events": ["media.analyzed"],
"description": "Write Speak transcript back to Dropbox"
}'
// Speak posts: { eventType, state, mediaId } (verified 2026-05-07)
import express from "express";
const app = express();
app.use(express.json());
app.post("/speak/dropbox-writeback", async (req, res) => {
const { eventType, state, mediaId } = req.body;
if (eventType !== "media.analyzed" || state !== "processed") return res.sendStatus(204);
res.sendStatus(202);
// 1. Fetch transcript from Speak
const transcript = await fetch(
`https://api.speakai.co/v1/media/${mediaId}/transcript`,
{ headers: { "x-speakai-key": process.env.SPEAK_API_KEY } }
).then(r => r.json());
// 2. Fetch insight for the summary
const insight = await fetch(
`https://api.speakai.co/v1/media/insight/${mediaId}`,
{ headers: { "x-speakai-key": process.env.SPEAK_API_KEY } }
).then(r => r.json());
const media = insight.data;
const transcriptText = (transcript.data?.paragraphs ?? [])
.map(p => `[${p.speaker || "Speaker"}] ${p.text}`)
.join("\n\n");
const outputContent = [
`# ${media.name}`,
`Processed: ${new Date(media.updatedAt).toISOString()}`,
"",
"## Transcript",
transcriptText,
].join("\n");
// 3. Write back to Dropbox - same folder as original, with -transcript.txt suffix
const originalPath = media.tags?.find(t => t.startsWith("dropbox-path:"))?.replace("dropbox-path:", "");
const outputPath = originalPath
? originalPath.replace(/(\.[^.]+)$/, "-transcript.txt")
: `/transcripts/${mediaId}-transcript.txt`;
await fetch("https://content.dropboxapi.com/2/files/upload", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DROPBOX_TOKEN}`,
"Content-Type": "application/octet-stream",
"Dropbox-API-Arg": JSON.stringify({
path: outputPath,
mode: "overwrite",
autorename: false,
}),
},
body: outputContent,
});
});
app.listen(3000);
import os, requests
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/speak/dropbox-writeback")
async def hook(req: Request):
body = await req.json()
if body.get("eventType") != "media.analyzed" or body.get("state") != "processed":
return {"ok": True}
media_id = body["mediaId"]
# 1. Fetch transcript from Speak
transcript = requests.get(
f"https://api.speakai.co/v1/media/{media_id}/transcript",
headers={"x-speakai-key": os.environ["SPEAK_API_KEY"]},
timeout=30,
).json()
# 2. Fetch insight for summary
insight = requests.get(
f"https://api.speakai.co/v1/media/insight/{media_id}",
headers={"x-speakai-key": os.environ["SPEAK_API_KEY"]},
timeout=30,
).json()["data"]
paragraphs = transcript.get("data", {}).get("paragraphs", [])
transcript_text = "\n\n".join(
f"[{p.get('speaker', 'Speaker')}] {p['text']}" for p in paragraphs
)
output_content = "\n".join([
f"# {insight['name']}",
f"Processed: {insight.get('updatedAt', '')}",
"",
"## Transcript",
transcript_text,
])
# 3. Write back to Dropbox
tags = insight.get("tags") or []
original_path = next((t.replace("dropbox-path:", "") for t in tags if t.startswith("dropbox-path:")), None)
if original_path:
import re
output_path = re.sub(r"(\.[^.]+)$", "-transcript.txt", original_path)
else:
output_path = f"/transcripts/{media_id}-transcript.txt"
requests.post(
"https://content.dropboxapi.com/2/files/upload",
headers={
"Authorization": f"Bearer {os.environ['DROPBOX_TOKEN']}",
"Content-Type": "application/octet-stream",
"Dropbox-API-Arg": f'{{"path": "{output_path}", "mode": "overwrite", "autorename": false}}',
},
data=output_content.encode("utf-8"),
timeout=30,
)
return {"ok": True}
Tag each Dropbox-sourced media with dropbox-path:/your/folder/file.mp3 during upload so the write-back handler knows where to put the transcript. Requires files.content.write scope on your Dropbox App token.
Log every Dropbox-sourced call in HubSpot, Salesforce, or Zoho
Same verified middleware pattern as the rest of the integrations cluster: receive Speak’s flat {eventType, state, mediaId} notification, fetch full insight via GET /v1/media/insight/:mediaId, then create the CRM activity. Source-tag with dropbox so reports can split Dropbox-sourced files vs live call recordings.
// Speak webhook body shape (verified 2026-05-07): { eventType, state, mediaId }
import express from "express";
const app = express();
app.use(express.json());
app.post("/speak/dropbox-to-crm", async (req, res) => {
const { eventType, state, mediaId } = req.body;
if (eventType !== "media.analyzed" || state !== "processed") return res.sendStatus(204);
res.sendStatus(202);
// 1. Fetch full insight
const { data } = await fetch(
`https://api.speakai.co/v1/media/insight/${mediaId}`,
{ headers: { "x-speakai-key": process.env.SPEAK_API_KEY } }
).then(r => r.json());
// Skip files not tagged as Dropbox-sourced (optional filter)
if (!data.tags?.includes("dropbox")) return;
// 2. Push to HubSpot Meetings (or Salesforce Tasks, or Zoho Calls)
const start = new Date(data.createdAt);
const end = new Date(start.getTime() + (data.duration?.inSecond || 0) * 1000);
await fetch("https://api.hubapi.com/crm/v3/objects/meetings", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.HUBSPOT_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
properties: {
hs_timestamp: start.toISOString(),
hs_meeting_title: data.name,
hs_meeting_body: `Dropbox file transcript. Open in Speak: https://app.speakai.co/media/${mediaId}`,
hs_meeting_external_url: `https://app.speakai.co/media/${mediaId}`,
hs_meeting_start_time: start.toISOString(),
hs_meeting_end_time: end.toISOString(),
hs_meeting_outcome: "COMPLETED",
},
}),
});
});
app.listen(3000);
Full destination-specific code (HubSpot Meeting + association IDs, Salesforce Task + SOQL contact resolution, Zoho Calls + Notes) on /integrations/hubspot/, /integrations/salesforce/, and /integrations/zoho/. The Speak side is identical across all three CRM destinations.
Search every Dropbox file from Claude or ChatGPT
Connect Speak’s MCP server to Claude or ChatGPT and your team queries the entire Dropbox-sourced library through conversation. No SQL, no dashboards, no exports.
# Claude Desktop / Claude Code (auto-detects your installation)
npx @speakai/mcp-server init
# Paste your Speak API key when prompted. Setup takes about 2 minutes.
# Claude.ai (web) and ChatGPT MCP connector
# Settings > Integrations > Add MCP Server
# Remote URL: https://api.speakai.co/v1/mcp
# Auth header: x-speakai-key: YOUR_SPEAK_API_KEY
# Verify the connection responds:
curl -s https://api.speakai.co/v1/mcp \
-H "x-speakai-key: $SPEAK_API_KEY" \
-H "Accept: application/json"
2. Example prompts your team can use today:
- “Show every Dropbox recording from last month tagged
legalwhere a speaker used negative language.” - “Summarize the 5 longest podcast episode recordings imported from Dropbox this quarter.”
- “Pull verbatim quotes from Dropbox customer call recordings where the topic was pricing or onboarding.”
- “Compare key themes across 20 Dropbox field interview recordings. Group by sentiment.”
- “Find every Dropbox file where a speaker mentioned a competitor. Pull timestamps.”
Works with Claude.ai, Claude Desktop, Claude Code, and ChatGPT MCP connectors. Tag Dropbox imports with dropbox to scope MCP queries to that source. View MCP server →
Why Speak AI + Dropbox
Dropbox stores the files. Speak turns those files into structured data. The combination handles the full pipeline from file arrival to CRM entry, compliance archive, or research deliverable – without manual downloads or tool switching.
Multi-source ingest, not just Dropbox
Dropbox is one of dozens of inputs. The same Speak workspace ingests Zoom recordings, Google Meet exports, live recorder submissions, podcast audio, and direct file uploads. One searchable library, every audio and video source your team uses.
Custom Magic Prompts, not fixed templates
Speak’s Magic Prompt runs your prompts on every Dropbox file: legal deposition key-claim extraction, podcast highlight identification, customer objection scoring, competitor mention tagging. Save prompts once, run them on every file that lands in the folder forever.
SOC 2 + GDPR + HIPAA-eligible
Speak ships with SOC 2 Type 2, GDPR compliance, and HIPAA-eligible plans for healthcare and legal customers. Your Dropbox file data is encrypted in transit and at rest, and Speak does not train on your conversations.
MCP-native for Claude and ChatGPT
The official @speakai/mcp-server exposes 83 tools to AI assistants. Your team queries the Dropbox file library in plain English from Claude Desktop or ChatGPT, without exporting transcripts to other tools.
Teams trust Speak AI for their most important recordings
4.9 on G2
“Speak AI has been instrumental in transforming how we handle qualitative data. The transcription accuracy is impressive, and the NLP insights save us hours of manual analysis.”
Research Director | Consulting Firm
“We switched from Otter.ai and the depth of analysis is on another level. Sentiment scoring, keyword extraction, and theme detection all happen automatically.”
Product Manager | SaaS Company
“The ability to search across all our customer recordings and pull specific moments is a game-changer for our support team.”
Head of CX | Enterprise Tech
How to use Speak AI with Dropbox for transcription and file analysis
Dropbox is the file storage platform used by millions of teams to store audio and video files: legal depositions, customer call exports, podcast episodes, lecture recordings, field research interviews, and batch ingest from voice recorders. Every one of those files is a potential source of insight, decisions, and follow-up actions. Speak AI is what turns those files into structured, searchable, shareable data – without a manual export step or a tool switch.
Where Speak fits in the Dropbox file pipeline
Speak runs after the file lands in Dropbox. Dropbox handles storage, sync, versioning, and sharing. Speak handles transcription in 100+ languages, AI analysis with custom Magic Prompts, cross-file search, and downstream automation. The handoff happens via a Dropbox webhook (Path B), a cron folder scan (Path C), or a direct share link paste (Path A). After processing, Speak can write the transcript back to Dropbox, push to your CRM, or expose everything via MCP for Claude and ChatGPT.
How Dropbox webhooks work with Speak
Dropbox webhook notifications are thin: Dropbox sends your callback URL a POST with the account IDs that changed, not the file content. Your handler must then call POST /2/files/list_folder/continue with a stored cursor to find out which files changed, download each one via POST https://content.dropboxapi.com/2/files/download, and upload to Speak’s POST /v1/media/upload. This two-step notification + fetch pattern is standard for Dropbox. Speak does not have a direct Dropbox OAuth – the webhook handler pattern above is the production path.
How do I transcribe Dropbox files automatically?
Three production paths, ranked by lift:
- Share link paste. Copy any Dropbox file’s share link, append
?dl=1, and paste it into Speak’s upload URL field. Speak fetches the file and transcribes it. Zero setup. Works for any file in any Dropbox folder. - Dropbox webhook handler. Create a Dropbox App, register a webhook URI, and let Dropbox notify your handler whenever a file is added. Your handler downloads and uploads to Speak. Near-real-time.
- Cron folder scan. Poll
/2/files/list_folder/continueon a schedule, compare to processed files, upload new ones to Speak. No webhook server required.
All three deliver the same output: full speaker-labeled transcript, AI summary, sentiment, action items, plus structured CRM push and optional Dropbox write-back via the files/upload API.
Can Speak write transcripts back to Dropbox?
Yes. After Speak fires a media.analyzed webhook, your handler fetches the transcript from GET /v1/media/:mediaId/transcript, formats it as a .txt or .md file, and POSTs it back to Dropbox via POST https://content.dropboxapi.com/2/files/upload with Dropbox-API-Arg: {"path": "/your/folder/file-transcript.txt", "mode": "overwrite"}. The token needs files.content.write scope. Full recipe in Tab 2 above.
Use cases by role
Legal teams use Speak with Dropbox to auto-transcribe deposition recordings, court proceeding exports, and client interview files that land in a secure Dropbox folder. Magic Prompts extract key claims, deadlines, and speaker assignments. HIPAA-eligible plans and SOC 2 compliance meet legal data requirements.
Podcast and content teams pipe recorded episodes from Dropbox into Speak. Transcripts land back in Dropbox alongside the audio file. Show notes, chapter markers, and highlight clips are generated automatically via Magic Prompts and exported to the content team’s CMS or Notion.
Customer research teams bring field interview recordings from Dropbox into the same workspace as their Zoom and embed recorder sessions. Code themes across the entire library, ask Claude for verbatim quotes via MCP, and build research deliverables in hours instead of weeks. See Speak AI for qualitative researchers.
Sales and RevOps teams export recorded customer calls from their dialer or conferencing tool into Dropbox, then Speak auto-ingests, transcribes, and pushes each call to HubSpot, Salesforce, or Zoho with Magic Prompt scoring on discovery completeness and objection handling. See Speak AI for sales teams.
Frequently asked questions
Does Speak access my entire Dropbox?
No. When you create a Dropbox App for the webhook path, you can scope it to a single folder (recommended) or Full Dropbox. If you use the share link path, Speak only fetches the specific file you share – it has no access to your broader Dropbox. Use the Single Folder scope in your Dropbox App for least-privilege access.
How do I limit Speak to one Dropbox folder?
When creating your Dropbox App at dropbox.com/developers/apps, choose “Single folder” under “Choose the type of access.” The app token is then scoped only to that folder. Your webhook handler only receives notifications for files in that folder. This is the recommended approach for production pipelines.
What audio and video file types does Speak support?
Speak processes MP3, MP4, WAV, M4A, MOV, WEBM, AAC, OGG, FLAC, and most other common audio and video formats. If you upload a file type that is not supported, Speak returns an error on the upload request. For a full list, see the Speak API docs.
Can I write transcripts back to Dropbox automatically?
Yes. Register a media.analyzed webhook in Speak, and when a Dropbox file finishes processing, your handler fetches the transcript and POSTs it back to Dropbox via POST https://content.dropboxapi.com/2/files/upload with your token (needs files.content.write scope). Tab 2 above has the full Node and Python recipes.
How do I scope the Dropbox token?
In the Dropbox App Console under Permissions, enable only what your pipeline needs. For read-only ingest: files.content.read. For write-back: also add files.content.write. For folder listing via webhook: also add files.metadata.read. Avoid account-wide tokens – use app tokens scoped to the target folder and the minimum permission set.
Can I limit the folder scan to new files only?
Yes, using cursors. On first run, call POST /2/files/list_folder to get an initial cursor. Store it. On each subsequent run (webhook notification or cron), call POST /2/files/list_folder/continue with the stored cursor. Dropbox returns only the delta since the last cursor – new and modified entries only. Update the stored cursor after each call.
Start using Speak AI with Dropbox today
83 analysis tools. 100+ languages. Dropbox webhook, transcript write-back, CRM push, and MCP-native for Claude and ChatGPT. Same workspace as your Zoom, Meet, Teams, and live recorder sessions.
Try Speak AI free
Create your account, paste a Dropbox share link into the uploader, and the transcript lands in your Speak workspace automatically. Full access for 7 days. No credit card required.
Book a demo
For teams evaluating Speak for a Dropbox-connected batch processing pipeline, book a 30-minute demo with the Speak team. We will walk through the webhook setup, transcript write-back, and CRM push live.





