Skip to main content

Invoice Ingestion and AI Extraction

This guide walks through how invoices enter the SpendOne Platform, the AI-based platform for indirect corporate spend, and how the document is turned into structured, postable data. It covers the three supported ingestion channels (manual upload, IMAP polling, email forwarding), the AI extraction step that produces line items, totals, tax and a supplier match, the human review workflow, PO matching, approval, and accounting export.

For admins. Invoice ingestion is configured under Administration → Inbox. Each tenant can connect one or more IMAP mailboxes (server, port, credentials) and a forwarding address that accepts inbound emails with PDF attachments. Manual upload is always available from Invoices → Upload. Reviewers see invoices that need attention under Invoices → Inbox; the review queue is split by workflow step (tax validation, reconciliation, additional data, booking proposal). Accounting export targets are configured under Administration → Accounting, where the two DATEV methods connect over OAuth, and trigger from the invoice detail page once the workflow is complete.

For integrators. The flow spans four route groups: /invoices (lifecycle and reprocess), /invoices/{code}/workflow and the surrounding substep endpoints under /invoices/{code}/tax-validation, /invoices/{code}/reconciliation, /invoices/{code}/additional-data and /invoices/{code}/booking-proposal (human review), /inbound-attachments (email-ingested files awaiting an invoice), and /fi-export/jobs (accounting export, all methods) plus /datev/* and /invoices/{code}/send-to-datev (the DATEV methods' own endpoints). The IMAP and inbound-email channels are server-side workers (not driven by API calls), but every invoice they create is observable and editable through the same /invoices/{code} endpoints. See the OpenAPI reference for full payload schemas.

Sequence​

Step 1: Ingestion​

There are three entry points; all of them produce an invoice in PENDING_EXTRACTION:

  • Manual upload. POST /invoices with a multipart body carrying the PDF in file and the required po_code, plus an optional ignore_duplicate_file.
  • IMAP polling. A per-tenant worker polls the configured mailbox on a schedule, downloads PDF attachments from new messages, and creates one invoice per attachment. Successfully processed messages are deleted from the server.
  • Email forwarding. Messages forwarded to the tenant's inbound address are parsed, and PDF attachments are persisted as inbound-attachments. A reviewer can promote an attachment to an invoice or attach it to an existing PO via PUT /inbound-attachments/{id}/assign-po.

Step 2: AI extraction​

This is the core of the platform. Once the PDF lands, the document is dispatched to the LLM-backed extraction service. The model returns a normalized extraction result: header fields (invoice number, issue date, due date, currency), totals (net, tax, gross), per-line items, applied tax rates, and a supplier hint that the platform resolves against the supplier directory. The invoice transitions from PENDING_EXTRACTION to SAVED and the human-review workflow opens.

If extraction fails or produces low-confidence output, requires_manual_review is set on the invoice. Re-running extraction is explicit and idempotent: POST /invoices/{code}/reprocess discards the prior extraction and dispatches the document again, useful when an LLM model is upgraded or when a corrupt PDF has been replaced.

Step 3: Human review​

Review is not a single screen. It is a state machine of substeps, each with its own GET (to fetch state) and POST (to confirm or correct), and every one of them under /invoices/{code}:

  • GET /invoices/{code}/workflow: current step and what is blocking
  • POST /invoices/{code}/tax-validation/correct and POST /invoices/{code}/tax-validation/confirm: verify VAT lines
  • GET /invoices/{code}/matching and POST /invoices/{code}/matching/manual-select: match the invoice to a purchase order; candidates are returned by GET /invoices/{code}/matching/candidates
  • POST /invoices/{code}/reconciliation/correct and POST /invoices/{code}/reconciliation/confirm: verify supplier, cost center, dates against the matched PO
  • POST /invoices/{code}/additional-data/complete: fill any tenant-required custom fields
  • GET /invoices/{code}/booking-proposal and PUT /invoices/{code}/booking-proposal: review and adjust the GL/tax-account proposal

When all substeps are confirmed, POST /invoices/{code}/workflow/hand-over-to-accounting transitions the invoice into the accounting queue.

Step 4: Approval​

If an approval rule matches the invoice (typically by amount threshold or cost-center owner), an approval plan is generated and the invoice is routed exactly like a purchase request (see the Approval Rules Configuration guide). Approvers act through the same /approvals/* endpoints. Invoices without a matching rule skip this step.

Step 5: Accounting export​

Once approved (or directly after hand-over for tenants without invoice-approval rules), the invoice is exported to the connected accounting system. POST /fi-export/jobs is the unified dispatcher: it reads the tenant's fi_export.export_method setting and routes to that method, so one call works whatever the tenant is configured for. It answers with a job code; GET /fi-export/jobs/{job_code} then carries the run's counters and a submissions array with one entry per invoice.

On the DATEV method there is also a per-invoice route, POST /invoices/{code}/send-to-datev, which enqueues a single DATEV Unternehmen Online booking proposal and returns a submission observable at GET /invoices/{code}/datev-submissions and /invoices/{code}/datev-submission/latest. The two-leg DATEV_REWE mode (a document upload to DATEV Unternehmen Online followed by a Rechnungswesen booking entry) has no per-invoice route and runs through the dispatcher. GET /datev/status reports whether the DATEV connection is live. See the Accounting System Integration guide for connection setup.