Get Extraction
GET/api/purchase-invoices/ocr/:purchase_extraction_id
Retrieve a purchase invoice OCR extraction record. Returns extracted header data merged with matched supplier and PO info, line items with per-line product matches (5-tier match: supplier_sku → SKU → barcode → MPN → fuzzy name), candidate purchase orders for the supplier (with attach-to-existing-invoice metadata), error_message (if failed/duplicate), and inbound-email source metadata.
Example 200 response:
{
"data": {
"id": 7,
"status": "pending_review",
"file_url": "https://sku2.test/api/purchase-invoices/ocr/7/pdf",
"page_count": 2,
"header": {
"supplier_invoice_number": "INV-9988",
"invoice_date": "2026-04-20",
"due_date": "2026-05-20",
"subtotal": 1250.00,
"tax_amount": 125.00,
"total_amount": 1375.00,
"po_number": "PO-12345",
"matched_supplier_id": 12,
"matched_supplier_name": "Acme Supplies",
"matched_purchase_order_id": 88,
"matched_purchase_order_number": "PO-12345"
},
"is_matched_supplier": true,
"extracted_supplier_name": "Acme Supplies, Inc.",
"lines": [
{
"raw_sku": "WID-001",
"description": "Widget Type 1",
"quantity": 50,
"unit_price": 25.00,
"line_total": 1250.00,
"matched_product_id": 4321,
"matched_product_sku": "WID-001",
"matched_product_name": "Widget Type 1 — Blue"
}
],
"unmatched_line_count": 0,
"azure_cost_usd": 0.0125,
"error_message": null,
"source": "email",
"source_email_from": "billing@acme.com",
"source_email_subject": "Invoice INV-9988",
"supplier": { "id": 12, "name": "Acme Supplies" },
"purchase_order": {
"id": 88,
"purchase_order_number": "PO-12345",
"purchase_order_date": "2026-04-15"
},
"candidate_purchase_orders": [
{
"id": 88,
"purchase_order_number": "PO-12345",
"purchase_order_date": "2026-04-15",
"order_status": "closed",
"existing_invoice_id": 211,
"existing_invoice_number": "INV-9988",
"existing_invoice_has_document": false,
"can_attach_document": true
}
],
"created_at": "2026-04-25T10:30:00.000000Z"
}
}
Candidate purchase orders behavior: The backend includes both open POs for the matched supplier AND a fallback lookup by PO number across all statuses (open/closed). When a candidate PO has can_attach_document: true, the frontend should offer the user the option to attach the OCR'd PDF to the existing invoice via POST /api/purchase-invoices/ocr/{extraction}/attach-to-invoice instead of creating a new invoice.
Existing-invoice fields (existing_invoice_id, existing_invoice_number, existing_invoice_has_document, can_attach_document): These are populated ONLY when the OCR'd supplier_invoice_number matches an existing invoice on that PO (case-insensitive, trimmed comparison). For partial-invoice scenarios where a single PO has multiple invoices with different supplier_invoice_numbers, the candidate PO returns null for these fields when no invoice matches the OCR'd number — allowing a new invoice to be created instead of triggering a false "already invoiced" warning.
Request
Responses
- 200
Successful response