WaterMeter AI

水道メーターOCR API

水道メーターOCR API. このページでは、サードパーティ連携向けにサイトバックエンドが公開する HTTP API を説明します。

実際のアップロードから始める

まずアカウントを登録し、ワークスペースで自分の水道メーター写真をアップロードします。結果形式を確認してから、連携用のAPIキーを作成してください。

概要

  • 外部連携はすべてサイトバックエンドを使用してください。
  • サードパーティプログラムから waterMeterAi を直接呼び出さないでください。
  • Open API は、Web ポータルと同じユーザー、クォータ、キャッシュ、タスク、監査ルールを共有します。
  • バックエンドはデプロイ設定により、下流の異なる AI 業務へ振り分けできます。
  • タスク応答には汎用の result_summary オブジェクトが含まれ、業務ごとに異なる結果タイプを表示できます。

認証

  • サイトにサインインし、API キーページで API キーを作成します。
  • 完全な API キーは作成時に一度だけ表示されます。
  • すべてのリクエストで Authorization ヘッダーにキーを送信してください。
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

アップロードルール

  • 最大ファイルサイズ: 画像 1 枚あたり 20 MB。
  • サポート形式: JPEG, PNG, WEBP。
  • バックエンドは拡張子だけでなく、実際のファイル内容を検証します。

アップロードサイズの強制

  • バッチ アップロードでは、デフォルトで最大 8 つの画像を受け入れますが、画像ごとに 20 MB、ファイル コンテンツの合計に 20 MB の制限があります。
  • 制限を超えるファイルまたはバッチは、イメージ検証またはタスク作成の前に 413 を返します。部分的なバッチは作成されません。
  • バックエンドは、Content-Length が欠落している場合やチャンク転送が使用されている場合でも、実際に受信したバイト数を強制します。

タスク状態

  • queued: 受け付け済みで AI 処理待ち。
  • running: 現在処理中、またはディスパッチャーへ渡され最終結果をポーリング中。
  • batch_waiting_ai: バッチ内の全項目が AI サービスの復帰を待機中。
  • batch_running: バッチはすでにディスパッチャーへ渡され、まだ処理中。
  • done: 正常に完了。
  • failed: 処理に失敗。
  • waiting_ai: AI サービスがオンラインに戻るまでキューで待機し、その後自動再開。

結果の取得元

  • fresh: 新しい AI 実行で生成。
  • cached_exact: 現在の AI バージョンのキャッシュに一致。
  • cached_stale: AI オフラインのため、最新のキャッシュ結果を返却。
  • pending: 最終結果はまだありません。
  • failed: タスクが失敗しました。
  • タスクが未完了の場合は、error_message で最新の再試行または待機理由を確認してください。

クォータと課金

  • 大量のワークロード送信でクォータ不足を避けたい場合は、送信前に `GET /api/open/quota` を使用してください。
  • クォータを消費するのは `fresh` の AI 実行だけです。
  • `cached_exact`、`cached_stale`、`pending`、`failed` の結果はクォータを消費しません。
  • 無料アカウントは日次クォータを先に使用します。有料アカウントはバックエンドポリシーに従い、有効な周期クォータパッケージ、その後一時または固定クォータを使用します。
  • クォータが不足している場合、タスク送信は新しいタスクを作成せず、`429` とエラーメッセージを返します。

キャッシュと結果の鮮度

  • バックエンドは、画像ハッシュと AI バージョン、下流ビジネスの namespace を含めて成功結果をキャッシュします。
  • `cached_exact` は、同じ画像に現在の AI バージョンの成功結果が既にあり、新しい AI 実行が不要だったことを示します。
  • `cached_stale` は、AI サービスがオフラインで、バックエンドが利用可能な最新の履歴結果を返したことを示します。
  • `is_latest_ai_version` が false の場合、その結果は利用可能だが確認対象の履歴データとして保存してください。
  • すべての `done` タスクがクォータを消費したとは限りません。`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

現在のクォータと残りの使用量を読み取ります。

リクエスト例
curl -X GET "https://watermeterai.com/api/open/quota" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
レスポンス例
{
  "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

タスクの送信とキャッシュされた結果のフォールバックのパブリック サービス ステータスを読み取ります。

リクエスト例
curl -X GET "https://watermeterai.com/api/open/ai-status" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
レスポンス例
{
  "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

1 つの画像をアップロードし、1 つのタスクを作成します。

リクエスト例
curl -X POST "https://watermeterai.com/api/open/tasks" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx" \
  -F "file=@D:\data\meter_001.jpg"
レスポンス例
{
  "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}

1 つのタスクのステータスと最終読み取り値を読み取ります。

リクエスト例
curl -X GET "https://watermeterai.com/api/open/tasks/task_a" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
レスポンス例
{
  "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

現在の API キー ユーザーが所有する最近のタスクを読み取ります。

リクエスト例
curl -X GET "https://watermeterai.com/api/open/tasks?limit=20" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
レスポンス例
{
  "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

1 回のリクエストで複数の画像をアップロードします。

リクエスト例
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"
レスポンス例
{
  "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}

バッチの進行状況とファイルごとのタスクの状態を読み取ります。

リクエスト例
curl -X GET "https://watermeterai.com/api/open/batches/5a14f4e5f6d34fdabce00e62c0dd0001" \
  -H "Authorization: Bearer wm_xxxxxxxxxxxxxxxxx"
レスポンス例
{
  "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": ""
    }
  ]
}

推奨フロー

  • 大きなワークロードを送信する前に `GET /api/open/ai-status` を確認してください。
  • 送信直後に `task_id` または `batch_id` を自分のシステムへ保存してください。
  • `queued`、`running`、`waiting_ai`、`batch_waiting_ai`、`batch_running` は最終状態ではないため、ポーリングを続けてください。
  • バックエンドへのネットワーク経路のレイテンシが高く、デプロイ済み業務がバッチモードをサポートする場合は、バッチリクエストを使用してください。
  • バッチリクエストは現在 `webBackend -> dispatchCenter -> waterMeterAi` を経由します。
  • `batch_waiting_ai` は、各項目がまだ AI サービスを待機しており、能動的に実行中ではないことを意味します。
  • デプロイ済み業務が `CAD` の場合、当面は `POST /api/open/tasks` を使用し、バッチアップロードは利用不可として扱ってください。

エラー注記

  • 400: リクエストが無効であるか、デプロイされたビジネスがバッチ アップロードをサポートしていません。
  • 401: API キーが見つからない、無効、期限切れ、または無効になっています。
  • 403: the user account is not active, the key lacks the required scope, or the source IP is outside the key allowlist.
  • 404: タスクまたはバッチが見つからないか、現在のユーザーが所有していません。
  • 413: ファイルが大きすぎます。
  • 415: サポートされていない画像タイプまたは無効な画像コンテンツ。
  • 429: quota exhausted or the API key request, submission, or concurrency limit was exceeded.
400 バッチアップロードは利用できません
{
  "detail": "batch upload is not supported for business: cax"
}
401 API キーが見つからないか無効です
{
  "ok": false,
  "error": "unauthorized",
  "message": "Missing or invalid API key."
}
413 ファイルが大きすぎます
{
  "ok": false,
  "error": "file_too_large",
  "message": "Maximum file size is 20MB."
}
429 の割り当てがなくなりました
{
  "ok": false,
  "error": "quota_exhausted",
  "message": "Quota exhausted.",
  "quota": {
    "remaining": 0,
    "quota_summary_text": "Free daily quota: 20/20 used today. Remaining: 0."
  }
}

ワークフローを試しますか?

最初の写真は Web ワークスペースで試し、結果形式が合ったら API キーに進みます。