Orari e chiusure
I calendari definiscono quando l'azienda è aperta: fasce settimanali, festività, eccezioni (chiusure o aperture straordinarie) e forzature manuali. Numeri, regole, menu e code possono seguire un calendario. Scope calendars:read / calendars:write.
Creare un calendario
curl -s -X POST https://centralino.exovoip.it/api/v1/calendars \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"Ufficio","timezone":"Europe/Rome","isDefault":true,
"closedDestination":{"type":"voicemail","extensionId":12},
"hours":[{"weekday":1,"start":"09:00","end":"13:00"},{"weekday":1,"start":"14:00","end":"18:00"}],
"preloadHolidays":true}'const { calendar } = await pbx.calendars.create({
name: 'Ufficio',
timezone: 'Europe/Rome',
isDefault: true,
closedDestination: { type: 'voicemail', extensionId: 12 },
hours: [
{ weekday: 1, start: '09:00', end: '13:00' },
{ weekday: 1, start: '14:00', end: '18:00' },
],
preloadHolidays: true, // festività nazionali italiane
});$calendar = $pbx->calendars->create([
'name' => 'Ufficio',
'timezone' => 'Europe/Rome',
'isDefault' => true,
'closedDestination' => ['type' => 'voicemail', 'extensionId' => 12],
'hours' => [
['weekday' => 1, 'start' => '09:00', 'end' => '13:00'],
['weekday' => 1, 'start' => '14:00', 'end' => '18:00'],
],
'preloadHolidays' => true,
])['calendar'];calendar = pbx.calendars.create({
"name": "Ufficio",
"timezone": "Europe/Rome",
"isDefault": True,
"closedDestination": {"type": "voicemail", "extensionId": 12},
"hours": [
{"weekday": 1, "start": "09:00", "end": "13:00"},
{"weekday": 1, "start": "14:00", "end": "18:00"},
],
"preloadHolidays": True,
})["calendar"]hours: fasce per giorno della settimana (weekdayda 1 = lunedì a 7 = domenica, orariHH:MM,24:00per fine giornata). Più fasce nello stesso giorno sono consentite.PUT /v1/calendars/:id/hourssostituisce tutte le fasce.openDestination/closedDestination: dove vanno le chiamate in orario e fuori orario (usate dalla destinazionecalendar).closedPromptIdriproduce un messaggio prima della destinazione di chiusura.isDefault: il calendario predefinito dell'azienda, usato dai codici funzione*90–*93.preloadHolidays: carica le festività nazionali;POST /v1/calendars/:id/holidaysaggiunge anche il santo patrono del comune (codice ISTAT).
Forzare aperto o chiuso
Una forzatura ha la precedenza su orari ed eccezioni. È lo strumento per chiusure improvvise (inventario, emergenze) o aperture straordinarie.
# Chiuso per 2 ore
curl -s -X POST https://centralino.exovoip.it/api/v1/calendars/4/force \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" \
-d '{"state":"closed","mode":"hours","hours":2,"note":"Inventario"}'
# Stato attuale
curl -s https://centralino.exovoip.it/api/v1/calendars/4/status -H "X-API-Key: $EXOPBX_API_KEY"
# Ritorno agli orari normali
curl -s -X DELETE https://centralino.exovoip.it/api/v1/calendars/4/force -H "X-API-Key: $EXOPBX_API_KEY"await pbx.calendars.force(4, { state: 'closed', mode: 'hours', hours: 2, note: 'Inventario' });
const status = await pbx.calendars.status(4); // { state, reason, nextTransitionAt, force, ... }
await pbx.calendars.clearForce(4);$pbx->calendars->force(4, ['state' => 'closed', 'mode' => 'hours', 'hours' => 2, 'note' => 'Inventario']);
$status = $pbx->calendars->status(4);
$pbx->calendars->clearForce(4);pbx.calendars.force(4, {"state": "closed", "mode": "hours", "hours": 2, "note": "Inventario"})
status = pbx.calendars.status(4)
pbx.calendars.clear_force(4)Modalità di scadenza (mode):
mode | Durata |
|---|---|
next_transition | Fino al prossimo cambio previsto dagli orari. Per una chiusura forzata: fino alla prossima apertura prevista (es. da venerdì sera a lunedì mattina). Predefinita. |
hours | Per hours ore (1–720) |
until | Fino alla data e ora until |
manual | Finché non viene rimossa con DELETE /v1/calendars/:id/force |
# Aperto fino alla prossima variazione prevista dagli orari
curl -s -X POST https://centralino.exovoip.it/api/v1/calendars/4/force -H "X-API-Key: $EXOPBX_API_KEY" \
-H "Content-Type: application/json" -d '{"state":"open","mode":"next_transition"}'
# Chiuso fino a una data e ora precise
curl -s -X POST https://centralino.exovoip.it/api/v1/calendars/4/force -H "X-API-Key: $EXOPBX_API_KEY" \
-H "Content-Type: application/json" -d '{"state":"closed","mode":"until","until":"2026-12-27T08:00:00.000Z"}'
# Chiuso finché non viene rimossa la forzatura
curl -s -X POST https://centralino.exovoip.it/api/v1/calendars/4/force -H "X-API-Key: $EXOPBX_API_KEY" \
-H "Content-Type: application/json" -d '{"state":"closed","mode":"manual"}'await pbx.calendars.force(4, { state: 'open', mode: 'next_transition' });
await pbx.calendars.force(4, { state: 'closed', mode: 'until', until: '2026-12-27T08:00:00.000Z' });
await pbx.calendars.force(4, { state: 'closed', mode: 'manual' });$pbx->calendars->force(4, ['state' => 'open', 'mode' => 'next_transition']);
$pbx->calendars->force(4, ['state' => 'closed', 'mode' => 'until', 'until' => '2026-12-27T08:00:00.000Z']);
$pbx->calendars->force(4, ['state' => 'closed', 'mode' => 'manual']);pbx.calendars.force(4, {"state": "open", "mode": "next_transition"})
pbx.calendars.force(4, {"state": "closed", "mode": "until", "until": "2026-12-27T08:00:00.000Z"})
pbx.calendars.force(4, {"state": "closed", "mode": "manual"})GET /v1/calendars/:id/status restituisce lo stato attuale (open / closed), il motivo (force, exception, weekly, no_hours), la prossima variazione e l'eventuale forzatura attiva. Lo storico delle forzature (da pannello, API o telefono) è in GET /v1/calendars/:id/overrides.
Ogni forzatura genera l'evento in tempo reale calendar.override (anche per i webhook) e, se configurata, una notifica.
Dal telefono: gli interni abilitati usano *90 (chiuso), *91 (aperto), *92 (ripristina orari) e *93 (stato), con PIN facoltativo. Vedi Interni. Ogni interno può anche seguire un calendario dell'azienda e spegnersi o riaccendersi da solo con *94 / *95: vedi Orari e stato dell'interno.
Eccezioni e simulazione
Le eccezioni coprono periodi con orari diversi: ferie, ponti, aperture straordinarie. Il simulatore restituisce lo stato del calendario in un momento qualsiasi, con il dettaglio della giornata.
curl -s -X POST https://centralino.exovoip.it/api/v1/calendars/4/exceptions \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" \
-d '{"name":"Chiusura estiva","type":"closed","dateFrom":"2026-08-10","dateTo":"2026-08-21"}'
curl -s -X POST https://centralino.exovoip.it/api/v1/calendars/4/simulate \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" -d '{"at":"2026-08-12T10:00:00+02:00"}'await pbx.calendars.createException(4, {
name: 'Chiusura estiva',
type: 'closed',
dateFrom: '2026-08-10',
dateTo: '2026-08-21',
});
const sim = await pbx.calendars.simulate(4, { at: '2026-08-12T10:00:00+02:00' });$pbx->calendars->createException(4, ['name' => 'Chiusura estiva', 'type' => 'closed', 'dateFrom' => '2026-08-10', 'dateTo' => '2026-08-21']);
$sim = $pbx->calendars->simulate(4, ['at' => '2026-08-12T10:00:00+02:00']);pbx.calendars.create_exception(4, {"name": "Chiusura estiva", "type": "closed", "dateFrom": "2026-08-10", "dateTo": "2026-08-21"})
sim = pbx.calendars.simulate(4, {"at": "2026-08-12T10:00:00+02:00"})Import ed export in formato iCal (.ics): POST /v1/calendars/:id/ical/import (testo o URL), GET /v1/calendars/:id/ical/export.ics; con icalUrl impostato la sincronizzazione è periodica (POST /v1/calendars/:id/ical/sync per forzarla).
Collegare un numero
curl -s -X PUT https://centralino.exovoip.it/api/v1/numbers/7/calendar \
-H "X-API-Key: $EXOPBX_API_KEY" -H "Content-Type: application/json" \
-d '{"calendarId":4,"closedDestination":{"type":"voicemail","extensionId":12}}'await pbx.numbers.setCalendar(7, {
calendarId: 4,
closedDestination: { type: 'voicemail', extensionId: 12 },
});$pbx->numbers->setCalendar(7, ['calendarId' => 4, 'closedDestination' => ['type' => 'voicemail', 'extensionId' => 12]]);pbx.numbers.set_calendar(7, {"calendarId": 4, "closedDestination": {"type": "voicemail", "extensionId": 12}})Endpoint
| Descrizione | Richiesta | Scope | Metodo SDK |
|---|---|---|---|
| Elenco calendari con stato corrente | GET /v1/calendars | calendars:read | calendars.list() |
| Crea calendario (festività nazionali precaricate) | POST /v1/calendars | calendars:write | calendars.create() |
| Anteprima festività di un anno e patroni disponibili | GET /v1/calendars/holidays | calendars:read | calendars.holidays() |
| Dettaglio calendario | GET /v1/calendars/:id | calendars:read | calendars.get() |
| Modifica calendario | PATCH /v1/calendars/:id | calendars:write | calendars.update() |
| Elimina calendario (IN_USE se assegnato) | DELETE /v1/calendars/:id | calendars:write | calendars.delete() |
| Sostituisce le fasce settimanali | PUT /v1/calendars/:id/hours | calendars:write | calendars.setHours() · py: calendars.set_hours() |
| Stato attuale e prossima transizione | GET /v1/calendars/:id/status | calendars:read | calendars.status() |
| Forza aperto/chiuso con scadenza | POST /v1/calendars/:id/force | calendars:write | calendars.force() |
| Ripristina orari automatici | DELETE /v1/calendars/:id/force | calendars:write | calendars.clearForce() · py: calendars.clear_force() |
| Storico forzature | GET /v1/calendars/:id/overrides | calendars:read | calendars.overrides() |
| Simulatore: cosa succede il giorno X all’ora Y | POST /v1/calendars/:id/simulate | calendars:read | calendars.simulate() |
| Carica festività nazionali e patrono | POST /v1/calendars/:id/holidays | calendars:write | calendars.preloadHolidays() · py: calendars.preload_holidays() |
| Eccezioni (chiusure e aperture straordinarie) | GET /v1/calendars/:id/exceptions | calendars:read | calendars.listExceptions() · py: calendars.list_exceptions() |
| Crea eccezione | POST /v1/calendars/:id/exceptions | calendars:write | calendars.createException() · py: calendars.create_exception() |
| Modifica eccezione | PATCH /v1/calendars/:id/exceptions/:exceptionId | calendars:write | calendars.updateException() · py: calendars.update_exception() |
| Elimina eccezione | DELETE /v1/calendars/:id/exceptions/:exceptionId | calendars:write | calendars.deleteException() · py: calendars.delete_exception() |
| Importa eventi iCal (file o indirizzo) | POST /v1/calendars/:id/ical/import | calendars:write | calendars.importIcal() · py: calendars.import_ical() |
| Esporta in formato iCal | GET /v1/calendars/:id/ical/export.ics | calendars:read | calendars.exportIcal() · py: calendars.export_ical() |
| Sincronizza ora dall’indirizzo iCal configurato | POST /v1/calendars/:id/ical/sync | calendars:write | calendars.syncIcal() · py: calendars.sync_ical() |
