Send call transcripts from any tool: the custom inbound
Wire Zapier, n8n, or your own scripts to deliver call transcripts to Wren — the endpoint, payload format, and request signing explained.
Beyond the built-in recorder connections (Fathom, Fireflies, Granola), Wren can accept call transcripts from anything that can send a signed JSON request — Zapier, n8n, a script, or another product you use.
Create your endpoint
Open Settings → Connected Accounts, select the Recorder tab, and find the Custom inbound card. Click Create endpoint and Wren mints two things:
- a webhook URL — treat it like a password; it identifies your account
- a signing secret — shown only once, right then
Copy both into the tool that will send transcripts. If you lose the secret, use Rotate secret on the card: it mints a new secret while keeping the URL exactly the same, so you only update the secret in your tools.
There is one custom endpoint per account. Every tool you wire shares the same URL and secret, and rotating the secret applies to all of them at once.
Signing requests
Every request must carry a signature header:
- Header:
x-wren-signature - Value: HMAC-SHA256 of the raw request body, using your signing secret as the key, encoded as hex
sig=$(printf '%s' "$body" | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1)
curl -X POST "$URL" \
-H "content-type: application/json" \
-H "x-wren-signature: $sig" \
-d "$body"
Sign the exact bytes you send — serialize your JSON first, then sign that string. A missing or invalid signature is rejected and nothing is stored.
Payload format
{
"externalId": "mytool:abc123", // required — see below
"title": "Call with Sarah", // optional; exclusion rules match on it
"startedAt": "2026-08-11T17:00:00Z", // optional; ISO 8601 or epoch
"durationMs": 1800000, // optional; must be > 0 or it's ignored
"summary": "One-line recap", // optional
"participants": [ // optional
{ "name": "Jacob", "email": "jacob@example.com" }
],
// Exactly ONE of these two carries the transcript:
"segments": [
{ "speaker": "Jacob", "text": "…", "startMs": 0 },
{ "speaker": "Sarah", "text": "…", "startMs": 12000 }
],
// — or —
"text": "The full transcript as plain text."
}
Rules the payload must follow:
externalIdis required and should be prefixed per tool (for examplezapier:run-4211). Wren deduplicates on it, and every tool shares the one custom connection — two tools both sending"1"would collide. Keep it under 512 characters.- The transcript must actually contain text: an empty
segmentsarray, or segments whose text is all whitespace, is rejected the same as a missing transcript. speakeris optional per segment (it defaults to "Unknown"); a plaintexttranscript is stored as a single segment.
What happens after delivery
Wren acknowledges the request immediately and processes it in the
background: the call appears in Sources → Calls shortly after, and gets
scored soon after that. Re-sending the same externalId is safe — it's a
no-op, so your tool can retry on timeouts.
Your exclusion rules run before anything is stored: push every call and let the rules decide. A call whose title matches an exclusion keyword — or any untitled call, if you've turned that toggle on — is never stored at all.
If a delivery has a formatting problem (missing externalId, no
transcript), Wren records the failure and shows it on the Custom inbound
card rather than storing a broken call.
Still need help?
Can't find what you're looking for? Email us at support@writewithwren.com and we'll get back to you.
What to include in your message — and which address to use for what.