Skip to main content

Incoming Invoices

This section explains how to receive, validate, review, and process incoming invoices using faktoora's infrastructure. We support various input channels, automatic validations, and multi-level approval workflows.


Supported Input Channels

1. Email (IMAP or faktoora mailbox)

  • You can connect your own IMAP mailbox in the faktoora UI under Settings > Inbox.
  • Alternatively, faktoora provides a default mailbox address (you@in.faktoora.de) for immediate use.
  • faktoora scans all mailboxes every 5 minutes to extract attached invoices (PDF, XRechnung, ZUGFeRD).

2. API Upload

  • Submit invoices via POST /import/incoming with multipart/form-data, not JSON.
  • Form field:
    • file (binary): The invoice file to upload (XRechnung XML, ZUGFeRD PDF/A-3, etc.)
  • Response (202 Accepted):
    {
    "importId": "IMP456789"
    }
    • importId (string): Unique identifier for this import task

Backwards compatibility: The legacy endpoint POST /import (without the /incoming segment) also accepts invoice uploads and is still supported. New integrations should use POST /import/incoming.

3. PEPPOL Network

  • faktoora supports full PEPPOL connectivity.
  • You can receive invoices directly via your faktoora-assigned PEPPOL ID.

Import API Endpoints

All /import/incoming paths require apiKeyAuth. The legacy /import/{importId} prefix is also supported for backwards compatibility.

EndpointMethodPurpose
POST /import/incomingPOSTUpload an invoice file (multipart/form-data, field: file). Returns { “importId”: “...” }.
PATCH /import/incoming/{importId}PATCHEdit invoice data after import (partial update). Returns the updated invoice record.
GET /import/incomingGETPaginated list of all incoming imported invoices (supports page, perPage, sort, order, filters).
GET /import/incoming/{importId}/validationGETJSON validation summary. Returns { “status”: “accepted” } or { “status”: “rejected” }.
GET /import/incoming/{importId}/validation/pdfGETPDF validation report.
GET /import/incoming/{importId}/statusGETImport processing status with validationStatus, visualizationStatus, and overallStatus.
GET /import/incoming/{importId}/content/summaryGETKey invoice attributes.
GET /import/incoming/{importId}/contentGETMerged complete content (seller, buyer, line items, taxes, payment terms, payment means, delivery).
GET /import/incoming/{importId}/content/pdfGETPDF visual representation of the invoice.
GET /import/incoming/{importId}/content/lineitemsGETArray of invoice line items.
GET /import/incoming/{importId}/content/taxesGETVAT breakdown by category.
GET /import/incoming/{importId}/content/paymenttermsGETPayment terms (due date, Skonto conditions, etc.).
GET /import/incoming/{importId}/content/paymentmeansGETPayment methods (bank transfer, SEPA, etc.).
GET /import/incoming/{importId}/content/sellerGETSeller snapshot from the invoice.
GET /import/incoming/{importId}/content/buyerGETBuyer snapshot from the invoice.
GET /import/incoming/{importId}/content/deliveryGETDelivery address from the invoice.
GET /import/incoming/{importId}/sourceGETOriginal source file (XML preferred over PDF). Returns application/xml or application/pdf.
GET /import/incoming/{importId}/attachmentsGETPaginated list of embedded attachments extracted from the invoice.
GET /import/incoming/{importId}/attachment/{attachmentId}GETMetadata for a single attachment.
GET /import/incoming/{importId}/attachment/{attachmentId}/fileGETDownload the attachment file (application/octet-stream).
Example: Upload an invoice
curl -X POST \
-H “X-API-KEY: your-api-token” \
-F “file=@invoice.xml” \
https://api.faktoora.com/api/v1/import/incoming

Response (202 Accepted)

{ “importId”: “IMP456789” }
Example: Check import status
curl -H “X-API-KEY: your-api-token” \
https://api.faktoora.com/api/v1/import/incoming/IMP456789/status

Response (200 OK)

{
“validationStatus”: “accepted”,
“visualizationStatus”: “accepted”,
“overallStatus”: “accepted”
}

overallStatus is accepted only when both validationStatus and visualizationStatus are accepted. Possible values for each: accepted, failed, pending.

Example: Retrieve structured content
# Full merged content
curl -H “X-API-KEY: your-api-token” \
https://api.faktoora.com/api/v1/import/incoming/IMP456789/content

# Just line items
curl -H “X-API-KEY: your-api-token” \
https://api.faktoora.com/api/v1/import/incoming/IMP456789/content/lineitems

# Original XML source file
curl -H “X-API-KEY: your-api-token” \
https://api.faktoora.com/api/v1/import/incoming/IMP456789/source

Editing an Imported Invoice

Use PATCH /import/incoming/{importId} to correct or enrich invoice data after import — for example, to fix a typo in the invoice number, update amounts, link the invoice to a customer, or replace line items.

Only the fields you include in the request body are updated; all other fields remain unchanged.

Restrictions

  • Terminal statuses: invoices with status PAID, CANCELLED, or ARCHIVED cannot be edited. The API returns 400.
  • Status changes: the status field is not accepted on this endpoint. Use the dedicated status-transition endpoints instead.
  • File references (invoiceIncomingFileId, xmlInvoiceFileId, etc.) are silently ignored if included.
  • Ownership: the importId must belong to the authenticated API key. Returns 404 otherwise.
  • customerId / projectId: validated to belong to the authenticated user. Returns 404 if not found.

Editable fields

FieldTypeNotes
invoiceNumberstringCorrect the invoice number
invoiceTypeCodenumber380, 381, or 384
issueDatedate-timeInvoice date
lastPaymentDatedate-timeDue date
amountnumberTotal amount (max 99999999.99)
outstandingBalancenumberRemaining balance (max 99999999.99)
buyerReferencestringReference/routing field
invoiceCurrencyCodestringISO 4217 currency code
customerIduuidLink to a customer record
projectIduuidLink to a project
sellerNamestringSeller display name
sellerSnapshotobjectFull seller address/contact data
buyerSnapshotobjectFull buyer address/contact data
invoiceIncomingPositionsarrayLine items — full replace (existing items are deleted)
vatBreakdownarrayTax breakdown — triggers automatic taxAmount recalculation
paymentMeansarrayPayment methods — full replace
paymenttermstringFree-text payment terms
specifiedTradePaymentTermsarrayStructured Skonto terms
Example: Correct an invoice number and link to a customer
curl -X PATCH \
-H "X-API-KEY: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"invoiceNumber": "RE-2024-0042",
"customerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}' \
https://api.faktoora.com/api/v1/import/incoming/IMP456789

Response (200 OK) — returns the full updated invoice record.

Example: Update VAT breakdown (triggers taxAmount recalculation)
curl -X PATCH \
-H "X-API-KEY: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"amount": 1190.00,
"vatBreakdown": [
{ "category": "S", "rate": 19, "taxable": 1000.00, "amount": 190.00 }
]
}' \
https://api.faktoora.com/api/v1/import/incoming/IMP456789

taxAmount on the invoice is recalculated automatically from the provided vatBreakdown.


Validation & Reporting

  • Automatic EN16931 validation runs upon upload.
  • If rejected:
    1. A PDF validation report is generated.
    2. A webhook with status=rejected fires.
  • If accepted:
    • Invoice moves into your UI for review and approval.
    • You may retrieve a human-readable report via the HTML or PDF endpoints above.

Invoice Visibility & Workflow in the UI

Once an invoice import is accepted, it appears in the faktoora UI under Incoming Invoices. From there, users can:

  1. Review the imported invoice details.
  2. Manually reject with a reason (triggers a rejection email).
  3. Confirm to begin an approval workflow.
  4. Trigger payment (if a bank account is connected).
  5. Archive after payment completion.

Process Diagrams

Sequence Diagram

This diagram shows the end-to-end flow from sender to payment.

Flowchart

This flowchart outlines the automatic and manual steps from receipt to archiving.