How to Connect Aircall to Claude
Call recordings are personal data, and there is a difference between an agent placing a call and an agent filling a human's dialer. Aircall auth, limits and the safer endpoint.
Aircall has two endpoints for getting a phone call to happen, and the difference between them is the single most useful thing in this post.
POST /v1/users/:id/calls places the call. Your agent decides, the phone rings, a human somewhere answers.
POST /v1/users/:id/dial fills the number into a specific user's Aircall Workspace dialer. Nothing is dialled. A person looks at it and presses call.
That second one is a human-in-the-loop approval gate built into the API, for free, with no policy engine required. For most agent use cases it is the right choice, and almost nobody notices it is there.
Before the mechanics: call data is personal data
This matters more here than in most integrations, so it goes first rather than in a compliance footnote.
A call record contains who phoned whom, when, and for how long. A recording contains a person's voice. A transcript contains whatever they said, which in a support or sales context routinely includes account details, personal circumstances and occasionally things they would not have said if they had remembered the call was recorded.
Three consequences for an agent. Recording consent law varies by jurisdiction and some places require all parties to agree, so whether you may process a recording at all is not a technical question. Sending transcripts to a model is a data transfer your privacy review will care about, and it needs to be in your records of processing. And the audit log of exactly which transcripts an agent read is the artifact that answers "what did you do with our customers' calls," which is a question you want a precise answer to rather than a reassuring one.
None of that means do not build it. It means decide deliberately which calls are in scope, keep the audit trail, and read the security checklist before connecting any AI assistant to company data before you point an agent at a year of recordings.
Auth and limits
Aircall customers use basic auth: your api_id is the username and api_token is the password, base64 encoded together as api_id:api_token. Technology partners use OAuth 2.0 instead, exchanging a code at POST /v1/oauth/token for a bearer token. Base URL is https://api.aircall.io/v1 and HTTPS only. The docs specifically advise against putting credentials in the URL, which is worth repeating because it is exactly what a model will do if it is improvising a curl command.
Rate limit is 120 requests per minute per company, and the responses tell you where you stand via X-AircallApi-Limit, X-AircallApi-Remaining and X-AircallApi-Reset. Higher limits are available by asking support.
Note that the budget is per company, not per integration. Your agent is sharing it with your dialler, your CRM sync and anything else wired into Aircall, so an agent that paginates through a month of calls as fast as it can will degrade tools your sales team is actively using. Rate-limit errors are retried with exponential backoff automatically, but the polite design is to page slowly and cache.
The 204 that returns nothing
Placing a call takes number_id and a to number in E.164 format, and on success it returns 204 No Content. No body. No call ID.
An agent that expects an object back gets nothing useful, and a naive implementation will treat the empty response as a failure and try again, which phones the person twice. You cannot correlate the call from the response either, so you need webhooks or a follow-up list query to find out what happened.
The call also only works if that user is available and not already on another call, so a successful request still depends on a human's state at that moment. Design for "it did not go through because Priya is on a call" as a normal outcome rather than an error.
Setting it up
npx swytchcode
swy login
swy init --mode=sandbox
swy get aircall
swy auth connect aircall # api_id + api_token; the basic-auth
# encoding is handled for you
swy auth status
swy discover "list calls" --project aircall
swy discover "retrieve a transcription" --project aircall
swy discover "dial a number into the workspace" --project aircall
swy list methods aircall
swy info <canonical_id>
swy add method <canonical_id> # reads + dial. Not place-call, not delete-recording.That allowlist is the whole design. Reads so the agent can analyse, dial so it can hand a suggested call to a human, and nothing that places a call or destroys a recording. Recording deletion in particular is both irreversible and sometimes legally constrained in both directions, since you may be required to retain records or required to delete them, and neither is a decision for a language model.
Credentials go to a local store outside your project, encrypted at rest, and are injected when a call runs, so they never enter the model's context. See the authentication docs. Keep --project aircall on discover calls, and run swy get before swy info or info will report a real method as missing.
If you do allow outbound calls
{
"id": "outbound-calls-need-a-human",
"target": ["<aircall place-call canonical_id>"],
"when": { "field": "to", "operator": "!=", "value": "<your-test-number>" },
"action": {
"type": "REQUIRES_APPROVAL",
"message": "Agent wants to place a real outbound call"
},
"approval_timeout": "1h"
}Calls to your test number pass so development stays pleasant; anything else stops and asks. Held calls go to Slack or Telegram and fail closed, so an unapproved call is never placed. That is the right default for something that interrupts a person and cannot be taken back. Setup is in the human approval docs, the schema is in the policy reference, and because the file lives in your repo, loosening the rule is a reviewed pull request. See policy-as-code for AI agents.
Honestly though, prefer the dial endpoint. An approval prompt in Slack and a number sitting in a rep's dialer achieve the same control, and the second one fits how the team already works.
Idempotency and the double call
Placing a call is not idempotent and the 204 makes it worse, because the empty response gives a retry loop nothing to recognise. The failure is phoning a customer twice in thirty seconds, which reads as either a glitch or harassment depending on their mood.
Writes are only auto-retried when an idempotency key is set, so an unprotected call attempt fails visibly instead of quietly dialling again. Derive the key from the reason for the call, such as the ticket or lead ID, and check the call list before retrying anything ambiguous. Background in API idempotency: the complete guide and the idempotency docs.
Using it from Claude
Reading and summarising calls through MCP in Claude Desktop or Claude Code works well: you ask what happened on yesterday's calls and get an answer without opening Aircall. With the allowlist above, that session physically cannot place a call. Setup per client is in the MCP setup guide, the reference is in the MCP docs, and skills.md hands a coding agent the commands if you want it to wire this up. For an always-on service the Anthropic SDK guide has a working tool-use loop.
What you can build
- Call summaries into your CRM. Read the transcript after a call, write a summary and next steps into the customer record. Read-only against Aircall, and it removes the admin task reps most reliably skip.
- A callback queue that a human triggers. The agent decides who should be called back and in what order, then uses the dial endpoint to load each number into the right rep's dialer with context. The agent does the thinking, the human does the calling.
- Theme analysis across calls. Cluster transcripts to find what customers keep asking about, then raise the recurring gaps as ideas in Aha! or draft help articles in Notion. Use a defined window of calls rather than the whole history, for privacy as much as cost.
- Missed-call follow-up drafts. When a call is missed, draft the follow-up message and post it to Slack for the rep to send. No outbound permission needed anywhere.
FAQ
Should the agent place calls at all?
For most teams, use the dial endpoint instead and let a person press the button. You keep the agent's judgement about who to call and lose the entire category of risk where it calls the wrong person at the wrong time.
Can I send transcripts to a model?
Technically yes, legally it depends on your jurisdiction, your consent notices and your processing records. Treat it as a privacy decision with a documented answer rather than an implementation detail, and keep the audit log of which transcripts were read.
Why did my call request succeed but no call happened?
Most likely the user was unavailable or already on a call. The 204 tells you the request was accepted, not that a call connected, which is the same class of confusion as 200 OK but it failed. Confirm via webhook or a list query.
Aircall or a voice-agent platform?
Different jobs. Aircall is your team's phone system and an agent's role there is analysis and assistance. If you want an agent to actually hold the conversation, that is a voice-agent platform, and the Retell AI guide covers what changes when the model is doing the talking.
Related reading
More content
SendGrid API for AI Agents
One boolean in the SendGrid payload mails people who unsubscribed. bypass_list_management is the field your agent must never be able to set.
Addepar API for Wealth Management Agents
Addepar has no read-only key tier, so a key carries its user's permissions. If you want an agent that can only read portfolios, you have to build that constraint yourself.
FreeAgent API for Accounting Agents
FreeAgent lets you read accounting period locks before you write. An agent that skips that check will eventually post an entry into a period someone has already filed.
