NativePort
← All use cases

Extract invoice fields into JSON

Collect invoice identifiers, dates, currency, and totals for your accounting workflow.

The problem

Invoices vary in layout even when they describe the same information. A model working from a filename cannot read them, and a raw text extraction may confuse subtotal, tax, and amount due. Your accounting workflow needs explicit fields.

How NativePort helps

NativePort connects the invoice to a document reader with instructions for the values you need. It returns named fields that your application can display, validate, and match against a purchase order. You keep control of the checks before a record is accepted.

Technical implementation

Use Python 3 with requests installed (python -m pip install requests). Set NATIVEPORT_API_KEY in your environment to your NativePort key. Run the snippets on your server, where your key stays private.

Set DOCUMENT_URL to an HTTPS URL the document service can fetch, such as a time-limited file link. The example reads page 0 (the first page). Select only pages you need, up to 100 per request; split longer documents into batches. Send the URL, not inline file bytes.

python
import os
import requests

BASE = "https://api.nativeport.ai"
HEADERS = {"Authorization": f"Bearer {os.environ['NATIVEPORT_API_KEY']}"}

payload = {
    "document": {"type": "document_url", "document_url": os.environ["DOCUMENT_URL"]},
    "pages": [0],
}
schema = {'type': 'object',
 'properties': {'invoice_number': {'type': ['string', 'null']},
                'supplier': {'type': ['string', 'null']},
                'invoice_date': {'type': ['string', 'null']},
                'currency': {'type': ['string', 'null']},
                'subtotal': {'type': ['string', 'null']},
                'tax': {'type': ['string', 'null']},
                'total_due': {'type': ['string', 'null']}},
 'required': ['invoice_number',
              'supplier',
              'invoice_date',
              'currency',
              'subtotal',
              'tax',
              'total_due'],
 'additionalProperties': False}
payload["document_annotation_format"] = {
    "type": "json_schema",
    "json_schema": {"name": "extraction", "strict": True, "schema": schema},
}
payload["document_annotation_prompt"] = (
    'Extract the named invoice fields. Preserve printed amounts and currency.'
    ' Distinguish subtotal, tax, and total due. Use null when absent or '
    'unreadable.'
)
response = requests.post(BASE + "/mistral/v1/ocr", headers=HEADERS,
                         json=payload, timeout=120)
response.raise_for_status()
result = response.json()
import json
fields = result.get("document_annotation")
if isinstance(fields, str):
    fields = json.loads(fields)
if fields is None:
    raise ValueError("No document annotation returned; inspect the OCR response")
print(fields)

Validate the currency and reconcile subtotal, tax, and total in your application before posting to accounting. The extraction does not approve a payment. Structured annotations use the Document AI rate. See the Mistral request policy for document URLs, page selection, and accepted options. OCR returns recognized content; check unclear scans against the source.

Tool costs

Tool used in the examplePrice per call
Mistral — structured extraction $0.005275 / call (1 page)

Prices in USD. Usage-based tools have no fixed per-call price. View pricing.

Let your agent build it

You don’t need to write this code yourself. Copy this page’s link and paste it into your agent. Ask it to follow the guide and implement the feature for you.