Hi HubSpot team and developers,
I’m currently building a custom Calling Extension using the `@hubspot/calling-extensions-sdk`, and I’ve encountered a critical issue regarding iframe visibility during inbound calls.
##
Problem
Whenever we call:
```js
await cti.incomingCall({
createEngagement: true,
phoneNumber: “+90…”
});
HubSpot sended this:
{ type: ‘VISIBILITY_CHANGED’, data: { isHidden: true } }
This automatically hides the iframe, regardless of what we programmatically set for visibility (style.display = ‘block’ etc.). We even tried:
- MutationObserver to override the DOM style changes,
- Manual re-display logic inside onVisibilityChanged,
- Ensuring iframe load order and widget open timing.
Users cannot see the softphone interface during incoming calls.
Engagements logged as incoming are useless if the user can’t answer the call in the UI.
Using cti.outgoingCall() as a workaround creates incorrect engagement direction and corrupts reporting.
This limitation significantly impacts the usability of the Calling Extensions SDK for any inbound-capable softphone.
We’d greatly appreciate any guidance, workaround, or roadmap info for improving this behavior.
Thank you!
@ALOTECH This is actually by design.
When you fire cti.incomingCall() HubSpot immediately collapses the call-extension iframe and pops a small toast (“Incoming call from +90…”) at the bottom-left of the CRM. The iframe stays hidden until the rep clicks that toast (or presses the built-in “Answer” hot-key if you’ve wired one). As soon as they interact, HubSpot sends a second VISIBILITY_CHANGED event with isHidden: false and expands the iframe again.
Why they force it
- Prevents the soft-phone from covering the record timeline every time a call lands.
- Keeps the UI consistent with HubSpot’s own native dialer (same toast / same workflow).
- Ensures the rep explicitly accepts the call so call-start times and engagement direction stay accurate.
What you can do (work-arounds)
- Handle the toast flow: in your onVisibilityChanged callback, wait for isHidden: false, then rebuild or refocus your in-iframe phone UI (no need for MutationObservers—HubSpot will reopen it cleanly).
- Optional auto-answer: if you must auto-pop the iframe, use the toast’s “Accept” programmatic hook. In the payload returned from cti.incomingCall you can pass autoAnswer: true; HubSpot will still raise the toast but immediately trigger the click event and re-show the iframe.
- Custom banner instead of iframe: some partners show an overlay in their own code (outside the iframe) on the toast event, then open the iframe only after the rep clicks—it avoids the hidden/visible dance altogether.
- Outlook on future SDK updates: the Calling-Extensions team has noted requests for a “don’t hide my iframe” flag, but nothing is on the public roadmap yet. Best channel is a developer-ticket via your app listing; they do log + prioritize those votes.
Bottom line: you can’t override the automatic hide; the supported pattern is to surface your incoming call in the toast and reopen the iframe when the rep accepts (or auto-accept via the param). If you’re still seeing the iframe stay hidden even after the toast click, open a dev ticket—that part would be a bug.

Ruben Burdin
Real-Time Data Sync Between any CRM or Database | Founder @Stacksync (YC W24)