The async HTTP response is an acknowledgement only, delivering the actual reading via webhook. The sync HTTP response waits and delivers the reading immediately.
Every request produces two artefacts: a synchronous HTTP ack with a reference_id, and an asynchronous webhook delivery containing the reading. Your client correlates the two via that reference_id. See Webhooks for the payload format.
For the /api/meter-reading endpoint: Returned immediately when the request passes validation. The image has been queued — it has not been processed yet.
{"reference_id": "9c7d3f2a-1e4b-4d5a-9b6c-1f2e3d4c5b6a","status": "pending","createdAt": "2026-04-28T14:32:00.000Z"}
For the /api/meter-reading/sync endpoint: Returned after AI processing completes. Contains the full reading data directly. Webhooks are not sent.
{"id": 142,"user_id": 17,"reference_id": "9c7d3f2a-1e4b-4d5a-9b6c-1f2e3d4c5b6a","status": "completed","reading": "02390.276","confidence": 97,"unobstructed": true,"escalated": false,"created_at": "2026-04-28T14:32:02.318Z"}
reference_idstring (UUID v4)Stable correlation key for this request. Save it on your side — the same value will appear on the matching webhook delivery so you can update the right record.statusstringAlways "pending" on the immediate response. Internally the meter row transitions through "processing", "completed", or "failed"; you observe these states via webhook events, not by polling.createdAtstring (ISO 8601)Server timestamp at which the request was accepted.POSTed to your subscribed webhook URL once the AI has produced a reading. Carries the same reference_id you received in the ack.
{"event": "reading.completed","timestamp": "2026-04-28T14:32:02.318Z","data": {"reference_id": "9c7d3f2a-1e4b-4d5a-9b6c-1f2e3d4c5b6a","reading": "02390.276","confidence": 97,"unobstructed": true,"escalated": false,"reading_id": 142}}
reference_idstringUUID v4Matches the ack's reference_id. Use it to update the request record on your side.readingstringe.g. "02390.276"The extracted meter value. Decimal point and leading zeros are preserved.confidenceinteger0 – 100AI confidence as a percentage. Values above 80 are considered reliable.unobstructedbooleantrue / falseWhether the meter face was free from obstructions (dirt, glare, debris).escalatedbooleantrue / falseTrue when confidence is low enough that manual verification is recommended.reading_idinteger (optional)—Database row id for the persisted Reading. Only present when a reading was successfully extracted.POSTed when the AI cannot extract a reading (model error, unreadable image, transient infrastructure failure). The request still counts toward your monthly usage.
{"event": "reading.failed","timestamp": "2026-04-28T14:32:02.318Z","data": {"reference_id": "9c7d3f2a-1e4b-4d5a-9b6c-1f2e3d4c5b6a","api_key_id": 17,"reason": "AI processing error"}}
90 – 100HighReading is reliable. Use directly.70 – 89GoodReading is likely correct. Consider spot-checking.50 – 69MediumReading may have errors. Manual review recommended.0 – 49LowReading is unreliable. escalated will be true.Content-Typeapplication/json; charset=utf-8