Building a Telephony Module Application
This document describes what an external developer needs to implement to create their own app for the Flowlu Marketplace.
To develop an app, please refer to the Flowlu JS SDK.
General architecture of integration
Your application acts as middleware between Flowlu and the external telephony server:
Flowlu (CRM) | -> <- | Your app (middleware) | -> <- | External telephony server |
↕ | ↓ | |||
iframe (UI)
OAuth
API +
Webhooks | Database
Integrations, tokens, ID mappings |
Responsibilities of your app:
- Settings UI — a connection page opened inside Flowlu in an iframe.
- Backend — stores the integration (mapping of CRM user ↔ CRM account ↔ external channel account) and OAuth tokens.
- Outgoing Channel — receives webhooks from Flowlu and delivers events to the external server.
- Incoming Channel — receives notifications from the external server, transforms the data to the required format, and transmits it to Flowlu.
What needs to be implemented
| # | Component | Purpose |
| 1 | HTTPS endpoint for the settings page (iframe src) | Opened by the CRM when "Connect" is clicked; accepts a POST request with the user's auth data |
| 2 | Receiving CRM user OAuth tokens | Store access_token/refresh_token, identify the CRM user |
| 3 | Requesting CRM user data (API /api/v1/module/core/user/get) | Retrieve the CRM manager's ID, name, and email |
| 4 | Registering the channel in CRM (API /api/v1/module/telephony/telephony/create) | Create the integration and receive the channel uuid. Fields are described below |
Fields for channel registration (telephony/create):
- name — the name of the specific integration
- ref_id — your MiniApp ID
- code — must be the value mini_app
- webhook_url — the URL where the CRM will send requests
- icon_url — a URL for the integration icon
- can_redirect (true/false) — the ability to redirect a call to another employee
- manifest_id — integration point ID
Registering the application in the marketplace and integration point
Steps:
- Create an application in https:///module/miniapps/cabinet.
- In the manifest, add the integration point "telephony service connection".
- Fill in the integration point fields:
| Field | What to specify | Note |
| id | any code, e.g., my_server_telephony | used in the payload when opening; useful if there are multiple integration points |
| Header | name seen by the manager in the channel list | |
| Icon | public https-URL for the icon | |
| Action | Side panel / Modal window / Page | determines how the iframe will open |
| Size | size of the panel/modal | |
| iframe (src) | https:///integration/settings | must be HTTPS in production, otherwise the browser will block the iframe on the https-CRM |
After saving the manifest, your application will appear in the list of telephony services.
Iframe context data
Flowlu will send a POST request with the following body to the URL specified in iframe (src):
code JavaScript
{
"domain": ".flowlu.com",
"language": "en",
"placement": {
"id": "my_channel_wizard",
"code": "contactcenter.service.wizard"
},
"https": "1",
"account": { "id": "123456" },
"app": {
"id": "",
"version": "1.0.0"
},
"auth": {
"expires_at": "2026-03-27 17:29:33",
"access_token": "",
"refresh_token": ""
},
"ratelimit": { "limit": "16" }
}
Your endpoint should:
- Validate the payload and extract domain, app.id, app.version, account.id, auth.*.
- Construct the CRM base URL: https://{domain} (or http if https=0 — only relevant for dev environments).
- Identify the CRM user. Recommended pattern — "two-way lookup":
- Fast path: search your database for the OAuth client by the hash of access_token + domain + app.version. If found, the user is already known; no need to call the CRM API.
- Slow path: if not found, perform GET https://{domain}/api/v1/module/core/user/get with the Authorization: Bearer {access_token} header and create a record for the CRM user based on the response.
- Save/update OAuth tokens. The uniqueness key is (user_id, domain, app_version). It is advisable to clean up tokens for old application versions during updates to prevent database bloat.
- Render the settings form and return the HTML to the client.
Bidirectional data flow
After connecting the integration, data exchange occurs in two directions:
Flowlu -> your webhook_url — the CRM sends POST requests to your server:
- initiation of an outgoing call;
- requesting call lists and specific call data;
- requesting the list of SIP employees;
- integration health check.
Your application -> Flowlu — you send POST requests with call events to the CRM endpoint (POST /external/telephony/hook/mini_app/{account_id}/{telephony_uuid}):
- call initialization (for incoming calls, the CRM returns a routing decision);
- call connected;
- call completed;
- call recording information;
- call state update.
Detailed contracts (request/response formats, error codes) are described in the OpenAPI specifications:
- outgoing_hooks.yaml — requests from Flowlu to your webhook (file attached to the article)
- incoming_events.yaml — events from your application to Flowlu (file attached to the article)
Integration workflow
CRM User Flowlu (CRM) Your Application
│ │ │
│ Clicks "Connect" │ │
│────────────────────────>│ │
│ │ │
│ │ Opens iframe (POST │
│ │ with auth data) │
│ │───────────────────────────>│
│ │ │
│ │ Receives OAuth tokens │
│ │<───────────────────────────│
│ │ │
│ │ GET /api/v1/module/ │
│ │ core/user/get │
│ │<───────────────────────────│
│ │ │
│ │ {id, name, email} │
│ │───────────────────────────>│
│ │ │
│ │ POST /api/v1/module/ │
│ │ telephony/telephony/create│
│ │<───────────────────────────│
│ │ │
│ │ {uuid: telephony_uuid} │
│ │───────────────────────────>│
│ │ │
│ Integration is ready │ │
│<────────────────────────│ │
│ │ │
After this, the CRM begins sending requests to the webhook_url, and your application can send call events to Flowlu.
- attach_file incoming_events.yaml (23.66KB)
- attach_file outgoing_hooks.yaml (14.71KB)