WaterMeter AI

API OCR de compteur d’eau

API OCR de compteur d’eau. Cette page documente l'API HTTP publique exposée par le backend du site pour les intégrations tierces.

Commencer avec un vrai téléversement

Créez un compte, téléversez votre propre photo de compteur d’eau dans l’espace de travail, puis créez une clé API quand vous êtes prêt à intégrer.

Vue d'ensemble

  • Utilisez le backend du site pour toutes les intégrations externes.
  • N'appelez pas waterMeterAi directement depuis des programmes tiers.
  • L'API ouverte partage les mêmes utilisateurs, quotas, caches, tâches et règles d'audit que le portail web.
  • Le backend peut cibler différents services d'IA en aval selon la configuration de déploiement.
  • Les réponses de tâche incluent maintenant un objet générique result_summary pour afficher différents types de résultats.

Authentification

  • Connectez-vous sur le site et créez une clé API sur la page API Keys.
  • La clé API complète n'est affichée qu'une seule fois lors de sa création.
  • Envoyez la clé dans l'en-tête Authorization à chaque requête.
Authorization: Bearer wm_xxxxxxxxxxxxxxxxx

API Key Permissions and Limits

  • Each API key can have independent scopes, an IPv4/IPv6/CIDR allowlist, a total requests-per-minute limit, and a task submissions-per-minute limit.
  • A valid key without the required scope or outside its source IP allowlist returns 403.
  • Every valid-key request consumes the total request limit, including requests rejected by scope, IP, or submission policy.
  • Batch requests consume one total request unit and one submission unit per uploaded file.
  • Rate-limited responses return 429 with Retry-After and both X-RateLimit-* and X-SubmissionLimit-* headers.
  • Task creation also has a per-key concurrency limit and returns X-ConcurrencyLimit-* headers; a concurrency rejection uses 429.
  • For batch concurrency, only files that pass image validation reserve slots, and success headers report the actual active slots after task binding.
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1785902400
X-SubmissionLimit-Limit: 10
X-SubmissionLimit-Remaining: 9
X-ConcurrencyLimit-Limit: 3
X-ConcurrencyLimit-Active: 1
X-ConcurrencyLimit-Remaining: 2

Règles d'envoi

  • Taille maximale : 20 Mo par image.
  • Formats pris en charge : JPEG, PNG, WEBP.
  • Le backend valide le contenu réel du fichier, pas seulement son extension.

Application de la taille de téléchargement

  • Les téléchargements par lots acceptent jusqu'à 8 images par défaut, avec une limite de 20 Mo par image et une limite totale de contenu de fichier de 20 Mo.
  • Un fichier ou un lot qui dépasse sa limite renvoie 413 avant validation de l'image ou création de tâche ; aucun lot partiel n'est créé.
  • Le backend applique le nombre réel d'octets reçus même lorsque Content-Length est manquant ou qu'un transfert fragmenté est utilisé.

États des tâches

  • queued : acceptée et en attente de traitement par l'IA.
  • running : en cours de traitement, ou déjà remise au répartiteur pendant l'attente du résultat final.
  • batch_waiting_ai : tous les éléments du lot attendent encore le retour du service d'IA.
  • batch_running : le lot a déjà été envoyé au répartiteur et continue d'être traité.
  • done : terminé avec succès.
  • failed : le traitement a échoué.
  • waiting_ai : mise en file jusqu'au retour du service d'IA, puis reprise automatique.

Sources de résultat

  • fresh : généré par une nouvelle exécution d'IA.
  • cached_exact : correspond au cache de la version IA actuelle.
  • cached_stale : IA hors ligne, dernier résultat en cache renvoyé.
  • pending : aucun résultat final pour l'instant.
  • failed : la tâche a échoué.
  • Quand la tâche n'est pas terminée, consultez error_message pour connaître la dernière raison d'attente ou de nouvelle tentative.

Quota et facturation

  • Utilisez `GET /api/open/quota` avant d’envoyer de gros volumes si votre intégration doit éviter les échecs liés au quota.
  • Seules les exécutions AI `fresh` consomment du quota.
  • Les résultats `cached_exact`, `cached_stale`, `pending` et `failed` ne consomment pas de quota.
  • Les comptes gratuits utilisent d’abord le quota quotidien. Les comptes payants utilisent les forfaits de quota périodiques actifs, puis le quota temporaire ou fixe selon la politique du backend.
  • Lorsque le quota est épuisé, la soumission de tâche renvoie `429` avec un message d’erreur au lieu de créer une nouvelle tâche.

Cache et fraîcheur des résultats

  • Le backend met en cache les résultats réussis par hash d’image et version AI, avec l’espace de noms du service aval.
  • `cached_exact` signifie que la même image possède déjà un résultat réussi pour la version AI actuelle, donc aucune nouvelle exécution AI n’a été nécessaire.
  • `cached_stale` signifie que le service AI est hors ligne et que le backend a renvoyé le dernier résultat historique disponible.
  • Quand `is_latest_ai_version` vaut false, conservez le résultat comme donnée historique utilisable mais à vérifier.
  • Ne supposez pas que chaque tâche `done` a consommé du quota ; vérifiez `result_source`.

Task completion webhooks

  • Send signed task completion events to your HTTPS endpoint with automatic retries.
  • This API key is inactive. Existing records remain available, but new, enabled, test, and secret-rotation operations are blocked.
X-WaterMeter-Webhook-Id: whev_new_event
X-WaterMeter-Webhook-Replay-Of: whev_original_event
replay_of_event_id: whev_original_event
blocked endpoint management: HTTP 409
canceled delivery status: canceled

GET/api/open/quota

Lisez le quota actuel et l’utilisation restante.

Exemple de requête
curl -X GET "https://watermeterai.com/api/open/quota" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
Exemple de réponse
{
  "ok": true,
  "email": "[email protected]",
  "quota": {
    "account_type": "free",
    "daily_limit": 20,
    "used": 3,
    "remaining": 17,
    "day_tag": "2026-06-01",
    "is_unlimited": false,
    "monthly_remaining": 0,
    "monthly_bonus_remaining": 0,
    "fixed_remaining": 0,
    "nearest_expire_at": null,
    "quota_summary_text": "Free daily quota: 3/20 used today. Remaining: 17."
  }
}

GET/api/open/ai-status

Lisez le statut du service public pour la soumission des tâches et le remplacement des résultats mis en cache.

Exemple de requête
curl -X GET "https://watermeterai.com/api/open/ai-status" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
Exemple de réponse
{
  "ok": true,
  "is_online": true,
  "busy": false,
  "active_jobs": 0,
  "public_status": "online",
  "public_status_label": "online",
  "public_status_reason": "ready",
  "accepts_new_tasks": true,
  "can_return_cached_result": true,
  "queue_state": "idle",
  "queue_count": 0,
  "current_ai_version": "water_v2:wm-ai-v2-2026-06-01",
  "last_checked_at": "2026-06-01T06:15:30Z"
}

POST/api/open/tasks

Téléchargez une image et créez une seule tâche.

Exemple de requête
curl -X POST "https://watermeterai.com/api/open/tasks" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx" \
  -F "file=@D:\data\meter_001.jpg"
Exemple de réponse
{
  "ok": true,
  "task_id": "8e6c4d1f8f8348c0bc53e2e39d2dc111",
  "status": "queued",
  "result_source": "pending",
  "visibility": "private",
  "ai_online": true,
  "is_latest_ai_version": false,
  "final_reading": "-",
  "result_summary": {
    "resultKind": "unknown",
    "primaryLabel": "Result",
    "primaryValue": "-",
    "secondaryLabel": "Detail",
    "secondaryValue": "-",
    "summaryText": "No result is available yet."
  },
  "error_message": "",
  "created_at": "2026-06-01T06:16:10Z"
}

GET/api/open/tasks/{task_id}

Lisez l’état d’une tâche et la lecture finale.

Exemple de requête
curl -X GET "https://watermeterai.com/api/open/tasks/task_a" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
Exemple de réponse
{
  "ok": true,
  "task_id": "8e6c4d1f8f8348c0bc53e2e39d2dc111",
  "status": "done",
  "result_source": "fresh",
  "ai_online": true,
  "is_latest_ai_version": true,
  "final_reading": "123.45",
  "meter_type": "pointer",
  "success": "yes",
  "result_summary": {
    "resultKind": "water_meter",
    "primaryLabel": "Final Reading",
    "primaryValue": "123.45",
    "secondaryLabel": "Meter Type",
    "secondaryValue": "pointer",
    "summaryText": "Water meter recognition finished."
  },
  "error_message": "",
  "created_at": "2026-06-01T06:16:10Z"
}

GET/api/open/tasks

Lire les tâches récentes appartenant à l'utilisateur clé API actuel.

Exemple de requête
curl -X GET "https://watermeterai.com/api/open/tasks?limit=20" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
Exemple de réponse
{
  "ok": true,
  "items": [
    {
      "task_id": "8e6c4d1f8f8348c0bc53e2e39d2dc111",
      "status": "done",
      "result_source": "cached_exact",
      "final_reading": "123.45",
      "meter_type": "pointer",
      "success": "yes",
      "result_summary": {},
      "ai_online": true,
      "is_latest_ai_version": true,
      "created_at": "2026-06-01T06:16:10Z",
      "error_message": ""
    }
  ]
}

POST/api/open/batches

Téléchargez plusieurs images en une seule demande.

Exemple de requête
curl -X POST "https://watermeterai.com/api/open/batches" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx" \
  -F "files=@D:\data\meter_001.jpg" \
  -F "files=@D:\data\meter_002.jpg"
Exemple de réponse
{
  "ok": true,
  "batch_id": "5a14f4e5f6d34fdabce00e62c0dd0001",
  "status": "batch_running",
  "total_count": 2,
  "done_count": 0,
  "failed_count": 0,
  "pending_count": 2,
  "items": [
    {
      "index": 0,
      "file_name": "meter_001.jpg",
      "task_id": "task_a",
      "status": "queued",
      "result_source": "pending",
      "final_reading": "-",
      "failure_kind": "",
      "error_message": ""
    },
    {
      "index": 1,
      "file_name": "meter_002.jpg",
      "task_id": "task_b",
      "status": "queued",
      "result_source": "pending",
      "final_reading": "-",
      "failure_kind": "",
      "error_message": ""
    }
  ]
}

GET/api/open/batches/{batch_id}

Lisez la progression du lot et les états des tâches par fichier.

Exemple de requête
curl -X GET "https://watermeterai.com/api/open/batches/5a14f4e5f6d34fdabce00e62c0dd0001" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
Exemple de réponse
{
  "ok": true,
  "batch_id": "5a14f4e5f6d34fdabce00e62c0dd0001",
  "status": "batch_done",
  "total_count": 2,
  "done_count": 2,
  "failed_count": 0,
  "pending_count": 0,
  "items": [
    {
      "index": 0,
      "file_name": "meter_001.jpg",
      "task_id": "task_a",
      "status": "done",
      "result_source": "fresh",
      "final_reading": "123.45",
      "failure_kind": "",
      "error_message": ""
    },
    {
      "index": 1,
      "file_name": "meter_002.jpg",
      "task_id": "task_b",
      "status": "done",
      "result_source": "cached_exact",
      "final_reading": "456.78",
      "failure_kind": "",
      "error_message": ""
    }
  ]
}

Flux recommandé

  • Vérifiez `GET /api/open/ai-status` avant d'envoyer de gros volumes.
  • Enregistrez `task_id` ou `batch_id` dans votre propre système juste après l'envoi.
  • Traitez `queued`, `running`, `waiting_ai`, `batch_waiting_ai` et `batch_running` comme des états non finaux et continuez à interroger.
  • Utilisez les requêtes par lot quand le chemin réseau vers le backend a une forte latence et que le service déployé supporte le mode batch.
  • Les requêtes batch passent actuellement par `webBackend -> dispatchCenter -> waterMeterAi`.
  • `batch_waiting_ai` signifie que le lot attend encore le service d'IA, sans exécution active pour l'instant.
  • Quand le service déployé est `CAD`, utilisez pour l'instant `POST /api/open/tasks` et considérez le batch comme indisponible.

Notes d'erreur

  • 400 : demande non valide ou l'entreprise déployée ne prend pas en charge le téléchargement par lots.
  • 401 : clé API manquante, invalide, expirée ou désactivée.
  • 403: the user account is not active, the key lacks the required scope, or the source IP is outside the key allowlist.
  • 404 : tâche ou lot introuvable ou n'appartenant pas à l'utilisateur actuel.
  • 413 : fichier trop volumineux.
  • 415 : type d'image non pris en charge ou contenu d'image non valide.
  • 429: quota exhausted or the API key request, submission, or concurrency limit was exceeded.
Téléchargement de 400 lots indisponible
{
  "detail": "batch upload is not supported for business: cax"
}
401 clé API manquante ou invalide
{
  "ok": false,
  "error": "unauthorized",
  "message": "Missing or invalid API key."
}
Fichier 413 trop volumineux
{
  "ok": false,
  "error": "file_too_large",
  "message": "Maximum file size is 20MB."
}
Quota 429 épuisé
{
  "ok": false,
  "error": "quota_exhausted",
  "message": "Quota exhausted.",
  "quota": {
    "remaining": 0,
    "quota_summary_text": "Free daily quota: 20/20 used today. Remaining: 0."
  }
}

Prêt à tester le flux ?

Utilisez l’espace de travail web pour la première photo, puis passez aux clés API lorsque le format du résultat convient à votre système.