Response

The async HTTP response is an acknowledgement only, delivering the actual reading via webhook. The sync HTTP response waits and delivers the reading immediately.

Two stages

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.

Async HTTP acknowledgement 200 OK

For the /api/meter-reading endpoint: Returned immediately when the request passes validation. The image has been queued — it has not been processed yet.

JSON
{
"reference_id": "9c7d3f2a-1e4b-4d5a-9b6c-1f2e3d4c5b6a",
"status": "pending",
"createdAt": "2026-04-28T14:32:00.000Z"
}

Sync HTTP response 200 OK

For the /api/meter-reading/sync endpoint: Returned after AI processing completes. Contains the full reading data directly. Webhooks are not sent.

JSON
{
"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"
}

Acknowledgement fields

FieldTypeDescription
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.

Webhook delivery reading.completed

POSTed to your subscribed webhook URL once the AI has produced a reading. Carries the same reference_id you received in the ack.

JSON
{
"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
}
}
FieldTypeRangeDescription
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.

Failed delivery reading.failed

POSTed when the AI cannot extract a reading (model error, unreadable image, transient infrastructure failure). The request still counts toward your monthly usage.

JSON
{
"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"
}
}

Confidence score guide

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.

Response headers

HeaderDescription
Content-Typeapplication/json; charset=utf-8