AI phone call API: webhooks, retries and no double calls

Short answer: Start calls with POST /v1/calls and add webhook_url to get the finished call POSTed to you, signed, instead of polling. Send an Idempotency-Key header so a timed-out request can be retried without dialing the business twice. When a call ends without success, retryable says whether placing it again could work or whether it needs a change first.

Add CallForMe to your agentTry a free demo call

Using ChatGPT? Add it from ChatGPT's plugin directory in one step, on any plan.

$1 when someone answers, first 2 minutes included. Nothing if nobody picks up. Connecting asks for nothing.

On your phone? Email yourself the setup steps

If your backend, a cron job or a workflow tool places calls, three things matter beyond the call itself: getting the result without a polling loop, retrying a request without calling a business twice, and knowing which failures are worth another try. The REST API handles all three.

1. Get the result by webhook

Add webhook_url to the request. Once the call's outcome is final, CallForMe POSTs the whole call there: the same JSON GET /v1/calls/{id} returns, with the full transcript.

curl -X POST https://callforme.tel/v1/calls \
  -H "Authorization: Bearer $CALLFORME_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+14697707412",
    "business_name": "Maple Street Pizza",
    "goal": "Ask what time they close tonight.",
    "webhook_url": "https://example.com/hooks/callforme"
  }'
  • Deliveries go only to https URLs on public hostnames.
  • Answer with any 2xx. Anything else, or no answer within 10 seconds, is retried after 30 seconds, 5 minutes and 30 minutes.
  • GET /v1/calls/{id} shows webhook.status (pending, delivered, failed) and the last error, so you can see why something didn't arrive.
  • For call_around, every call in the batch gets its own delivery.

Verify each one with the CallForMe-Signature header. The code is in the REST docs.

2. Retry without double calls

Networks drop responses. If a request times out, you can't know whether the call was placed. Send an Idempotency-Key header (a UUID per call you mean to make):

  • The same key with the same body, within 24 hours, returns the first response with Idempotent-Replayed: true. Nobody is dialed twice.
  • A key is only used up once a call starts. If the first try came back 402 with a setup link, or 400 for a missing field, the same key works after you fix it.
  • The same key with a different body returns 409 IDEMPOTENCY_MISMATCH, so a bug that reuses keys can't send the wrong call.

3. Know which failures to retry

When a call ends without success, it carries retryable:

Ended as retryable What to do
Voicemail, no answer, busy, early hang-up true Try again later, or during their hours. next says when if they're closed.
Needs something from the user false Get it, then POST /v1/calls/{id}/redial with the changes.
Won't talk to an assistant false Redial with transfer_to so the user joins when a person answers, or have them call.
The business can't help, or the number is invalid false Find another business.

No-code tools

Zapier, Make and n8n can catch the webhook with their own hook triggers, with no loops or delays. See automations.

What it costs

$1 per answered call, including the first 2 minutes, then $0.40 a minute, up to 30 minutes. Unanswered and busy calls are free. Webhooks and retries cost nothing extra.

Questions

Do I have to poll for results?

No. Add webhook_url to the request and the finished call arrives there once its outcome is final, with answers, summary and transcript. Polling GET /v1/calls/{id}?wait=45 still works and returns early as soon as something changes.

What happens if my request times out and I send it again?

With an Idempotency-Key header, the retry returns the first response and nobody is dialed twice. Without one, an identical request from the same account within 2 minutes also returns the call already in progress.

How do I know a webhook really came from CallForMe?

Each delivery carries a CallForMe-Signature header: an HMAC-SHA256 of the timestamp and raw body, keyed with your webhook_signing_secret from GET /v1/account. Check it in constant time and reject old timestamps.

Should I retry every failed call?

No. Use retryable. Voicemail, no answer and early hang-ups are usually worth another try later. A call that needs something from the user, a business that won't talk to an assistant, or one that can't help comes back with retryable false and a next step.

Add CallForMe to your agent

One URL for any MCP agent. Connecting asks for nothing.

https://callforme.tel/mcp

Install steps for your agentTry a free demo callPricing

On your phone? Email yourself the setup steps

One email with the link, for when you're at your computer. Nothing else.