水表 OCR API
水表 OCR API. 本页说明网站后端对外开放的 HTTP API,供第三方系统接入。
先从真实上传开始
先注册账号,在工作台上传你自己的水表照片;确认结果格式适合后,再创建 API Key 接入系统。
总览
- 所有外部集成都应调用网站后端。
- 第三方程序不要直接调用 waterMeterAi。
- 开放 API 与网站共用用户、额度、缓存、任务和审计规则。
- 后端可根据部署配置切换不同下游 AI 业务。
- 任务返回中已包含通用 result_summary,便于不同业务展示不同结果类型。
鉴权
- 先登录网站,然后在 API 密钥页创建 API key。
- 完整 API key 只会在创建时显示一次。
- 每个请求都要在 Authorization 头中带上该 key。
Authorization: Bearer wm_xxxxxxxxxxxxxxxxx
API Key 权限与限制
- 每个 API Key 可独立配置 Scope、IPv4/IPv6/CIDR 白名单、总请求分钟限额和任务提交分钟限额。
- 有效 Key 缺少目标 Scope,或来源 IP 不在白名单时返回 403。
- 每个已通过 Key 鉴权的请求都会计入总请求限额,包括被 Scope、IP 或提交策略拒绝的请求。
- 批量请求按一次总请求计算,并按上传文件数累计提交单位。
- 触发限速时返回 429、Retry-After,以及 X-RateLimit-* 和 X-SubmissionLimit-* 两组响应头。
- 任务创建还受单 Key 并发上限约束,并返回 X-ConcurrencyLimit-* 响应头;并发不足时返回 429。
- 批量并发只为通过图片校验的文件预留槽位,成功响应头反映任务绑定后的实际活动槽。
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
上传规则
- 单张图片最大 20MB。
- 支持格式:JPEG、PNG、WEBP。
- 后端会校验真实文件内容,而不是只看扩展名。
上传大小限制
- 批量上传默认最多接收 8 张图片,单张上限为 20MB,全部文件内容合计上限为 20MB。
- 单个文件或整批超过限制时,后端会在图片校验或创建任务之前返回 413,且不会创建部分批次。
- 即使请求缺少 Content-Length 或使用分块传输,后端仍会按实际接收的字节数执行限制。
任务状态
- queued:已接收,等待 AI 处理。
- running:AI 正在处理,或已交给收发室但仍在轮询最终结果。
- 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` 和错误信息,不会创建新任务。
缓存与结果新鲜度
- 后端按图片 hash 和 AI 版本缓存成功结果,并包含下游业务命名空间。
- `cached_exact` 表示同一图片在当前 AI 版本下已有成功结果,因此不需要再次运行 AI。
- `cached_stale` 表示 AI 服务离线,后端返回了当前可用的最新历史结果。
- 当 `is_latest_ai_version` 为 false 时,应把结果当作可用但需要复核的历史数据保存。
- 不要假设每个 `done` 任务都消耗了额度;应检查 `result_source`。
任务完成 Webhook
- 任务完成后向你的 HTTPS 地址发送签名事件,并在失败时自动重试。
- 此 API Key 已失效。仍可查看记录或停用、删除端点,但不能新建、启用、测试或轮换签名密钥。
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
/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
/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
/api/open/tasks上传一张图片并创建单任务。
请求示例
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}
/api/open/tasks/{task_id}读取单个任务状态和最终读数。
请求示例
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/open/tasks读取当前 API Key 用户名下的最近任务。
请求示例
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
/api/open/batches一次请求上传多张图片。
请求示例
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}
/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 key 缺失、无效、过期或被禁用。
- 403:用户账户不可用、Key 缺少目标 Scope,或来源 IP 不在 Key 白名单中。
- 404:任务或批次不存在,或不属于当前用户。
- 413:文件过大。
- 415:图片类型不支持或图片内容无效。
- 429:额度已用完,或 API Key 的请求、提交、并发任务上限已触发。
400:批量上传不可用
{
"detail": "batch upload is not supported for business: cax"
}401:API key 缺失或无效
{
"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."
}
}准备测试完整流程?
先用网页工作台跑第一张图片,确认读数和结果结构后,再进入 API Key 接入。