Pacchetti
I pacchetti sono i piani commerciali di ExoVoIP: ogni pacchetto stabilisce cosa comprende il centralino di un'azienda. L'amministratore della piattaforma crea i pacchetti, ne assegna uno a ogni azienda e può fissare eccezioni per la singola azienda. I limiti effettivi sono quelli del pacchetto, con le eccezioni dell'azienda al posto delle voci corrispondenti.
Voci del pacchetto
| Campo | Significato | Quando si supera |
|---|---|---|
maxExt | Interni disponibili (0 = nessuno) | POST /v1/extensions risponde 409 LIMIT_REACHED |
maxCalls | Chiamate esterne contemporanee, in entrata e in uscita | Il centralino rifiuta le chiamate oltre il limite |
maxTrunks | Linee proprie dell'azienda (le linee condivise della piattaforma non contano) | POST /v1/trunks risponde 409 LIMIT_REACHED |
maxNumbers | Numeri assegnati all'azienda | Creazione e assegnazione dei numeri rispondono 409 LIMIT_REACHED |
maxPrompts | Messaggi vocali: messaggi, annunci, musiche e avvisi (esclusi gli avvisi creati per gli inoltri) | POST /v1/prompts e il caricamento rispondono 409 LIMIT_REACHED |
maxStorageMb | Spazio massimo per le registrazioni (MB) | Lo spazio scelto dall'azienda (quotaMb) non può superarlo |
aiMonthlyMinutes | Minuti di trascrizione AI al mese (registrazioni e segreteria) | Le nuove trascrizioni del mese non vengono eseguite |
maxAppDevices | Dispositivi con l'app ExoVoIP per ogni interno | L'attivazione di un nuovo dispositivo risponde 409 LIMIT_REACHED |
plugins | Funzioni extra incluse | Le funzioni non incluse rispondono 403 PLUGIN_REQUIRED |
null significa senza limite (ammesso per maxTrunks, maxNumbers, maxPrompts, maxStorageMb e aiMonthlyMinutes). L'errore 409 LIMIT_REACHED riporta in details la voce (limit), il massimo (max) e, dove serve, l'utilizzo attuale (used).
Limiti e utilizzo dell'azienda
GET /v1/tenants/current/limits (scope extensions:read) restituisce il pacchetto dell'azienda della chiave, i limiti effettivi in limits e l'utilizzo in usage: interni, linee, numeri, messaggi vocali, spazio occupato dalle registrazioni (MB) e minuti di trascrizione usati nel mese in corso.
# Limiti del pacchetto e utilizzo dell'azienda della chiave
curl -s https://centralino.exovoip.it/api/v1/tenants/current/limits -H "X-API-Key: $EXOPBX_API_KEY"
# Oltre un limite
# HTTP/1.1 409 Conflict
# {"error":{"code":"LIMIT_REACHED","message":"Il pacchetto comprende al massimo 10 messaggi vocali","details":{"limit":"prompts","max":10,"used":10}}}import { isExoPBXError } from '@exobyte/exopbx-sdk';
const { limits, usage } = await pbx.tenants.currentLimits();
console.log(`Interni: ${usage.extensions} su ${limits.maxExt}`);
try {
await pbx.prompts.createTts({ name: 'Benvenuto', text: 'Benvenuti!', kind: 'prompt' });
} catch (err) {
if (isExoPBXError(err, 'LIMIT_REACHED')) {
const { limit, max } = err.details as { limit: string; max: number };
console.log(`Limite del pacchetto raggiunto (${limit}: ${max})`);
} else throw err;
}use Exobyte\ExoPBX\ApiException;
$out = $pbx->tenants->currentLimits();
echo 'Interni: ', $out['usage']['extensions'], ' su ', $out['limits']['maxExt'], PHP_EOL;
try {
$pbx->prompts->createTts(['name' => 'Benvenuto', 'text' => 'Benvenuti!', 'kind' => 'prompt']);
} catch (ApiException $e) {
if ($e->getErrorCode() !== 'LIMIT_REACHED') throw $e;
echo 'Limite raggiunto: ', $e->getDetails()['limit'], PHP_EOL;
}from exopbx import ExoPBXError
out = pbx.tenants.current_limits()
print("Interni:", out["usage"]["extensions"], "su", out["limits"]["maxExt"])
try:
pbx.prompts.create_tts({"name": "Benvenuto", "text": "Benvenuti!", "kind": "prompt"})
except ExoPBXError as err:
if err.code != "LIMIT_REACHED":
raise
print("Limite raggiunto:", err.details["limit"])Gestione dei pacchetti (amministratore della piattaforma)
Gli endpoint packages.* sono riservati all'amministratore della piattaforma (scope tenants:read / tenants:write).
POST /v1/packagescrea un pacchetto con nome, descrizione e tutte le voci inlimits;isDefault: truelo rende il pacchetto proposto alle nuove aziende (uno solo alla volta).PATCH /v1/packages/:idmodifica nome, descrizione e singole voci: i nuovi limiti valgono subito per tutte le aziende del pacchetto, tranne le voci che l'azienda ha come eccezione.DELETE /v1/packages/:idelimina un pacchetto non assegnato; se è assegnato ad aziende o è quello proposto alle nuove aziende risponde409 IN_USE.
All'installazione esiste il pacchetto Standard (50 interni, 10 chiamate contemporanee, nessun altro limite, nessuna funzione extra): le aziende già presenti lo ricevono e conservano come eccezioni i limiti che avevano prima.
Pacchetto ed eccezioni di un'azienda
GET /v1/tenants/:id/package restituisce pacchetto, eccezioni (overrides), limiti effettivi e utilizzo dell'azienda. PUT /v1/tenants/:id/package assegna il pacchetto e, con overrides, sostituisce le eccezioni ({} le toglie tutte; senza overrides restano quelle attuali). Le eccezioni uguali al pacchetto vengono tolte automaticamente.
Anche PUT /v1/tenants/:id/limits (interni e chiamate), PUT /v1/tenants/:id/plugins (funzioni extra) e aiMonthlyMinutes in PATCH /v1/tenants/:id salvano eccezioni dell'azienda. Chiamate contemporanee e funzioni extra si applicano subito al centralino.
# Solo amministratore della piattaforma (chiave globale)
curl -s -X POST https://centralino.exovoip.it/api/v1/packages -H "X-API-Key: $EXOPBX_API_KEY" \
-H "Content-Type: application/json" -d '{
"name": "Professional",
"limits": {"maxExt": 100, "maxCalls": 20, "maxTrunks": 2, "maxNumbers": 10,
"maxPrompts": null, "maxStorageMb": 10240, "aiMonthlyMinutes": 300,
"maxAppDevices": 5, "plugins": ["recording"]}
}'
# Assegna il pacchetto all'azienda 3 con un'eccezione: 30 chiamate contemporanee
curl -s -X PUT https://centralino.exovoip.it/api/v1/tenants/3/package -H "X-API-Key: $EXOPBX_API_KEY" \
-H "Content-Type: application/json" -d '{"packageId": 2, "overrides": {"maxCalls": 30}}'const { package: pro } = await pbx.packages.create({
name: 'Professional',
limits: {
maxExt: 100,
maxCalls: 20,
maxTrunks: 2,
maxNumbers: 10,
maxPrompts: null,
maxStorageMb: 10240,
aiMonthlyMinutes: 300,
maxAppDevices: 5,
plugins: ['recording'],
},
});
const view = await pbx.tenants.setPackage(3, { packageId: pro.id, overrides: { maxCalls: 30 } });
console.log(view.limits.maxCalls, view.usage.extensions);
// Nuovi limiti del pacchetto: valgono subito per tutte le sue aziende
await pbx.packages.update(pro.id, { limits: { maxExt: 120 } });$out = $pbx->packages->create([
'name' => 'Professional',
'limits' => [
'maxExt' => 100, 'maxCalls' => 20, 'maxTrunks' => 2, 'maxNumbers' => 10,
'maxPrompts' => null, 'maxStorageMb' => 10240, 'aiMonthlyMinutes' => 300,
'maxAppDevices' => 5, 'plugins' => ['recording'],
],
]);
$view = $pbx->tenants->setPackage(3, [
'packageId' => $out['package']['id'],
'overrides' => ['maxCalls' => 30],
]);out = pbx.packages.create({
"name": "Professional",
"limits": {
"maxExt": 100, "maxCalls": 20, "maxTrunks": 2, "maxNumbers": 10,
"maxPrompts": None, "maxStorageMb": 10240, "aiMonthlyMinutes": 300,
"maxAppDevices": 5, "plugins": ["recording"],
},
})
view = pbx.tenants.set_package(3, {"packageId": out["package"]["id"], "overrides": {"maxCalls": 30}})Endpoint
| Descrizione | Richiesta | Scope | Metodo SDK |
|---|---|---|---|
| Elenco pacchetti con il numero di aziende che li usano | GET /v1/packages | tenants:read | packages.list() |
| Crea pacchetto | POST /v1/packages | tenants:write | packages.create() |
| Dettaglio pacchetto | GET /v1/packages/:id | tenants:read | packages.get() |
| Modifica pacchetto (i nuovi limiti valgono subito per tutte le sue aziende) | PATCH /v1/packages/:id | tenants:write | packages.update() |
| Elimina pacchetto (409 IN_USE se assegnato o proposto alle nuove aziende) | DELETE /v1/packages/:id | tenants:write | packages.delete() |