Aller au contenu

API REST

⬇️ Télécharger cette page en Markdown


Endpoints Publics

Base URL : https://urbafix.fr/api/

Format : JSON

Authentification : Headers X-Fingerprint (device ID) et X-API-Key (optionnel)


GET /get_types.php

Description

Récupère la liste des types d'incidents pour un code postal.

Paramètres

Nom Type Requis Description
code_postal string Oui Code postal (5 chiffres)

Exemple Requête

curl "https://urbafix.fr/api/get_types.php?code_postal=06500"

Réponse Succès

{
  "success": true,
  "types": [
    {
      "id": 1,
      "nom": "Nid-de-poule",
      "description": "Chaussée dégradée",
      "couleur": "#e74c3c",
      "ordre": 1,
      "actif": true,
      "contacts": [
        {"nom": "Service Voirie", "email": "voirie@mairie.test"}
      ]
    }
  ]
}

GET /get_incidents.php

Description

Liste les incidents pour un code postal avec filtres optionnels.

Paramètres

Nom Type Requis Description
code_postal string Oui Code postal (5 chiffres)
statut string Non nouveau, en_cours, resolu, ferme
type_id int Non Filtre par type
limit int Non Limite résultats (défaut: 100)

Exemple Requête

curl "https://urbafix.fr/api/get_incidents.php?code_postal=06500&statut=nouveau"

Réponse Succès

{
  "success": true,
  "incidents": [
    {
      "id": 123,
      "type_id": 1,
      "type_nom": "Nid-de-poule",
      "type_couleur": "#e74c3c",
      "adresse": "123 Rue Example",
      "latitude": 43.7750,
      "longitude": 7.5030,
      "description": "Gros trou dans la chaussée",
      "statut": "nouveau",
      "date_creation": "2026-01-04 10:30:00",
      "group_id": 5,
      "photos": [
        {"id": 1, "url": "https://urbafix.fr/uploads/incidents/photo1.jpg"}
      ]
    }
  ]
}

POST /submit_incident.php

Description

Création d'un nouvel incident avec photos/vidéos.

Headers

Content-Type: application/json
X-Fingerprint: device_unique_id
X-API-Key: optional_api_key

Body JSON

{
  "mairie_id": 1,
  "type_id": 1,
  "adresse": "123 Rue Example",
  "latitude": 43.7750,
  "longitude": 7.5030,
  "description": "Description du problème",
  "device_id": "android_abc123",
  "photos": [
    "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
  ],
  "videos": [
    {
      "video": "data:video/mp4;base64,AAAAHGZ0eXBpc29t...",
      "latitude": 43.7750,
      "longitude": 7.5030
    }
  ]
}

Réponse Succès

{
  "success": true,
  "incident_id": 123,
  "photos_uploaded": 1,
  "videos_uploaded": 1,
  "gps_warnings": [
    "Vidéo 0: GPS distant de 150m de l'incident"
  ]
}

Codes d'Erreur

Code Signification
400 Paramètres invalides
401 Authentification requise
413 Fichier trop volumineux
500 Erreur serveur

GET /get_user_incidents.php

Description

Récupère les incidents créés par un device ID.

Paramètres

Nom Type Requis Description
code_postal string Oui Code postal
device_id string Oui Device fingerprint

Exemple Requête

curl "https://urbafix.fr/api/get_user_incidents.php?code_postal=06500&device_id=android_abc123"

Authentification

Device Fingerprint

Header X-Fingerprint généré côté mobile :

// Android
val fingerprint = "${Build.MODEL}_${Build.ID}_${UUID.randomUUID()}"

API Key (Optionnel)

Header X-API-Key pour applications tierces.

Génération :

openssl rand -hex 32

Configuration : Stocké dans table api_keys


Rate Limiting

Implémenté par SecurityHelpers::checkRateLimit() (compteur APCu, par endpoint). Défaut 100 req/min si un endpoint n'appelle pas la fonction avec des valeurs explicites ; la plupart des endpoints d'écriture sont bien plus stricts :

Limite Endpoints (exemples)
5 / heure send_registration_email.php, submit_demande_collectivite.php, submit_interest.php
10 / heure check_mairie_registration.php, confirm_registration.php, submit_alerte.php, submit_feedback.php, submit_waitlist.php
20 / heure verify_registration_token.php
50 / heure submit_incident.php
10 / 5 min admin_login.php
20–200 / min Endpoints de lecture (get_*.php) et add_photos.php/delete_incident.php/register_push_endpoint.php

Identifiant : SecurityHelpers::getRateLimitIdentifier() — IP réelle du client (dernier maillon de X-Forwarded-For ajouté par le reverse proxy, jamais falsifiable par le client), combinée au header X-Fingerprint quand présent. Voir Conformité ANSSI §18.

Dépassement : HTTP 429, header Retry-After: <secondes>, body {"success":false,"error":"Too Many Requests","message":"..."}. Pas de headers X-RateLimit-*.

Si APCu indisponible : la fonction autorise la requête par défaut (error_log de l'incident) plutôt que de bloquer tout le trafic.


CORS

Géré par SecurityHelpers::setCorsHeaders() — whitelist codée en dur (pas de variable d'environnement CORS_ALLOWED_ORIGINS) :

$origins = [
    'https://urbafix.fr',
    'https://www.urbafix.fr',
    'android://org.urbanappslab.urbafix',
    'capacitor://localhost',
];
// + localhost:3000/8080 si APP_ENV !== 'production'

Headers envoyés :

Access-Control-Allow-Origin: <origine si whitelistée, sinon absent>
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, X-Fingerprint, X-API-Key, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 3600

Origine non whitelistée → pas de Access-Control-Allow-Origin dans la réponse (le navigateur bloque côté client, la requête serveur s'exécute quand même : ce n'est pas un contrôle d'accès, seulement une protection navigateur).


Exemples cURL

Création Incident Simple

curl -X POST https://urbafix.fr/api/submit_incident.php \
  -H "Content-Type: application/json" \
  -H "X-Fingerprint: test-device-123" \
  -d '{
    "mairie_id": 1,
    "type_id": 1,
    "adresse": "123 Rue Test",
    "latitude": 43.7750,
    "longitude": 7.5030,
    "description": "Test incident",
    "device_id": "test-device-123"
  }'

Récupération Types

curl "https://urbafix.fr/api/get_types.php?code_postal=06500" | jq

GET+POST /api/admin/email_test_mode.php

Description

Lit ou modifie le mode d'envoi des emails (test vs production). Protégé par session admin (requireAuth()).

GET — Lire le mode actuel

curl "https://urbafix.fr/api/admin/email_test_mode.php" \
  -b "PHPSESSID=..."

Réponse

{ "success": true, "email_test_mode": true }
Valeur Signification
true Mode TEST — emails redirigés vers l'adresse de test
false Mode PROD — emails envoyés à la mairie réelle

POST — Modifier le mode

curl -X POST "https://urbafix.fr/api/admin/email_test_mode.php" \
  -H "Content-Type: application/json" \
  -b "PHPSESSID=..." \
  -d '{"enabled": false}'

Body JSON

Champ Type Description
enabled boolean true = activer mode test, false = activer mode production

Réponse

{ "success": true, "email_test_mode": false }

Stockage

Persisté dans la table app_settings :

SELECT value FROM app_settings WHERE `key` = 'email_test_mode';
-- '1' = test, '0' = production

Utilisation Android

Appelé par ProfileViewModel (build DEBUG uniquement) via MonQuartierApi.getEmailTestMode() et setEmailTestMode().


Format d'Erreur Standard

{
  "success": false,
  "error": "Message d'erreur lisible",
  "code": "ERROR_CODE",
  "details": {
    "field": "Description spécifique"
  }
}

Versioning

Version actuelle : v1

Future : API v2 (GraphQL) en Q4 2026

Rétrocompatibilité : v1 maintenue 2 ans après sortie v2