Skip to main content

Invoice Integration Interface v2

Scope

This specification defines a unified, state-of-the-art integration interface for:

  • Abacus
  • Sage50
  • Accounto

It replaces provider-specific coupling with a canonical integration contract and adapter pattern.

Goals

  • Single canonical API contract for all finance integrations
  • Strict idempotency and replay safety
  • Asynchronous, observable processing with job tracking
  • Backward-compatible migration from current exporter/importer jobs
  • Clear provider adapter boundaries (Abacus, Sage50, Accounto)

Non-Goals

  • No direct replacement of provider business rules in phase 1
  • No UI redesign in phase 1

Architecture

  • Integration API (/api/integration/v2/*) receives requests and validates payloads
  • Orchestrator persists command/event records and schedules jobs
  • Canonical domain model is the only internal contract
  • Provider adapters map canonical model <-> external provider model
  • Transport adapters handle REST, SQL/CSV, XML/MQTT specifics

Components

  • IntegrationController
  • IntegrationService
  • IdempotencyStore
  • JobStore
  • AuditTrailService
  • ProviderAdapter interface
  • AbacusAdapter, Sage50Adapter, AccountoAdapter

Canonical Domain Model

TenantContext

  • tenant_id (string, required)
  • client_accounting (string, required)
  • source_system (enum: centraquest, abacus, sage50, accounto)

BusinessPartner

  • partner_id (string)
  • external_id (string)
  • type (enum: company, person)
  • name (string)
  • address (object)
  • tax_id (string, optional)
  • bank_accounts (array)

InvoiceDocument

  • invoice_id (string, internal obj_id)
  • barcode (string)
  • invoice_number (string)
  • document_date (date)
  • due_date (date)
  • currency (string, ISO 4217)
  • gross_amount (decimal)
  • net_amount (decimal)
  • tax_amount (decimal)
  • creditor_or_debitor (enum: creditor, debitor)
  • partner (BusinessPartner)
  • line_items (array of LineItem)

LineItem

  • line_no (integer)
  • account_no (string)
  • cost_center_1 (string, optional)
  • cost_center_2 (string, optional)
  • tax_code (string, optional)
  • tax_rate (decimal, optional)
  • text (string)
  • amount (decimal)
  • inventory (object, optional)

PaymentStatusEvent

  • provider_reference (string)
  • invoice_id (string)
  • status (enum: open, partially_paid, paid, rejected)
  • paid_amount (decimal, optional)
  • paid_at (datetime, optional)
  • raw_payload (object)

API Contract (v2)

Base path: /api/integration/v2

1) Export Invoice

POST /tenants/{tenant_id}/providers/{provider}/invoices:export

Headers:

  • Idempotency-Key (required)
  • X-Correlation-Id (optional)

Body:

  • client_accounting (required)
  • invoice_id (required)
  • booking_type (creditor|debitor, required)
  • options (optional)

Response:

  • 202 Accepted
  • { "job_id": "...", "state": "queued" }

2) Export Addresses

POST /tenants/{tenant_id}/providers/{provider}/addresses:export

3) Import Master Data

POST /tenants/{tenant_id}/providers/{provider}/master-data:import

Body:

  • domains (array: addresses|accounts|taxes|banks|currencies|payment_terms|cost_centers|plants)
  • incremental_since (datetime, optional)

4) Import Payment Status

POST /tenants/{tenant_id}/providers/{provider}/payments:import

5) Job Status

GET /jobs/{job_id}

Response fields:

  • job_id, provider, operation, state, progress, created_at, updated_at, errors[]

6) Webhook Inbound (optional)

POST /webhooks/{provider}

Security:

  • HMAC signature header validation
  • replay window check (timestamp + nonce)

Error Model

All non-2xx responses use RFC7807-style payload:

  • type
  • title
  • status
  • detail
  • instance
  • correlation_id
  • provider_error (optional)

Idempotency & Consistency

  • Every mutating request requires Idempotency-Key
  • Key scope: tenant_id + provider + operation + payload_hash
  • Duplicate requests return original job_id and latest state
  • Outbound provider calls include deterministic external reference when supported

State Model

  • queued
  • running
  • succeeded
  • failed
  • partially_succeeded
  • dead_lettered

Retries

  • Retryable: network errors, 429, 5xx, transient provider unavailability
  • Non-retryable: mapping/validation errors, 4xx semantic errors
  • Backoff: exponential with jitter
  • Max attempts configurable per provider and operation

Observability

  • Structured logs with correlation_id, tenant_id, provider, job_id
  • Metrics: success rate, latency, retry count, dead-letter count
  • Audit trail entry per state transition and external side effect

Security

  • API keys/tokens stored encrypted (no plaintext in logs)
  • Least-privilege credentials per tenant/provider
  • TLS required for all outbound network calls
  • Optional mTLS support for enterprise endpoints

Provider Adapter Requirements

Abacus Adapter

  • Support asynchronous XML processing flow (request/result file pattern)
  • Support agent transport (MQTT/local process mode)
  • Map inventory fields where account starts with 5* (existing behavior)

Sage50 Adapter

  • Support SQL/CSV import compatibility
  • Support legacy transfer channels while exposing v2 API semantics
  • Preserve existing client accounting and period logic

Accounto Adapter

  • Use REST API /v2/{tenant}/{endpoint} style compatibility
  • Support address upsert, booking export, and payment status sync
  • Respect tenant-specific API key handling from obj_table_invoice_client

Mapping Rules

  • Canonical -> provider mapping is explicit and versioned per provider
  • Mapping files versioned as mapping/{provider}/v2/*.yaml
  • Breaking mapping changes require new mapping version and migration note

Migration Strategy

Phase 1: Parallel Run

  • Keep current jobs active
  • Introduce v2 API and adapters in shadow mode
  • Compare outcomes (existing vs v2) for selected tenants

Phase 2: Controlled Cutover

  • Enable v2 per tenant/provider feature flag
  • Automatic fallback to legacy flow on critical failure

Phase 3: Decommission Legacy

  • Freeze old exporter entry points
  • Remove legacy paths after agreed stabilization period

Definition of Done

  • v2 endpoints operational for Abacus, Sage50, Accounto
  • End-to-end export/import tests per provider
  • Idempotency and retry tests green
  • Audit and job observability visible in admin tools
  • Migration runbook approved

Open Items

  • Confirm webhook availability for each provider
  • Confirm canonical field ownership for payment references
  • Decide final SLA per operation type
  • Define tenant onboarding checklist for credentials and validation