API Agents¶
Endpoints REST dédiés à l'application agents, localisés dans /api/agents/.
Authentification¶
Le pairing QR remplace l'authentification par email/mot de passe. Le token de pairing est généré dans le backoffice admin (via pairing_generate.php) et scanné par l'application mobile.
POST /api/agents/auth/pair.php¶
Authentifie un agent en utilisant un token de pairing QR et retourne les tokens JWT.
{
"success": true,
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "dGhpcyBpcyBhIHJlZnJl...",
"expires_in": 3600,
"agent": {
"id": 1,
"email": "agent@collectivite.test",
"nom": "Dupont",
"prenom": "Jean",
"collectivite_id": 1,
"collectivite_name": "Ville de Nice",
"collectivite_type": "MAIRIE",
"role": "agent",
"code_insee": "06088",
"mairie_latitude": 43.7009,
"mairie_longitude": 7.2683
}
}
}
POST /api/agents/auth/refresh.php¶
Renouvelle les tokens avec le refresh token.
POST /api/agents/auth/logout.php¶
Invalide le refresh token côté serveur.
Header requis
Authorization: Bearer {access_token}
Incidents¶
Authentification
Tous les endpoints incidents requièrent le header Authorization: Bearer {access_token}.
GET /api/agents/incidents/list.php¶
Liste les incidents de la collectivité avec filtres optionnels.
Paramètres query :
| Paramètre | Type | Description |
|---|---|---|
status |
string | Filtrer par statut (NEW, ASSIGNED, IN_PROGRESS, RESOLVED, CLOSED) |
priority |
string | Filtrer par priorité (LOW, NORMAL, HIGH, URGENT) |
search |
string | Recherche textuelle (adresse, description) |
page |
int | Page (défaut: 1) |
limit |
int | Limite par page (défaut: 20, max: 100) |
{
"success": true,
"incidents": [
{
"id": 123,
"type_id": 1,
"type_name": "Voirie",
"type_color": "#ef4444",
"adresse": "12 Rue de la Paix, 06000 Nice",
"latitude": 43.7102,
"longitude": 7.2620,
"description": "Nid-de-poule dangereux",
"status": "NEW",
"priority": "HIGH",
"assigned_agent_id": null,
"assigned_agent_name": null,
"photo_count": 2,
"comment_count": 0,
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 45,
"total_pages": 3
}
}
GET /api/agents/incidents/detail.php¶
Détail complet d'un incident avec photos et commentaires.
Paramètres query :
| Paramètre | Type | Requis | Description |
|---|---|---|---|
id |
int | Oui | ID de l'incident |
{
"success": true,
"incident": {
"id": 123,
"type_id": 1,
"type_name": "Voirie",
"type_color": "#ef4444",
"adresse": "12 Rue de la Paix, 06000 Nice",
"latitude": 43.7102,
"longitude": 7.2620,
"description": "Nid-de-poule dangereux sur la chaussée",
"status": "IN_PROGRESS",
"priority": "HIGH",
"assigned_agent_id": 5,
"assigned_agent_name": "Marie Martin",
"assigned_agents": [
{ "id": 5, "nom": "Martin", "prenom": "Marie", "is_referent": true },
{ "id": 8, "nom": "Petit", "prenom": "Luc", "is_referent": false }
],
"attente_motif_nom": null,
"attente_note": null,
"attente_started_at": null,
"attente_contact_nom": null,
"attente_contact_telephone": null,
"attente_contact_telephone_urgence": null,
"declarant_device_id": "abc123...",
"declarant_email": null,
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-16T14:20:00Z"
},
"photos": [
{
"id": 456,
"type": "DECLARANT",
"url": "/uploads/incidents/123_1.jpg",
"latitude": 43.7102,
"longitude": 7.2620,
"created_at": "2026-01-15T10:30:00Z"
},
{
"id": 789,
"type": "INTERVENTION",
"agent_id": 5,
"agent_name": "Marie Martin",
"url": "/uploads/incidents/123_intervention_1.jpg",
"latitude": 43.7103,
"longitude": 7.2621,
"created_at": "2026-01-16T14:20:00Z"
}
],
"comments": [
{
"id": 101,
"agent_id": 5,
"agent_name": "Marie Martin",
"content": "Intervention prévue demain matin.",
"is_internal": false,
"created_at": "2026-01-16T09:00:00Z"
}
]
}
Équipe assignée (assigned_agents)
Modèle many-to-many (incident_agents : incident_id, agent_id, is_referent) remplaçant l'ancien assigné unique. assigned_agent_id/assigned_agent_name restent renvoyés (premier agent de assigned_agents, ou colonne legacy incidents.assigned_agent_id en fallback) pour compatibilité clients existants.
POST /api/agents/incidents/update_status.php¶
Met à jour le statut et/ou la priorité d'un incident. Le passage au statut ATTENTE requiert motif_id.
Historique
Sortir du statut ATTENTE (quel que soit le nouveau statut) clôture la période ouverte dans incident_wait_periods, fusionnée avec le reste de l'historique dans l'affichage de l'incident.
GET /api/agents/incidents/motifs_attente.php¶
Liste les motifs de mise en attente actifs de la mairie de l'incident (configurables par mairie).
Paramètres query : incident_id (int, requis)
POST /api/agents/incidents/update_priority.php¶
Met à jour la priorité d'un incident. Rejeté (403) si mairies.priorite_agents_autorise = 0 pour la mairie de l'incident — revalidé côté serveur indépendamment de l'état affiché côté client.
POST /api/agents/incidents/add_comment.php¶
Ajoute un commentaire à un incident.
Commentaires internes
Les commentaires avec is_internal: true ne sont visibles que par les agents, pas par les citoyens.
POST /api/agents/incidents/add_photo.php¶
Ajoute une photo d'intervention à un incident.
Contacts (intervenants)¶
GET /api/agents/intervenants/list.php¶
Liste les intervenants actifs (carnet de contacts). Sans incident_id : intervenants de la mairie de l'agent (ou de toutes les mairies de sa collectivité si EPCI) — utilisé par l'onglet "Contacts". Avec incident_id : intervenants de la mairie de cet incident — utilisé par le sélecteur du dialogue ATTENTE.
Paramètres query :
| Paramètre | Type | Description |
|---|---|---|
incident_id |
int | Optionnel — restreint à la mairie de cet incident |
Statistiques¶
GET /api/agents/stats/dashboard.php¶
Statistiques du tableau de bord pour la collectivité.
{
"success": true,
"stats": {
"total": 150,
"by_status": {
"NEW": 25,
"ASSIGNED": 30,
"IN_PROGRESS": 45,
"RESOLVED": 40,
"CLOSED": 10
},
"assigned_to_me": 12,
"resolved_today": 5,
"resolved_this_week": 28
},
"recent_incidents": [
{
"id": 123,
"type_name": "Voirie",
"adresse": "12 Rue de la Paix",
"status": "NEW",
"priority": "HIGH",
"created_at": "2026-01-18T08:00:00Z"
}
]
}
Codes d'erreur¶
| Code | Signification |
|---|---|
| 200 | Succès |
| 400 | Requête invalide (paramètres manquants) |
| 401 | Non authentifié (token invalide/expiré) |
| 403 | Non autorisé (accès refusé) |
| 404 | Ressource non trouvée |
| 500 | Erreur serveur |
Sécurité¶
- TLS 1.3 obligatoire
- JWT avec expiration courte (1h access, 7j refresh)
- Rate limiting : 100 requêtes/minute par agent
- Validation de toutes les entrées
- Logs sans données sensibles