Extensions
An extension is a phone system user: short number, name, SIP credentials for phones and softphones, voicemail, forwarding and recording. Scopes extensions:read / extensions:write.
Creating an extension
curl -s -X POST https://centralino.exovoip.it/api/v1/extensions \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" \
-d '{"number":"105","name":"Giulia Verdi","email":"giulia.verdi@example.com",
"voicemail":{"enabled":true,"email":"giulia.verdi@example.com"}}'const { extension, sipPassword } = await pbx.extensions.create({
number: '105',
name: 'Giulia Verdi',
email: 'giulia.verdi@example.com',
voicemail: { enabled: true, email: 'giulia.verdi@example.com' },
});
// sipPassword: mostrata solo ora (rigenerabile con extensions.resetPassword)$out = $pbx->extensions->create([
'number' => '105',
'name' => 'Giulia Verdi',
'email' => 'giulia.verdi@example.com',
'voicemail' => ['enabled' => true, 'email' => 'giulia.verdi@example.com'],
]);
$sipPassword = $out['sipPassword'];out = pbx.extensions.create({
"number": "105",
"name": "Giulia Verdi",
"email": "giulia.verdi@example.com",
"voicemail": {"enabled": True, "email": "giulia.verdi@example.com"},
})
sip_password = out["sipPassword"]Main fields:
| Field | Description |
|---|---|
number | Extension number (unique within the tenant) |
name, email | Display name and address for notifications and voicemail |
voicemail | Voicemail: enabled, email, PIN |
followMe | Forwarding to mobile |
forwarding | Destinations for busy / no answer / unreachable |
recordMode | Recording: inherit, always, on_demand, never |
The SIP password is returned on creation and by POST /v1/extensions/:id/password (regeneration). GET /v1/extensions/:id/sip-credentials returns the full credentials for configuring a phone or the WebRTC softphone.
Limits: if the tenant has reached its maximum number of extensions, creation returns 409 LIMIT_REACHED.
Updating, searching, deleting
curl -s "https://centralino.exovoip.it/api/v1/extensions?registered=false" -H "X-API-Key: $EXOPBX_API_KEY"
curl -s -X PATCH https://centralino.exovoip.it/api/v1/extensions/12 -H "X-API-Key: $EXOPBX_API_KEY" \
-H "Content-Type: application/json" -d '{"name":"Giulia Verdi (Vendite)"}'
curl -s https://centralino.exovoip.it/api/v1/extensions/12/sip-credentials -H "X-API-Key: $EXOPBX_API_KEY"
curl -s -X DELETE https://centralino.exovoip.it/api/v1/extensions/12 -H "X-API-Key: $EXOPBX_API_KEY"const offline = await pbx.extensions.list({ registered: false });
await pbx.extensions.update(12, { name: 'Giulia Verdi (Vendite)' });
const sip = await pbx.extensions.sipCredentials(12); // username, password, domain, wssUrl, porte
await pbx.extensions.delete(12);$offline = $pbx->extensions->list(registered: false);
$pbx->extensions->update(12, ['name' => 'Giulia Verdi (Vendite)']);
$sip = $pbx->extensions->sipCredentials(12);
$pbx->extensions->delete(12);offline = pbx.extensions.list(registered=False)
pbx.extensions.update(12, {"name": "Giulia Verdi (Vendite)"})
sip = pbx.extensions.sip_credentials(12)
pbx.extensions.delete(12)List filters: q (number or name), enabled, registered. Real-time status (registered, busy, ringing, connected devices) is covered in Real-time.
Forwarding to mobile
curl -s -X PUT https://centralino.exovoip.it/api/v1/extensions/12/follow-me \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" \
-d '{"enabled":true,"number":"+393331234567","rings":3,"mode":"sequential"}'await pbx.extensions.followMe(12, {
enabled: true,
number: '+393331234567',
rings: 3,
mode: 'sequential',
});$pbx->extensions->followMe(12, ['enabled' => true, 'number' => '+393331234567', 'rings' => 3, 'mode' => 'sequential']);pbx.extensions.follow_me(12, {"enabled": True, "number": "+393331234567", "rings": 3, "mode": "sequential"})External destinations follow the tenant's allowed-destinations policy (national only, national and European, all): a number that is not allowed returns 400 VALIDATION_ERROR with the reason in the details. For forwarding with announcement or in silent mode, see Mobile forwarding.
Feature codes and Do Not Disturb
From their phone, enabled extensions (canOverrideHours field) can force business hours open or closed (*90 closed, *91 open, *92 reset, *93 status). Each extension can also switch itself off or back on with *94 (off) and *95 (on): see Extension hours and status. The optional PIN for the business-hours codes is set like this:
curl -s -X PUT https://centralino.exovoip.it/api/v1/feature-codes/settings \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" -d '{"overridePin":"4821"}'await pbx.featureCodes.setSettings({ overridePin: '4821' }); // null per rimuovere il PIN$pbx->featureCodes->setSettings(['overridePin' => '4821']);pbx.feature_codes.set_settings({"overridePin": "4821"})An extension's Do Not Disturb feature, when available on your phone system, appears among the endpoints below, and its status is visible in the dnd and availability fields of the real-time data.
Extension hours and status
Each extension has its own hours, which decide when it receives calls:
Hours (scheduleMode) | Behaviour |
|---|---|
always | Always on (default) |
tenant | Follows the company's business hours (default calendar) |
calendar | Follows a specific company calendar, set in calendarId |
Outside its hours, or when switched off, the extension does not ring: neither its phones nor the mobile linked through forwarding. The call follows the extension's "no answer" rule; if none is set, it goes to voicemail (if enabled). In ring groups and queues the extension is skipped. Callers from another extension, including during an attended transfer, first hear the message "The extension you called is not available at the moment".
The status can be forced at any time:
- from the phone:
*94switches your own extension off and*95switches it on, with a voice confirmation; - from the control panel: on the extension page, "Hours and status" card, with the Switch on, Switch off and Back to schedule buttons; the hours are chosen in the same card;
- via API:
forcefield withon,offorauto(back to schedule).
The override lasts until the extension's next scheduled change (with "Always on", until changed again) and does not affect the company's business hours, which are managed with *90–*93.
curl -s https://centralino.exovoip.it/api/v1/extensions/12/availability -H "X-API-Key: $EXOPBX_API_KEY"
curl -s -X PUT https://centralino.exovoip.it/api/v1/extensions/12/availability \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" \
-d '{"scheduleMode":"calendar","calendarId":3}'
curl -s -X PUT https://centralino.exovoip.it/api/v1/extensions/12/availability \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" -d '{"force":"off"}'const { availability } = await pbx.extensions.getAvailability(12);
await pbx.extensions.setAvailability(12, { scheduleMode: 'calendar', calendarId: 3 });
await pbx.extensions.setAvailability(12, { force: 'off' }); // 'auto' per tornare all'orario$state = $pbx->extensions->getAvailability(12);
$pbx->extensions->setAvailability(12, ['scheduleMode' => 'calendar', 'calendarId' => 3]);
$pbx->extensions->setAvailability(12, ['force' => 'off']);state = pbx.extensions.get_availability(12)
pbx.extensions.set_availability(12, {"scheduleMode": "calendar", "calendarId": 3})
pbx.extensions.set_availability(12, {"force": "off"})The response includes the hours, the current override with its expiry (forceExpiresAt, null when it lasts until changed again) and available, i.e. whether the extension is receiving calls right now. Fields omitted from the PUT are left unchanged.
User role
Control panel users with the "user" role can view and edit only their own extension (details, forwarding, hours and status, SIP credentials).
Endpoints
| Request | Scope | SDK method |
|---|---|---|
GET /v1/feature-codes/settings | extensions:read | featureCodes.getSettings() · py: feature_codes.get_settings() |
PUT /v1/feature-codes/settings | extensions:write | featureCodes.setSettings() · py: feature_codes.set_settings() |
GET /v1/extensions | extensions:read | extensions.list() |
POST /v1/extensions | extensions:write | extensions.create() |
GET /v1/extensions/:id | extensions:read | extensions.get() |
PATCH /v1/extensions/:id | extensions:write | extensions.update() |
DELETE /v1/extensions/:id | extensions:write | extensions.delete() |
PUT /v1/extensions/:id/follow-me | extensions:write | extensions.followMe() · py: extensions.follow_me() |
GET /v1/extensions/:id/dnd | extensions:read | extensions.getDnd() · py: extensions.get_dnd() |
PUT /v1/extensions/:id/dnd | extensions:write | extensions.setDnd() · py: extensions.set_dnd() |
GET /v1/extensions/:id/availability | extensions:read | extensions.getAvailability() · py: extensions.get_availability() |
PUT /v1/extensions/:id/availability | extensions:write | extensions.setAvailability() · py: extensions.set_availability() |
POST /v1/extensions/:id/password | extensions:write | extensions.resetPassword() · py: extensions.reset_password() |
GET /v1/extensions/:id/sip-credentials | extensions:write | extensions.sipCredentials() · py: extensions.sip_credentials() |
