Feature: Custo-manifest (Rainbow Extensions) — telephony events
Licence: All licences — Cloud PBX · OmniPCX Enterprise · OXO Connect
License detail: PBX event extensions are the only custo-manifest extension family available with an Essentials license.
You can use this article to configure automatic actions triggered by PBX call events. You will see when each event fires, which fields are required, and how to pass Rainbow call context to your REST endpoint or local script.
Overview
PBX call events let you trigger automatic actions when a call starts ringing, is answered, or ends — without manual intervention. This feature is available to all Rainbow licences for companies connected to a Cloud PBX or Alcatel-Lucent Enterprise PBX (OmniPCX Enterprise or OXO Connect).
What you can do with PBX call events:
- Open a CRM application (desktop app or web page) automatically when a call arrives or ends
- Push caller information to a REST API (screen pop, call logging, data enrichment)
- Execute a follow-up action when the call is answered or released
- React to outgoing calls to log or trigger a workflow
PBX call event types
| Extension point | When it fires |
|---|---|
| on-incoming-pbx-call-actions | Incoming call starts ringing |
| on-answering-incoming-pbx-call-actions | User answers an incoming call |
| on-releasing-incoming-pbx-call-actions | Incoming or outgoing call ends |
| on-outgoing-pbx-call-actions | User places an outgoing call |
| on-makecall-insert-correlator | At each makecall — inserts a correlator (OXE only) |
Configuring a PBX event action
The custo-manifest is a JSON object with the following structure:
{
"version": "2",
"jsonType": "Rainbow-custo-manifest",
"extension-points": {
"<EXTENSION-POINT-KEY>": [
{
"name": "...",
"command": {
"url": "...",
"params": "...",
"commandType": "rest",
"method": "GET"
},
"icon": "...",
}
]
}
}Global rules:
- version must be "2".
- jsonType must be "Rainbow-custo-manifest". Inside a ZIP, this field identifies which JSON file is the manifest.
- Each key under extension-points is an array — up to 3 actions maximum per extension point.
- Each action contains at least a name (for events it is optional) and a valid command object.
Action fields
| Field | Position | Description |
|---|---|---|
| name | root | Text shown (button/widget title, menu label). Mandatory depending on the EP. |
| icon / iconId | root | Button icon (URL, ${custo.path}\... or built-in sprite). Mandatory for icon buttons. |
| tooltip | root | Tooltip text. Optional. |
| command | root | Command object (see §3.2). Always mandatory. |
The command object
The command object is always mandatory and carries at least a url. Depending on the chosen commandType, additional sub-fields are valid.
"command": {
"url": "{{server}}/your-endpoint",
"params": "user=${localUser.email}",
"commandType": "rest",
"method": "GET",
"header": ["Authorization: Bearer TOKEN"],
"bodyParameters": { "key": "value" }
}| Field | When to use it |
|---|---|
| url | Mandatory. Application path, Web URL, file or REST API. |
| params | Optional. Appended after ? for GET, or as URL parameters. Variables allowed. |
| commandType | Optional. Default "rest". Values: "rest", "file" (depending on EP). |
| method | Optional (only if commandType: "rest"). Values: "GET", "POST". |
| header | Optional (if REST). Array of "Header-Name: value" strings inserted as HTTP headers. |
| bodyParameters | Mandatory if method: "POST". JSON object sent as body. Variables allowed. |
Rainbow Variables
$Variables are replaced at runtime with their actual value. They can appear in command.url, command.params, command.bodyParameters, and in content returned to the extension for display.
Syntax
${object.attribute}
${object.attribute.regex(pattern)}
${object.attribute.regex(pattern, replacement)}Available objects and attributes
Rainbow user (ME)
${localUser.firstName} ${localUser.lastName}
${localUser.email} ${localUser.canonicalNumber}
${localUser.phoneNumber} ${localUser.internalNumber}
${localUser.phonePbx} ${localUser.nickname}
${localUser.loginEmail} ${localUser.id}Caller
${caller.firstName} ${caller.lastName} ${caller.phoneNumber}Called
${called.phoneNumber}Call context
${call.callId}
${call.globalCallId} (OXE only)
${call.correlator}Contact (if identified)
${contact.firstName} ${contact.lastName}
${contact.phoneNumber} ${contact.email}
${contact.company} ${contact.workNumber}
${contact.mobileNumber} ${contact.personalNumber}
${contact.personalMobile}
${contact.tags} (concatenated, comma-separated)Compatibility — PBX call events
| Extension point | Allowed variable objects |
|---|---|
| Outgoing call events | localUser, called, call, contact |
| Incoming call events (incoming / answering / releasing) | localUser, caller, called, call, contact |
regex modifier
Applies a regex to the variable value before substitution:
// Normalize a number — replace +33 or +1 by 0
"params": "pbx=${localUser.phonePbx.regex(^\+33|^\+1, 0)}"
// Replace email domain
"params": "byEmail=${localUser.email.regex(alcatel.com, al-enterprise.com)}"
// Extract last 9 digits (no replacement = extraction)
"params": "${called.phoneNumber.regex(.{0,9}$)}"${time} variable
Available on all extension points — substituted at the moment the action is executed.
| Variable | Value |
|---|---|
| ${time} | Full date-time (ISO 8601, e.g. 2026-05-18T15:30:45.123Z) |
| ${time.year} | Year — 4 digits |
| ${time.month} | Month — 01-12 |
| ${time.day} | Day — 01-31 |
| ${time.hour} | Hour — 00-23 |
| ${time.minute} | Minute — 00-59 |
| ${time.second} | Second — 00-59 |
| ${time.millisec} | Milliseconds — 000-999 |
// Build a log identifier
"params": "logId=${time.year}-${time.month}-${time.day}_${time.hour}${time.minute}${time.second}"Local resources — ${custo.path}
To distribute a manifest with local files (icons or display files):
- Reference each resource as ${custo.path}\\file-name.ext
- Package custo-manifest.json and the resource files into a ZIP (manifest at the root)
{
"icon": "${custo.path}\\basketball.png",
"command": {
"commandType": "file",
"url": "${custo.path}\\FileDisplay.txt"
},
"responseType": "markdown"
}Event-specific fields
| Field | Description |
|---|---|
| "filter" | "NoShortNumber" — does not fire if the caller number is a short (internal) number |
| "RaiseChangeCall" | false = direct calls only · true = direct + transferred calls · "only" = transferred calls only |
Including local resources (ZIP archive)
If the action references local files (icons or display files), package the custo-manifest.json with those files in a .zip archive before importing.
Required ZIP structure — the manifest must be at the root:
my-manifest.zip
├── custo-manifest.json
├── icon.png
└── display-content.txtDeploying the manifest
Once the manifest is configured, deploy it via the Rainbow administration console or locally. See Deploying a custo-manifest in Rainbow.
Examples of configuration
Execute an application or script with parameters
Only supported by Rainbow Desktop.
Example 1 — on-incoming-pbx-call-actions executes a desktop application (e.g. MicroCRM) with a parameter from params (no return):
{
"version": "2",
"jsonType": "Rainbow-custo-manifest",
"extension-points": {
"on-incoming-pbx-call-actions": [
{
"name": "Exec CRM",
"command": {
"url": "C:\\MyApp\\CustoApp\\MicroCRM.exe",
"params": "-number ${caller.phoneNumber}"
}
}
]
}
}Example 2 — on-incoming-pbx-call-actions executes a script (.bat) with multiple parameters from params (no return):
{
"version": "2",
"jsonType": "Rainbow-custo-manifest",
"extension-points": {
"on-incoming-pbx-call-actions": [
{
"name": "BatScript",
"command": {
"url": "C:\\MyApp\\MyApp.bat",
"params": "IN-COMING canNr:${localUser.canonicalNumber} userIntNr:${localUser.internalNumber}
callerNr:${caller.phoneNumber} FN:${caller.firstName} LN:${caller.lastName}
CorData:${call.correlatorData} Hex:${call.hexCorrelatorData}"
}
}
]
}
}Open a web page with parameters
Supported by Rainbow Desktop and Rainbow Web.
Example 1 — on-incoming-pbx-call-actions opens a web page with caller number as query parameter (no return):
{
"version": "2",
"jsonType": "Rainbow-custo-manifest",
"extension-points": {
"on-incoming-pbx-call-actions": [
{
"name": "Yellow pages",
"command": {
"url": "https://www.pagesjaunes.fr/annuaireinverse/recherche",
"params": "quoiqui=${caller.phoneNumber}&proximite=0"
}
}
]
}
}Example 2 — on-incoming-pbx-call-actions opens a web page with the caller number embedded directly in the URL (no return):
{
"version": "2",
"jsonType": "Rainbow-custo-manifest",
"extension-points": {
"on-incoming-pbx-call-actions": [
{
"name": "Contact popup",
"command": {
"url": "http://localhost:3000/contactShow?phone=${caller.phoneNumber}"
}
}
]
}
}Execute a REST API call with parameters
Supported by Rainbow Desktop and Rainbow Web — requires the API server to respond to CORS requests.
Example 1 — When the incoming call ends, on-releasing-incoming-pbx-call-actions creates a call log via REST GET with parameters in params (no return):
{
"version": "2",
"jsonType": "Rainbow-custo-manifest",
"extension-points": {
"on-releasing-incoming-pbx-call-actions": [
{
"name": "GetRestApi",
"command": {
"commandType": "rest",
"method": "GET",
"url": "http://localhost:3000/IncidentManager/CreateCallLog",
"params": "byEmail=${localUser.email}&CustomerContact=${caller.phoneNumber}"
}
}
]
}
}Example 2 — When the incoming call ends, on-releasing-incoming-pbx-call-actions creates a call log via REST POST with a JSON body (no return):
{
"version": "2",
"jsonType": "Rainbow-custo-manifest",
"extension-points": {
"on-releasing-incoming-pbx-call-actions": [
{
"name": "PostRestApi",
"command": {
"commandType": "rest",
"method": "POST",
"url": "http://localhost:3000/IncidentManager/EndCallLog",
"bodyParameters": {
"caller": "${contact.phoneNumber}",
"user": "${localUser.email}"
}
}
}
]
}
}