POST/forms/scanmultipart
GET/forms/scan/last
GET/forms/field-form/{form_type}
This endpoint takes a file, so it is multipart/form-data, not JSON. Do not set Content-Type yourself; the boundary has to come from the encoder.
curl -X POST "$BASE/forms/scan" \ -H "Authorization: Bearer $TOKEN" \ -F "file=@breaker-52-1.jpg" \ --max-time 120
const body = new FormData() body.append('file', file) const res = await fetch(`${BASE}/forms/scan`, { method: 'POST', // Authorization only. Setting Content-Type here would omit the // multipart boundary and the request would fail to parse. headers: { 'Authorization': `Bearer ${token}` }, body, signal: AbortSignal.timeout(120_000), })
with open("breaker-52-1.jpg", "rb") as fh: # files= sets the multipart Content-Type for you. scan = s.post(f"{BASE}/forms/scan", files={"file": fh}, timeout=120).json()
The transcription is returned as fields keyed to the recognised form. GET /forms/field-form/{form_type} returns the blank field contract for a form type (its identifier, version and section structure) which is what you map a scan onto, and what you would render your own capture UI from.
Scanning does not write to the database
A scan returns extracted fields and nothing more. Persisting them is a separate POST /db/equipment/{eid}/records with the values in form_data, which keeps the review step in your control rather than in ours.