How to set an AI phone system inside your own CRM

Embed the Allo dialer in your own CRM with one iframe, then use webhooks and the API to write AI call summaries, transcripts and recordings to your records.

September 28, 2026

Every few days a partner asks us the same question with a different CRM in it. A property manager running tenants out of a home-grown back office. A recruiting agency on a niche ATS. An insurance broker whose "CRM" is an Airtable base with 40 fields nobody else would understand. None of them want to leave that tool. They just want to make phone calls.

That used to mean one of two bad options: keep the phone system in another tab and copy notes across by hand, or build telephony yourself, tough, ah?. But don't worry, this article is about a third option, and about exactly how it works.

Why custom CRMs are the hardest place to put a phone

Native integrations are built for the mass market. They know what a HubSpot contact or a Salesforce lead looks like, and they write calls to it. Your CRM does not have leads. It has tenants, job sites, loan files, candidates, policies. The call belongs on one of those, next to the fields that make your business yours.

So the choice has always been between a phone system that does not know your data, and a phone system you have to build. Building one is a bigger project than it looks from the outside.

What a phone needsBuild it yourselfAllo API + embedded dialer
Business numbersPick a carrier, buy numbers country by countryLocal numbers in 120+ countries, ported for free
Texting compliance10DLC and Sender ID registrations on youGuided registration, with the Allo team
Calling from the browserWebRTC, microphones, audio qualityOne iframe
Recording and transcriptsStorage, speech to text, consent rulesEvery call, with recording compliance settings
AI on the callYour own models, prompts and pipelinesSummaries, tags and an AI receptionist, built in
Getting data into the CRMYour codeYour code, fed by signed webhooks
The last row is the only one you still own. It is also the only one that should be custom.

Three ways in: the dialer, webhooks and the API

Every Allo integration with a custom CRM is built from the same three pieces. Each one answers a different question.

Allo connection options to your CRM: Embedded dialer, webhooks, REST API.
LayerAnswersLivesTypical use
Embedded dialerHow does my team call from here?In your page, as an iframeClick to call, ringing inside the record, screen pop
WebhooksWhat just happened?On your serverWrite the call, summary and recording to the right record
REST APICan my CRM make Allo do something?On your serverSend a text, load a calling list, search past calls

The embedded dialer, our newest piece

The embedded dialer puts the full Allo dialer inside your app with a single iframe. Your team signs in to Allo inside it once, and from then on calls start and ring right where they work. It talks to your page in both directions through postMessage.

EventDirectionWhat your CRM can do with it
dialYour app → dialerOpen the dialer with a number ready to call
readyDialer → your appEnable call buttons only once the dialer is loaded
loginDialer → your appKnow which teammate is signed in
incoming_callDialer → your appScreen pop: open the caller's record before anyone says hello
outgoing_callDialer → your appMark the record as "on a call" for the rest of the team
call_answeredDialer → your appStart a talk track, a timer or a checklist
call_endedDialer → your appAsk the rep for an outcome while it is fresh

Tip

One step before it works

Embedding is switched on per domain. Email [email protected] with the domains your CRM runs on, then drop in the iframe.

Webhooks: the part that makes it AI native

The dialer tells your page what is happening. Webhooks tell your server what happened, with everything the AI produced. The one that matters most is call.completed, sent about 30 seconds after the call hangs up, with the summary, the full transcript, the recording URL, the tags, the result and any fields the AI receptionist collected.

There are 22 event types in total, from call.received (which already carries the matching person, company and deals) to sms.received, tag.added and thread comments. Every delivery is signed, retried up to 8 times over about 27.5 hours, and can be replayed after an outage.

The API: when your CRM gives the orders

The REST API is how your CRM makes Allo do things. The endpoints custom CRMs use the most:

  • Load the power dialer from any list in your CRM, for yourself or for a teammate, with names and companies attached.
  • Send a text from the team's Allo number, so it lands in the same thread as the calls.
  • Search every call and text by keyword across transcripts, summaries and messages.
  • Read and add tags so your CRM filters and Allo filters stay the same.
  • Write summary templates so the AI summary follows your fields, not a generic format.
  • Configure the AI receptionist per line: prompt, knowledge, business hours, transfer rules.

One call, end to end

Here is what a single outbound call looks like when both channels are wired. The browser events drive the screen while the call is live. The webhooks carry the result to your database once it is over.

Timeline of one call: dial, outgoing_call, call_answered and call_ended in the browser, then call.triggered, call.answered and call.completed with the Al summary on the server.
  1. The rep clicks a number in your CRM Your page sends dial with the number. The embedded dialer opens with the call ready, on the rep's own Allo line.
  2. The call starts The dialer fires outgoing_call to your page and Allo fires call.triggered to your server. Use whichever is closer to the thing you want to update.
  3. The prospect picks up call_answered in the browser. Show the talk track for this deal stage, or start your own timer.
  4. The rep hangs up call_ended in the browser. Ask for the outcome now, while the rep still remembers it.
  5. About 30 seconds later call.completed reaches your server with the summary, transcript, recording and tags. Your handler writes them to the record, in your schema.
  1. The code: the embed

    <iframe id="allo" src="https://web.withallo.com?variant=dialer" allow="microphone; autoplay" style="width: 376px; height: 640px; border: 0;" ></iframe> <script> const ALLO = "https://web.withallo.com"; const dialer = document.getElementById("allo").contentWindow; // 1. Every phone number in your CRM becomes a call button document.querySelectorAll("[data-phone]").forEach((el) => { el.addEventListener("click", () => { dialer.postMessage( { source: "allo-host", type: "dial", payload: { phone_number: el.dataset.phone } }, ALLO ); }); }); // 2. Your CRM reacts to what happens on the call window.addEventListener("message", ({ origin, data }) => { if (origin !== ALLO || data?.source !== "allo-dialer") return; switch (data.type) { case "incoming_call": openCallerRecord(data.payload); break; // screen pop case "outgoing_call": markRecord("on a call"); break; case "call_ended": askForOutcome(); break; } }); </script>

  2. The code: writing the call into your CRM

    // POST /webhooks/allo (subscribed to call.completed and sms.received) app.post("/webhooks/allo", express.raw({ type: "application/json" }), async (req, res) => { // 1. Verify the webhook-signature header first (see the Allo docs) // 2. Deduplicate on the webhook-id header: delivery is at least once res.sendStatus(200); // answer within 20 seconds, work in the background const { topic, data } = JSON.parse(req.body); if (topic !== "call.completed") return; const number = data.type === "INBOUND" ? data.from_number : data.to; const record = await crm.findByPhone(number); // your lookup, your schema await crm.addActivity(record.id, { kind: "call", direction: data.type, // INBOUND or OUTBOUND outcome: data.result, // ANSWERED, VOICEMAIL, TRANSFERRED_AI... duration: data.length, // "4m 22s" summary: data.summary, // the AI summary tags: data.tags, recording: data.recording_url, transcript: data.concatenated_transcript, rep: data.user_email, collected: data.data_collected, // fields the AI receptionist gathered }); });

  3. The code: a "call this list" button

    Any filtered view in your CRM can become a calling session. One request to append numbers to a rep's power dialer queue, and they dial back to back from the embedded dialer. curl -X POST https://api.withallo.com/v2/api/dialing-queues/current/numbers \ -H "Authorization: Api-Key YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "numbers": [ { "number": "+14155550142", "name": "Dana", "last_name": "Whitfield", "company": "Harborline" }, { "number": "+14155550187", "name": "Marcus", "last_name": "Bell", "company": "Bell & Sons Roofing" } ] }'

What lands on the record

This is the part your team will actually feel. The rep does not type notes. The record fills itself, and it fills itself with what your business needs, because you decide where each field goes.

A custom CRM record after a call: Al summary, colored call tags, a recording player and a follow-up text, each mapped to a webhook field.

1iframe to embed the dialer

~30s from hang-up to summary on your server

22webhook event types

8automatic retries per delivery

The top 10 CRMs, and where the custom part starts

Most teams are not on a fully custom CRM. They are on a big one they bent into shape with custom objects, extra apps and an internal tool or two on the side. Here is how Allo meets the ten most used CRMs, and when to reach past the native sync.

Map of CRMs: eight with nalkve Allo sync, Dynamics 365 and Freshsales through the API and embedded dialer, and custom-built CRMs through the APl and embedded dialer.
CRMNative Allo syncReach for the API + embedded dialer when...
SalesforceYesCalls should land on a custom object, or reps live in a Lightning app you built
HubSpotYesYou run a custom object or an internal tool beside the CRM
Microsoft Dynamics 365Not yetAlways: embed the dialer on the form, write calls with webhooks
Zoho CRMYesYour team works in a custom Zoho module or a Creator app
PipedriveYes (Business plan)You want calling lists built from filters Pipedrive does not have
monday CRMYesThe call belongs on a board that is not your contacts board
FreshsalesNot yetAlways: the API and the embedded dialer cover it today
OdooYesYou extended Odoo with your own module and views
AttioYesCalls should drive custom lists or workflows beyond the synced record
GoHighLevelYesYou are an agency and each sub-account runs its own setup
Native integrations as listed in the Allo help center. Where one exists, start there, then add the API for the custom part.

Less common CRMs Allo already syncs with natively

Before you write a line of code, check this list. Plenty of the niche CRMs partners ask about are already native: connect them in a few clicks and calls log themselves, with the AI summary and the recording. See the full list in the integrations overview.

CRMBuilt forWhat Allo syncs natively
folkRelationship-driven teams, agencies, foundersCall recordings and AI summaries on the contact
StreakTeams running their pipeline inside GmailCall recordings and AI summaries
ApolloOutbound prospecting teamsCalls, texts and voicemails, with contacts, companies and deals kept aligned (Business plan)
SellsyEuropean SMBs selling and invoicing in one toolContacts, plus calls logged with summaries
BrevoMarketing-led teams on email and SMS campaignsCall recordings and AI summaries
noCRM.ioLead-focused sales teamsCall recordings and summaries on the lead
Pipeline CRMSmall sales teams managing dealsCall recordings and AI summaries
Follow Up BossReal estate agents and teamsCall recordings and summaries on the person
JobNimbusRoofers and exterior contractorsCall recordings and summaries on the contact
JobberHome service businessesCall recordings and summaries on the client
eWay-CRMTeams running their CRM inside OutlookContacts into Allo, every call and SMS logged as a journal on the contact and its company
Native integrations as documented in the Allo help center. Yours is not here? That is what the API and the embedded dialer are for, and tell us which one it is.

The CRMs teams build themselves

Then there is the long tail, and it is where most of the partner questions come from. Four recipes we see again and again:

Your CRMDialer goes inWebhooks write toThe API adds
An in-house back office (Rails, Django, Laravel, Node)The record page, as a side panelYour own database, via one endpointTexts and calling lists from any admin view
Airtable or NotionAn interface page or a small web app on topThe base, through an automation or a tiny serverA "call these rows" button
Retool or another internal tool builderAn iframe component next to the tableYour database, like the rest of the toolButtons that queue, text or tag
Vertical software (property, recruiting, insurance, clinics)A custom tab or panel, where the vendor allows itThe vendor's API or your warehouseThe workflows the vendor never built

Note

Native sync is right when

Your CRM is on the integrations list Calls belong on standard contacts and deals You want it running today with no code

Note

API + embedded dialer is right when

Your CRM is home-grown, vertical or not listed Calls belong on your own objects You want the phone inside your screen, not next to it

Tip

Building a CRM for other people?

If you sell vertical software or a CRM, the Allo reseller program is built for you: embed Allo in your product, bundle it with your offer and bill it at your own price.

Where to start this week

  1. Email [email protected] with the domains your CRM runs on, to switch on the embedded dialer.
  2. Paste the iframe on your record page and wire the dial event to your phone fields.
  3. Create an API key in Allo settings and subscribe a webhook to call.completed.
  4. Map the summary, tags and recording to your own fields. That mapping is the whole integration.
  5. Add one button that loads a filtered list into the power dialer. Your reps will ask for more.

FAQ

Can I use Allo with a CRM that has no native integration?

Yes. The embedded dialer works in any web app you control, and webhooks plus the REST API let you write calls, summaries and recordings into any database. That is the whole point of this setup.

What is the Allo embedded dialer?

The full Allo dialer inside your own app, loaded with one iframe. Your app can send it a number to call and receives events for ready, login, outgoing_call, incoming_call, call_answered and call_ended. See the embedded dialer docs.

Do my users need an Allo account?

Yes. Each teammate signs in to Allo inside the dialer the first time, and calls go out on their own Allo line, with recording, transcripts and AI summaries.

How do call summaries get into my CRM?

Through the call.completed webhook, sent about 30 seconds after the call ends. It carries the AI summary, full transcript, recording URL, tags, result and the fields the AI receptionist collected.

Can my CRM start a calling session?

Yes. The API can append numbers, with names and companies, to your own power dialer queue or a teammate's. The rep then dials the list back to back.

Is the AI receptionist available with a custom CRM?

Yes. It answers on your Allo line whatever CRM you use, and what it collects comes through the same webhooks, so a missed call can still end up as a qualified record in your system.

Which CRM are you using?

Seriously, tell us. Every niche CRM we hear about makes the next integration easier, and the most requested ones become native. Send the name to [email protected], or book a demo and we will sketch your setup with you, on a call, obviously.

Keep reading