In Retell, open Settings → API Keys and copy the key marked Webhook. Simplest path. The key usually has unrestricted permissions — fine if you trust us with your default.
Wire up your first agent in five minutes.
Three required steps. Three polish steps. Works for Retell voice agents and SMS chat agents — same flow, same dashboard. We never write to your Retell account; every integration change happens in your Retell dashboard, with you in control.
Three steps from signed up to dialing.
Do these in order. Each step is small enough to fit on a single screen and verifiable inside Retell's own dashboard.
-
01 Paste your Retell API key
From Settings, paste a Retell API key. The key is encrypted at rest with a tenant-specific DEK and never used to modify your Retell account.
Option 1 · default key Option 2 · restricted key - Retell Settings → API Keys → + Add Key
- Name it redialer.io
- Check Restrict permissions with ONLY: Build › Agent: Read and Deploy › Call: Edit
- Save, copy the value, then three-dot menu → Set as webhook key
Retell only allows one webhook key per workspace, so the swap affects every agent in that workspace. Use Option 1 if that's a problem.
-
02 Paste our webhook URL into your Retell agent
For each agent you connect we mint a unique webhook URL of the form https://redialer.io/api/webhooks/retell/wh_…. Drop it into your Retell agent's Webhook Settings → Agent Level Webhook URL field.
Per-agent webhook URL · /v1/agents/:id/webhook-url{ "agent_id": "65f590b6-3959-4e4a-a83f-4548173590ac", "webhook_url": "https://redialer.io/api/webhooks/retell/wh_hzQkZzSJQtfYCE8RlQoSr", "verification_status": "pending" }One URL per agent. The slug is opaque + rotatable from /app/setup/<agent_id> with a 24h grace where both old + new URLs work, so you never need to coordinate timing.
-
03 Add one Boolean to Post-Call Extraction
In your Retell agent's Post-Call Extraction config, add a single Boolean variable named redialer.io_callback. Instruct your agent to flip it true only when the caller asks you to call them back at a later time — on the original inbound call OR on an outbound redial we placed when the caller asks for yet another callback. Leave it false when they want someone else to follow up, or just want info, a quote, or an email.
We extract the requested time from the transcript and schedule a fresh redial row. Retries on voicemail, no-answer, busy, technical errors, and inactivity timeouts are handled separately based on Retell's disconnection_reason — no extra agent prompt needed.
Three nice-to-haves that shape the redial.
Skip these and redialer.io still works. Add them when you want richer signals on the second dial or downstream fan-out to your own tooling.
-
04 Forward call events to your own webhook
If you already pipe Retell call events into a CRM, Slack, or an internal workflow, point that downstream webhook at us in Agent setup · Downstream webhook URL and we'll pass through the same payload verbatim. We don't modify the body — it's a clean fan-out.
The forwarded body is the original Retell payload, not our normalized shape. Signature headers (Retell's X-Retell-Signature) are forwarded for end-to-end verification by your downstream.
-
05 Add the callback-time prompt snippet
We provide a short prompt fragment that nudges your agent to capture callback time consistently — E.164 numbers, ISO-8601 timestamps, timezone-aware phrasing. Paste it into your agent's prompt for cleaner global handling. Without it, we still parse times from the transcript via the post-call analyzer.
-
06 Adapt the opening line on retries
On every outbound dial we set a dynamic variable named redialer.io_redial_reason so your agent can open differently depending on why we're calling. Branch your prompt on these values:
- callback_requested · first dial after the caller asked for one
- voicemail_followup · previous attempt reached voicemail or an IVR
- no_answer_followup · previous attempt rang out with no pickup
- busy_followup · previous attempt got a busy signal
- retry · fallback for any transient technical retry
Pair with redialer.io_attempt and redialer.io_is_final_attempt for an explicit “last try” closing line.
The five nouns under the hood.
Everything in the dashboard and the API reduces to these five entities. Learning them once means the rest of the docs make sense without a glossary tab open.
- Tenant
- Your billing account on redialer.io. One human (or one team) → one tenant. Plan limits, monthly call quotas, and audit logs are tenant-scoped. Multiple workspaces can live under one tenant on Pro and Scale.
- Workspace
- One connected provider account (one Retell workspace, one Vapi account, one Bland account). Holds the API key, signing secret, and per-workspace defaults for retry logic, quiet hours, and data retention. Free + Starter ship with one; Pro = 5, Scale = 10.
- Agent
- A specific voice agent inside a workspace — synced from Retell by id. Has its own webhook URL slug, setup status, and optional per-agent overrides (paid tiers). Disabling an agent silences its webhook and stops scheduled redials immediately.
- Callback
- One scheduled outbound dial. Created when a caller asks for one (auto-extracted from the transcript) or when a retry policy fires after a non-terminal disconnection. Carries encrypted dynamic variables for replay on the redial and chains back to the call that triggered it.
- Chain
- The sequence of callbacks tied to the same caller across successive Retell calls. If the caller says “call me tomorrow” on Monday, dials in Tuesday, and asks for another callback, all three rows share a chain_root_id. Powers the /v1/callbacks/:id/chain endpoint and the “final attempt” close-out logic.
When we redial — and when we don't.
Retries fire automatically based on Retell's disconnection_reason on every outbound call. Every group has its own toggle + delay in Settings · Retry & Scheduling. Quiet hours and quiet days shift any retry forward to the next allowed slot.
| disconnection_reason | Group | Default | Default delay |
|---|---|---|---|
| voicemail, voicemail_reached | Voicemail / IVR | on | 4 hours |
| dial_no_answer | No answer | on | 1 hour |
| dial_busy | Busy | on | 10 minutes |
| dial_failed, telephony_error | Technical error | on | 30 minutes |
| inactivity_timeout | Conversation silent | on | 24 hours |
| user_hangup, agent_hangup | Terminal | off | — |
| dnd, dnc | Do-not-call | off | — |
The chain's overall ceiling is max_attempts — by default 3 on Free / Starter, 5 on Pro, 10 on Scale. Pro and Scale can override per agent from the agent setup page. The last attempt in a chain sets the redialer.io_is_final_attempt dynamic variable to true so your agent can deliver a closing line.
Callbacks that the caller explicitly requests (Post-Call Boolean = true) are exempt from quiet hours under TCPA's consent exception — we honor the requested time as-is.
Two signature contracts to keep straight.
One signature scheme protects the webhook deliveries we receive from Retell; another protects the forwarded deliveries you receive from us. Both use HMAC-SHA256 over the raw request body.
Retell → redialer.io
Retell signs each delivery with the workspace's shared webhook key. We verify with the same key (Option 1) or the restricted key marked “Set as webhook key” in Retell (Option 2). Signature header: X-Retell-Signature.
A missing or mismatched signature → 401. The dual-grace lookup accepts the previous slug for 24h after rotation so in-flight deliveries still verify.
redialer.io → your downstream
When you set a downstream webhook URL on an agent, we forward Retell's payload verbatim with both Retell's original X-Retell-Signature header AND our own X-Redialer-Signature derived from your per-tenant webhook secret. Verify either or both.
SSRF-hardened: we resolve the downstream URL's IP once at request time and pin the connection to it. Loopback, link-local, and private CIDRs are rejected.
import { createHmac, timingSafeEqual } from 'node:crypto';
function verifyRedialerSignature(rawBody, header, secret) {
if (!header) return false;
const expected = createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
const a = Buffer.from(header, 'hex');
const b = Buffer.from(expected, 'hex');
return a.length === b.length && timingSafeEqual(a, b);
} Default off. Explicit opt-in per workspace.
By default redialer.io stores only what it needs to fire the next redial. Transcripts, recording URLs, full Retell metadata, and collected variables are not retained unless you opt in.
Default retention level
Per workspace, choose default or minimal. Minimal zeroes ALL call data on terminal callback completion (not just PII) — including the to/from numbers and dynamic variables. Default keeps the identifiers needed to surface the row in Activity.
Historical call data
Per workspace, set how many days the full inbound + outbound call_analyzed payload stays attached to its callback row. 0 = don't store (default), -1 = forever. Cron purges individual rows past their window. Per-agent overrides are available on Pro and Scale.
Encryption: every PII field (phone numbers, dynamic variables, metadata, captured call payloads) is encrypted at rest with AES-256-GCM under a per-tenant DEK that itself is wrapped by a KEK held in Vault. Keys never live in app memory longer than a single decrypt operation.
One key per provider account.
Pro and Scale tenants can connect multiple Retell / Vapi / Bland accounts as separate workspaces. Each workspace has its own API key, webhook slugs, retry policy, retention settings, and the agent roster pulled from that provider account.
- Switch from the topbar. Every page in the dashboard re-scopes to the selected workspace.
- Bearer API keys are workspace-locked by default. Admin keys carve out tenant-wide access for ops tooling.
- Per-workspace agent caps. Free = 1, Starter = 5 enabled agents per workspace. Past-cap agents get HTTP 403 on their webhooks until you upgrade or disable.
- Soft delete with 24h grace. Disconnecting a workspace marks it for deletion; agents, callbacks, and API keys are kept for 24 hours so you can undo. After grace, a cron hard-deletes everything.
Drive everything from your own tooling.
Once your first agent is wired, the v1 REST API lets you cancel scheduled redials, force one through manually, fetch callback payloads with PII gating, mint per-workspace bearer keys, and pull activity / audit feeds. Every endpoint is documented with auth scopes, request / response shapes, and error envelopes.
API access is included on every paid tier (Starter and above). The shape won't change after v1 leaves beta — additive fields are not breaking and may appear on v1 responses anytime.
Coming soon to the docs.
- Vapi integration guide. Webhook URL placement, tool / function-call mapping, signature verification.
- Bland integration guide. Same shape, different field names. Beta-tier providers ship through the same /v1 surface.
- Data model reference. Per-table column reference for callbacks, agents, webhook_events, and the audit log — useful for anyone querying via the public API.
- Cookbook. Common recipes: forwarding to Slack on terminal failure, building a Sheet sync, schedule-then-redial via n8n.
Need something missing now? Reach out via the contact form — we're building the docs to your actual integration shape.