postBooksScanWithHttpInfo method
Scan a receipt or invoice into a proposed voucher
Takes a receipt or invoice as RAW BYTES — a PDF, an image or plain text, uploaded under its own content type, not wrapped in JSON — extracts what the document says, resolves the vendor's expense category, and answers a DRAFT carrying a balanced voucher proposed for it. NOTHING IS POSTED. That split is the whole design: the model only ever produces a structured reading of the document, the voucher is assembled deterministically in Go from that reading, and the ledger is written only by the separate book call a human confirms. So a misread scan can propose a wrong draft; it cannot move money. Amounts are exact integer cents end to end — the extraction returns cents, never a decimal — so no rounding enters the ledger. The draft's id is the FILE HASH, and that is what makes booking idempotent: re-scanning the same bytes addresses the same draft rather than queuing a second one. A row is written to the org's document inbox as a side effect, moving it from unsorted to draft. Scoped to the caller's own org from the validated principal and refused without one; sandbox=true targets the sandbox ledger, and filename is recorded for the inbox. An empty or oversized upload is a 400, and a deployment with no scanner model answers 501.
Note: This method returns the HTTP Response.
Parameters:
MultipartFilebody:
Implementation
Future<Response> postBooksScanWithHttpInfo({ MultipartFile? body, }) async {
// ignore: prefer_const_declarations
final path = r'/v1/books/scan';
// ignore: prefer_final_locals
Object? postBody = body;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/octet-stream'];
return apiClient.invokeAPI(
path,
'POST',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}