Water Bill OCR
Reads a Thai water bill from MWA or PWA and returns the customer, the readings and the charges.
/ocr/v3/water-bill/fileTry it- Price1 ICper page
- Measured99.5%
- Served29Kcalls
Input

OutputPOST /ocr/v3/water-bill/file
- provider
- การประปานครหลวง
- customer_name
- —
- customer_address
- 32/14 ม.3 ตำบลท่าจีน อำเภอสามพราน จังหวัดนครปฐม 11130
- account_number
- 67983262
- invoice_number
- 192011-5
- invoice_date
- 12/02/2567
- current_reading
- 606
- previous_reading
- 567
- consumption_cubic_meter
- 39
- water_usage_charge
- 430.39
- monthly_service_fee
- 25
- discount
- 0
- subtotal_before_vat
- 461.24
- vat_amount
- 32.29
- total_amount
- 493.53
- due_date
- 22/02/2567
Request
multipart/form-data only; there is no Base64 form. Every page of a PDF is read and billed.
Headers
apikeystringrequiredBody
filefilerequiredreturn_ocrbooleantrue to include the raw OCR text.target_langstringth, the default, en, or auto to keep the document's own language.include_confidencebooleantrue: a confidence from 0.00 to 1.00 per field./v3/store/ocr/water-bill is the same endpoint under the store prefix.
Response
The iapp-input-pages header carries the number of pages billed.
docsarrayOne entry per document read
docs.processedobjectThe fields read from the document
docs.processed.providerstringdocs.processed.customer_namedocs.processed.customer_addressdocs.processed.account_numberdocs.processed.invoice_numberdocs.processed.invoice_datedocs.processed.current_readingdocs.processed.previous_readingdocs.processed.consumption_cubic_meterdocs.processed.water_usage_chargedocs.processed.monthly_service_feedocs.processed.discountdocs.processed.subtotal_before_vatdocs.processed.vat_amountdocs.processed.total_amountdocs.processed.due_datestringdocs.messagestringdocs.rawobjectdocs.confidenceobjectdocs.process_msintegerdocs_countintegerprocess_msintegerStatus codes
| Code | Meaning |
|---|---|
| 400 | Unsupported file extension, or a file over 50 MB |
| 404 | Unknown document type in the URL |
| 422 | No file attached |
| 500 | Processing error; the response carries a code to quote to support |
| 502 | Temporary processing failure, also when any page of a multi-page file fails (code: PROCESSING_FAILED). Not charged; retry |
| 503 | Service busy (PROCESSING_BUSY). Not charged; retry, after the seconds in Retry-After when that header is present |
| 504 | Processing timed out (PROCESSING_TIMEOUT). Not charged; retry |
Details
Measured
On the production service, 28 October 2026, against 40 synthetic Thai water bills: every customer, account and amount invented, every page watermarked "specimen", half degraded as office scans and half as phone photographs.
| Measure | Result |
|---|---|
| Fields exactly right, 610 fields | 99.5% (95% CI 98.9–100.0) |
| Scan / phone photograph | 99.0% / 100.0% |
| Bills with every field right | 92.5% |
| Every other field, including meter readings, consumption, charges, VAT and totals | 100.0% |
| Weakest field: customer address | 92.5% |
| All 11 business-document types in the benchmark, 5,092 fields | 97.9% |
| Median time per page through the API, 44 documents across the 11 types | 10.8 s (19.9 s at the 95th percentile) |
Every error was in the customer address; check addresses against another source where they matter. Real bills, with stamps, handwriting and low-contrast printing, score lower than this synthetic set. Method and every field: the benchmark (PDF).
Limits
- Up to 50 MB per request.
- Only the fields above are extracted.
- Degraded scans, glare and handwriting over printed values lower accuracy. Prefer the original PDF, a square-on photograph in even light, or a scan at 300 dpi or more.
- The per-field confidence does not mark errors: across the 11 document types in the benchmark it averaged 0.957 on wrong fields and 0.967 on right ones, and 97.4% of wrong fields scored 0.90 or more. Choose fields for review with arithmetic checks (totals, VAT, balances) and identifier check digits instead.
Data handling
Consent and notice under PDPA and GDPR remain with you as the data controller.