Bible API Wazo — Guide du Développeur Expert
Document technique exclusif — Wazo Platform (Unified Communications as a Service)
Version: 2.0 — Mars 2026
Architecture microservices, REST API, WebSockets, Multi-tenant
CHAPITRE 1 : Fondations et Architecture Wazo
1.1 Écosystème Microservices Wazo
Wazo est une plateforme de communications unifiées reposant sur une architecture microservices distribuée. Chaque service est un démon indépendant, déployé sur le serveur Wazo, communiquant via des APIs RESTful et un bus de messages (RabbitMQ). Cette architecture permet une scalabilité horizontale, une maintenance modulaire et une isolation des fonctionnalités.
1.1.1 Cartographie des Services
IMPORTANT - Routing nginx : Toutes les API Wazo Admin passent par nginx sur le port 443. Les ports directs ci-dessous sont uniquement pour debugging ou accès direct. Utilisez toujours les routes nginx.
| Service | Port Direct | Nginx Route | Version API | Rôle Métier | Base URL Complete |
|---|---|---|---|---|---|
| wazo-auth | 9497 | /api/auth/0.1/* | 0.1 | Authentification, gestion des tokens, ACL | https://{host}/api/auth/0.1 |
| wazo-confd | 9486 | /api/confd/1.1/* | 1.1 | Configuration centrale | https://{host}/api/confd/1.1 |
| wazo-provd | 8667 | /api/provd/0.1/* | 0.1 | Provisioning terminaux | https://{host}/api/provd/0.1 |
| wazo-calld | 9500 | /api/calld/1.0/* | 1.0 | Contrôle appels temps réel | https://{host}/api/calld/1.0 |
| wazo-chatd | 9500 | /api/chatd/1.0/* | 1.0 | Présences XMPP, messaging | https://{host}/api/chatd/1.0 |
| wazo-webhookd | 9300 | /api/webhookd/1.0/* | 1.0 | Webhooks HTTP | https://{host}/api/webhookd/1.0 |
| wazo-call-logd | 9298 | /api/call-logd/1.0/* | 1.0 | Historique CDR | https://{host}/api/call-logd/1.0 |
| wazo-dird | 9489 | /api/dird/0.1/* | 0.1 | Annuaires | https://{host}/api/dird/0.1 |
| wazo-plugind | 9400 | /api/plugind/0.1/* | 0.1 | Plugins système | https://{host}/api/plugind/0.1 |
| wazo-agentd | 9500 | /api/agentd/1.0/* | 1.0 | Gestion agents ACD | https://{host}/api/agentd/1.0 |
| wazo-websocketd | 9502 | /api/websocketd/* | 2.0 | WebSocket events | wss://{host}/api/websocketd/ |
| wazo-amid | 9498 | /api/amid/1.0/* | 1.0 | Proxy AMI Asterisk | https://{host}/api/amid/1.0 |
| wazo-phoned | 9496 | /api/phoned/0.1/* | 0.1 | Push mobile, lookup | https://{host}/api/phoned/0.1 |
Note critique : wazo-calld, wazo-chatd et wazo-agentd partagent le port 9500 mais se distinguent par leur chemin de base. wazo-call-logd utilise le port 9298 (ne partage pas le 9500).
1.1.2 Communication Inter-Services
Les services Wazo communiquent selon deux modèles :
-
Communication synchrone (REST) : Requêtes HTTP directes entre le client et les services. Chaque requête doit inclure un token d’authentification valide.
-
Communication asynchrone (Bus de messages) : Wazo utilise RabbitMQ avec l’échange
wazo(topic). Les événements sont publiés sous forme de messages JSON structurés. Les clients peuvent s’abonner à ces événements via WebSocket ou HTTP long-polling.
// Exemple de message bus (événement user.created)
{
"name": "user_created",
"timestamp": "2026-03-07T15:30:00.000000Z",
"origin_uuid": "server-uuid-001",
"data": {
"uuid": "user-uuid-1234",
"firstname": "Alice",
"lastname": "Dupont",
"tenant_uuid": "tenant-uuid-main"
}
}
1.1.3 Cycle de Vie d’une Requête API
┌─────────────────────────────────────────────────────────────────────────────┐
│ CYCLE DE VIE REQUÊTE API WAZO │
└─────────────────────────────────────────────────────────────────────────────┘
[Client]
│
│ 1. Requête HTTP
│ Headers: X-Auth-Token, Accept, Content-Type
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ wazo-auth (Port 9497) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Validation du token │ │
│ │ ├─ Token expiré? → 401 Unauthorized │ │
│ │ ├─ ACL insuffisante? → 403 Forbidden │ │
│ │ └─ Token valide → Passage à wazo-confd │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
│ (Le token porte les infos: user_uuid, tenant_uuid, ACLs)
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ wazo-confd (Port 9486) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Vérification ACL + Filtrage tenant │ │
│ │ ├─ Tentative d'accès resource autre tenant → 404 │ │
│ │ └─ Autorisé → Exécution opération CRUD │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ Réponse HTTP │ │
│ │ 200/201/204/400/ │ │
│ │ 401/403/404/409/500 │ │
│ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
[Client]
1.2 Architecture Multi-Tenant
Wazo est nativement multi-tenant. Chaque tenant (aussi appelé “organisation” ou “client”) est isolé des autres au niveau des données et des permissions. Cette isolation est gérée à trois niveaux :
- Niveau base de données : Chaque tenant possède ses propres enregistrements dans les tables PostgreSQL.
- Niveau API : Le header
Wazo-Tenantpermet de filtrer les requêtes. - Niveau ACL : Les politiques définissent les droits d’accès par tenant.
1.2.1 Structure Hiérarchique des Tenants
┌─────────────────────────────────────────────────────────────────────────────┐
│ HIÉRARCHIE TENANTS WAZO │
└─────────────────────────────────────────────────────────────────────────────┘
[Tenant Root]
│
┌───────────┴───────────┐
│ │
[Tenant Principal] [Sous-Tenant A]
(Master Tenant) │
│ │
┌─────────┴─────────┐ │
│ │ │
[Sous-Tenant B] [Sous-Tenant C] [Sous-Tenant D]
Chaque tenant possède un UUID unique au format UUID v4 :
tenant-uuid-main: 6118e18b-17e2-49ef-a59c-0759063b9548
tenant-uuid-enfant: a1b2c3d4-e5f6-7890-abcd-ef1234567890
1.2.2 Header Wazo-Tenant — Guide Complet
Le header Wazo-Tenant est obligatoire pour toute opération multi-tenant, sauf pour le tenant principal (root).
Syntaxe
Wazo-Tenant: {tenant_uuid}
Exemples de Requêtes
# Requête SANS header Wazo-Tenant → Accès au tenant root (premier tenant configuré)
curl -k -X GET \
-H "Accept: application/json" \
-H "X-Auth-Token: {token}" \
https://wazo.example.com:9486/api/confd/1.1/users
# Requête AVEC header Wazo-Tenant → Accès à un tenant spécifique
curl -k -X GET \
-H "Accept: application/json" \
-H "X-Auth-Token: {token}" \
-H "Wazo-Tenant: 6118e18b-17e2-49ef-a59c-0759063b9548" \
https://wazo.example.com:9486/api/confd/1.1/users
Création d’un Sous-Tenant
Pour créer un sous-tenant, utilisez l’API wazo-auth :
curl -k -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-Auth-Token: {token}" \
-H "Wazo-Tenant: {tenant_parent_uuid}" \
-d '{
"name": "Sous-Tenant-A",
"slug": "sous-tenant-a"
}' \
https://wazo.example.com:9497/api/auth/0.1/tenants
# Réponse (201 Created)
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Sous-Tenant-A",
"slug": "sous-tenant-a",
"parent_uuid": "6118e18b-17e2-49ef-a59c-0759063b9548"
}
Récupérer la Liste des Tenants Accessibles
curl -k -X GET \
-H "Accept: application/json" \
-H "X-Auth-Token: {token}" \
https://wazo.example.com:9497/api/auth/0.1/tenants
# Réponse (200 OK)
{
"total": 3,
"items": [
{
"uuid": "6118e18b-17e2-49ef-a59c-0759063b9548",
"name": "Tenant Principal",
"slug": "tenant-principal",
"parent_uuid": null
},
{
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Sous-Tenant A",
"slug": "sous-tenant-a",
"parent_uuid": "6118e18b-17e2-49ef-a59c-0759063b9548"
}
]
}
Attention : Si vous êtes administrateur d’un sous-tenant, vous ne pouvez pas créer de tenant parent via l’API. Seuls les administrateurs du tenant root peuvent créer des hiérarchies de tenants.
1.2.3 Isolation des Ressources par Tenant
Chaque ressource Wazo est liée à un tenant_uuid. Les règles d’isolation sont les suivantes :
| Ressource | Champ tenant_uuid | Comportement |
|---|---|---|
| Users | tenant_uuid (propriété) |
Réservé au tenant créateur |
| Lines | tenant_uuid (propriété) |
Réservé au tenant créateur |
| Extensions | tenant_uuid (propriété) |
Réservé au tenant créateur |
| Devices | tenant_uuid (propriété) |
Réservé au tenant créateur |
| Trunks | tenant_uuid (propriété) |
Réservé au tenant créateur |
| Queues | tenant_uuid (propriété) |
Réservé au tenant créateur |
| IVR | tenant_uuid (propriété) |
Réservé au tenant créateur |
| Schedules | tenant_uuid (propriété) |
Réservé au tenant créateur |
Requête avec tenant incorrect :
# Tentative d'accès à un user d'un autre tenant
curl -k -X GET \
-H "X-Auth-Token: {token}" \
-H "Wazo-Tenant: tenant-a-uuid" \
https://wazo.example.com:9486/api/confd/1.1/users/user-uuid-autre-tenant
# Réponse (404 Not Found) — Le user existe mais n'est pas dans ce tenant
{
"error": "Not Found",
"details": "User not found"
}
1.3 Règles Communes des APIs Wazo
1.3.1 Paramètres Génériques
Toutes les APIs Wazo (confd, auth, provd, calld, etc.) partagent un ensemble de paramètres communs pour la manipulation des listes de ressources.
| Paramètre | Type | Description | Exemple |
|---|---|---|---|
limit |
int |
Nombre maximum d’éléments retournés (pagination) | ?limit=25 |
offset |
int |
Index de départ pour la pagination | ?offset=50 |
search |
string |
Recherche textuelle sur tous les champs indexables | ?search=alice |
order |
string |
Colonne de tri | ?order=firstname |
direction |
string |
Ordre de tri : asc ou desc |
?direction=desc |
Exemple Combiné
# Liste des utilisateurs 26-50, triés par nom décroissant, contenant "dupont"
curl -k -X GET \
-H "X-Auth-Token: {token}" \
-H "Wazo-Tenant: {tenant_uuid}" \
"https://wazo.example.com:9486/api/confd/1.1/users?limit=25&offset=25&search=dupont&order=firstname&direction=desc"
Format de Réponse Paginée
{
"total": 150,
"items": [
{
"uuid": "user-uuid-001",
"firstname": "Alice",
"lastname": "Dupont",
"email": "alice@example.com"
}
]
}
Le champ total indique le nombre total de ressources correspondantes, toutes pages confondues. Utilisez-le pour calculer le nombre de pages : pages = ceil(total / limit).
1.3.2 Headers HTTP Communs
| Header | Valeur | Obligatoire | Description |
|---|---|---|---|
Accept |
application/json |
Oui | Indique que le client attend du JSON |
Content-Type |
application/json |
Oui (POST/PUT) | Type du corps de la requête |
X-Auth-Token |
{token_string} |
Oui | Token d’authentification |
Wazo-Tenant |
{tenant_uuid} |
Conditionnel | UUID du tenant (obligatoire si multi-tenant) |
1.3.3 Codes HTTP et Gestion des Erreurs
Wazo utilise les codes HTTP standard. Voici les codes les plus fréquents :
| Code | Signification | Cause Commune | Détail |
|---|---|---|---|
| 200 | OK | Requête GET/PUT réussie | Corps de réponse présent |
| 201 | Created | Ressource créée avec POST | Corps avec la nouvelle ressource |
| 204 | No Content | DELETE ou PUT réussie sans retour | Pas de corps de réponse |
| 400 | Bad Request | JSON invalide, paramètre manquant | Voir details dans la réponse |
| 401 | Unauthorized | Token manquant ou expiré | Token non valide ou expiré |
| 403 | Forbidden | Token valide mais ACL insuffisante | Permissions insuffisantes |
| 404 | Not Found | Ressource inexistante ou endpoint invalide | UUID incorrect ou permission denied |
| 409 | Conflict | Ressource déjà existante | Doublon sur champ unique |
| 415 | Unsupported Media Type | Header Content-Type manquant |
POST/PUT sans JSON |
| 422 | Unprocessable Entity | Données syntaxiquement correctes mais sémantiquement invalides | Contrainte métier non respectée |
| 500 | Internal Server Error | Erreur interne Wazo | Erreur côté serveur |
Format Standard des Réponses d’Erreur
{
"error": "Bad Request",
"details": "Missing required field: 'firstname'",
"timestamp": "2026-03-07T15:30:00.123456Z",
"resource": "users"
}
Classe Exception Python (WazoAPIError)
Si vous utilisez le SDK Python wazo-confd-client, les erreurs sont levées sous forme d’exception :
from wazo_confd_client import Client
from wazo_confd_client.error import WazoAPIError
client = Client('wazo.example.com', username='admin', password='pass')
try:
user = client.users.create({'firstname': 'Alice'})
except WazoAPIError as e:
print(f"Status: {e.status_code}") # 400
print(f"Error: {e.message}") # Bad Request
print(f"Details: {e.details}") # Missing required field: 'firstname'
1.3.4 Conventions de Nommage des Endpoints
Wazo suit les conventions RESTful :
- Collection :
/users— GET (liste), POST (création) - Ressource individuelle :
/users/{uuid}— GET, PUT, DELETE - Sous-ressource (association) :
/users/{uuid}/lines/{line_id}— PUT, DELETE - Action spécifique :
/users/{uuid}/lines/{line_id}/update— POST
Ressources Imbriquées Courantes
# Ligne liée à un utilisateur
/users/{user_uuid}/lines/{line_id}
# Extension liée à une ligne
/lines/{line_id}/extensions/{extension_id}
# Endpoint SIP lié à une ligne
/lines/{line_id}/endpoints/sip/{endpoint_uuid}
# Extension liée à un groupe
/groups/{group_uuid}/extensions/{extension_id}
1.4 Modèle de Données Relationnel
Wazo est un système fortement relationnel. Comprendre les relations entre objets est crucial pour l’intégration.
1.4.1 Schéma de Relations Fondamental
┌─────────────────────────────────────────────────────────────────────────────┐
│ SCHÉMA RELATIONNEL WAZO CORE │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────────┐
│ CONTEXT │
│ (default, │
│ from-extern) │
└──────┬───────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ EXTENSION │ │ EXTENSION │ │ EXTENSION │
│ (numéro) │ │ (numéro) │ │ (numéro) │
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │
└──────────┬──────────┘ │
│ │
▼ │
┌────────────────┐ │
│ LINE │◄────────────────────────┘
│ (protocol) │
└───────┬───────┘
│
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ ENDPOINT │ │ USER │ │ DEVICE │
│ (SIP) │ │ (agent) │ │ (phone) │
└───────────┘ └───────────┘ └───────────┘
1.4.2 Règles d’Association
| Association | Régle | Exemple |
|---|---|---|
| Line → Extension | 1:1 ou 1:0 (optionnelle) | Une ligne peut avoir 0 ou 1 extension |
| Line → Endpoint SIP | 1:1 | Une ligne doit être liée à exactement 1 endpoint |
| Line → User | 1:N | Un utilisateur peut avoir plusieurs lignes |
| Extension → Destination | N:1 | Plusieurs extensions peuvent pointer vers un même IVR, Queue, Group |
| User → Voicemail | 1:0 ou 1:1 | Un utilisateur peut avoir 0 ou 1 boite vocale |
| Device → Line | N:M | Un téléphone peut être associé à plusieurs lignes |
Attention critique : Une ligne doit être liée à un endpoint SIP pour fonctionner. Sans endpoint, la ligne n’a pas de configuration technique et le téléphone ne pourra pas s’enregistrer. De même, sans extension, la ligne n’est pas joignable depuis l’extérieur.