Brazilian Nota Fiscal — deep extraction
Brazil's tax documents pack more structured information than any other receipt format in the world. Oligon parses all four common variants:
| Variant | Use case |
|---|---|
| NFe | B2B goods invoice (full XML equivalent). |
| NFCe | B2C consumer receipt with QR code. |
| NFSe | Service invoice (varies by município). |
| Cupom Fiscal | Legacy SAT / ECF receipt. |
Pass type: "nfe" / "nfce" / "nfse" / "cupom_fiscal" to maximise
fidelity. With no hint, Oligon auto-classifies in ~90 ms before
extracting.
What we extract
Beyond merchant, total, and line items, every BR document returns:
| Field | Description |
|---|---|
document_key | 44-digit chave de acesso. |
document_number | Sequential NF number. |
merchant_tax_id | CNPJ formatted XX.XXX.XXX/0001-YY. |
customer_tax_id | CPF/CNPJ when present on the document. |
line_items[].ncm | 8-digit Nomenclatura Comum do Mercosul. |
line_items[].cfop | 4-digit Código Fiscal de Operações. |
line_items[].cest | Código Especificador da Substituição Tributária. |
taxes.icms | ICMS breakdown (CST, base, alíquota, valor). |
taxes.pis_cofins | PIS + COFINS values. |
taxes.iss | ISS for service invoices. |
These appear under raw in the SDK responses; the typed Receipt
exposes only the cross-format common fields. Reach into raw for the
fiscal detail.
Validating the chave de acesso
The 44-digit key follows a defined structure and ends with a mod-11 check digit. Validate it before persisting:
def is_valid_chave(chave: str) -> bool:
if len(chave) != 44 or not chave.isdigit():
return False
seq = [int(c) for c in chave[:43]]
weights = [2, 3, 4, 5, 6, 7, 8, 9] * 6
total = sum(d * w for d, w in zip(reversed(seq), weights))
check = 11 - (total % 11)
if check >= 10:
check = 0
return check == int(chave[43])Oligon validates the check digit server-side and surfaces an
invalid_document_key warning in raw.warnings. Anything you compute
in your app is purely defence in depth.
QR codes on NFCe
NFCe receipts carry a QR code that links to the SEFAZ portal. Oligon extracts and validates the URL:
{
"type": "nfce",
"nfce_qr_url": "https://www.fazenda.sp.gov.br/nfce/qrcode?p=...",
"nfce_qr_signature_ok": true
}A true signature means the document was issued by SEFAZ. A false
result usually indicates a counterfeit receipt — surface it loudly to
end-users.
Per-state quirks
Each Brazilian state implements NFSe slightly differently (different
fields, different XML schema). We normalise to the same JSON shape, but
the original XML or PDF is preserved in raw.original_xml /
raw.original_pdf_text so you can fall back if a state-specific
attribute matters.
Sandbox samples
Test keys (sk_test_…) can use these well-known sample IDs to skip
real OCR:
| ID | Returns |
|---|---|
sample_nfe_full | Full NFe with line items, taxes, customer. |
sample_nfce_minimal | Minimal NFCe (one line, no customer). |
sample_nfse_sao_paulo | NFSe issued by município São Paulo. |
client.receipts.retrieve("sample_nfe_full")