Skip to main content

Accounting System Integration

Getting booked invoices out of SpendOne and into your financial system. Export is asynchronous and job-based throughout: you request an export, poll the job, then fetch the file. There is no real-time synchronization path and no push into your ledger.

Supported methods​

An export profile is configured per tenant with one of five methods:

MethodWhat it produces
CSVA CSV file shaped by a configurable export profile
EMAILThe export file delivered by email
SAPAn SAP-shaped file, fetched through the SAP download URL
DATEVA booking proposal submitted to DATEV Unternehmen Online
DATEV_REWEA document upload to DATEV Unternehmen Online followed by a Rechnungswesen booking entry

GET /api/v1/csv-export/method returns the method this tenant is configured for.

POST /api/v1/fi-export/jobs reads that setting and routes to whichever method the tenant runs, so an integration that uses the job flow below needs no per-method branching. The DATEV-specific endpoints exist alongside it and are described under DATEV.

The export job flow​

POST /api/v1/fi-export/jobs
Authorization: Bearer <access-token>
Content-Type: application/json

{
"invoice_codes": ["INV-1042"],
"purchase_order_codes": [],
"task_codes": []
}

Then poll and download:

GET /api/v1/fi-export/jobs # list jobs
GET /api/v1/fi-export/jobs/{job_code} # one job's status
GET /api/v1/fi-export/jobs/{job_code}/download-url # signed URL for the file
GET /api/v1/fi-export/jobs/{job_code}/sap-download-url # the SAP variant

One job carries many invoices, so this is the bulk path as well as the single-invoice one. GET /api/v1/fi-export/jobs/{job_code} answers with both halves of the outcome: the job's own total_items / successful_items / failed_items counters, and a submissions array with one entry per invoice carrying its invoice_code, status and error_message. Read the array, not only the counters, to find out which invoice failed.

Configuring the mapping​

Before a first export, the chart of accounts and the export shape have to exist:

GET /api/v1/accounts # chart of accounts
POST /api/v1/accounts/import # bulk-load it

On a DATEV tenant, GET /api/v1/datev/accounts returns the accounting accounts the MAESN integration exposes for the tenant, and the per-entity export configuration sits at GET /api/v1/datev/exports/configs, GET and PATCH /api/v1/datev/exports/configs/{code}.

For the CSV method, the column layout is a profile:

GET /api/v1/csv-export/profiles
POST /api/v1/csv-export/profiles
POST /api/v1/csv-export/profiles/{code}/fields
GET /api/v1/csv-export/available-fields
GET /api/v1/csv-export/targets # S3 or SFTP destination
GET /api/v1/csv-export/lookup-tables # value translation tables

Tax-code translation is separate, and required before an invoice with an unmapped tax rate can be transferred: GET /api/v1/tax-mappings. An unmapped rate fails the transfer with problem type booking-tax-code-unmapped.

Journal entries​

The booking itself is inspectable and editable before export:

GET /api/v1/journal-entries
GET /api/v1/journal-entries/{code}
POST /api/v1/journal-entries/{code}/lines
PUT /api/v1/journal-entries/{code}/lines/{id}
DELETE /api/v1/journal-entries/{code}/lines/{id}

The proposal that precedes it lives on the invoice: GET /api/v1/invoices/{code}/booking-proposal and its PUT.

DATEV​

DATEV is one of the five export methods, not the general shape of an export: a tenant on CSV, EMAIL or SAP never touches anything in this section, and POST /api/v1/fi-export/jobs covers all five. What follows is what the DATEV and DATEV_REWE methods add on top.

The connection is an OAuth app. GET /api/v1/datev/status reports whether it is live, and GET /api/v1/datev/auth-url starts the flow. The redirect targets that flow hands DATEV are served by the platform and are not part of the published surface: a browser reaches them, an integration never calls them. DELETE /api/v1/datev/account-key disconnects the stored account key.

For the DATEV method an invoice can also be submitted one at a time, and the result is tracked as a submission rather than a file:

POST /api/v1/invoices/{code}/send-to-datev # 202, transmission runs in the background
GET /api/v1/invoices/{code}/datev-submissions # every submission for it
GET /api/v1/invoices/{code}/datev-submission/latest # the most recent
GET /api/v1/datev/submissions/{id} # one submission by id

POST /invoices/{code}/send-to-datev always enqueues a DATEV Unternehmen Online booking proposal, which is the DATEV mode's shape; it does not read the tenant's configured export method, and it answers 503 when the MAESN integration is not configured. The two-leg DATEV_REWE flow has no per-invoice route, so a ReWe tenant exports through POST /api/v1/fi-export/jobs.