I’m building a custom CTI app for Freshsales (left_nav_cti) that integrates with a Yeastar PBX. The server-side function calls the PBX’s own Open API via the standard Request Method (requests.json templates + $request.invokeTemplate in server.js) to fetch an access token and mint a Linkus SDK login signature.
Symptom: Login works every time during local development (fdk run), but once the app is packaged and installed for real (private/Marketplace install), the exact same server-side call fails with an “IP forbidden” error returned by the PBX.
What I’ve already ruled out on the PBX side: I checked all three PBX-side mechanisms that could produce this — API IP Restriction (Integrations > API), country-level geo-defense, and the automatic 5-failed-attempts IP blocklist (Security > Security Rules > Blocked IPs). None show any trace of the rejected request, even when reproduced live and checked immediately afterward. Nothing shows in the PBX’s own logs either, which is odd given how verbose those logs normally are.
My working theory: since server.js’s serverless functions execute locally on the developer’s own machine during fdk run, but execute on Freshworks’ own cloud infrastructure once the app is actually installed, the outbound call to the PBX comes from a completely different IP in production than it did during development — and that production IP isn’t whitelisted anywhere the PBX would show it to me (possibly because the PBX is hosted on Yeastar’s own multi-tenant cloud infrastructure with a firewall/WAF layer that sits above what the tenant’s own Security Rules panel can see). Anyone who can help out…