Skip to the content.

ERP → Sunbay Invoice Data Integration Guide

This document specifies the invoice data Sunbay needs to obtain from your ERP / source system, and the two ways that data can be exchanged, so that Sunbay can run debt collection and receivables analytics on your behalf.

It is written for the IT team building the integration between the ERP landscape and Sunbay.

Two integration options are supported:

The data model (§3) is the core of this document and is identical for both options. Sections §4 and §5 describe the two exchange mechanisms; §6-§9 cover formats, security, reliability and scheduling. A number of protocol details are deliberately left open for onboarding (§10).

On flexibility. This is the specification to implement, not a loose suggestion. Where a field or detail genuinely cannot be met by your source system, we can align it together during onboarding (§10). Please implement the contract as written and flag the specific points that do not fit.

Scope. This document covers what data Sunbay needs and how it is exchanged. How Sunbay stores, processes, or acts on the data internally is intentionally out of scope.


Contents

  1. Purpose & Scope
  2. Integration Options
  3. Data Model
  4. Option A: Client-Hosted Invoice API (Sunbay Pulls)
  5. Option B: Push to Sunbay
  6. Data Formats & Conventions
  7. Security & Authentication
  8. Reliability
  9. Scheduling & Volume
  10. Points to Confirm During Onboarding

1. Purpose & Scope

Sunbay automates the collection of overdue receivables (email/SMS reminders and related flows) and provides receivables analytics. To do this, Sunbay needs a continuous feed of your sales/revenue invoices - both paid and unpaid - together with the debtor (customer) data for each invoice:

Optionally, the PDF of an invoice can be exchanged as well - it is needed only when invoice documents should be attached to reminder emails (§3.7).

In both integration options the ERP remains the system of record. Sunbay never writes back to the ERP - the integration is read-only from the ERP’s perspective.

In scope for this document


2. Integration Options

You expose a small, read-only HTTPS API over the ERP data (specified in §4). Sunbay calls it on a schedule it controls: incremental polls for new and changed invoices, plus optional periodic full snapshots for reconciliation.

Why this is the recommended option:

2.2 Option B - push to Sunbay

Your system pushes each invoice to Sunbay’s ingestion endpoints (§5), one call per invoice, on a schedule you run. Choose this option when connectivity is a hard constraint - i.e. no inbound endpoint may be exposed from your network, and your systems can only send data out over the public internet.

2.3 Comparison

Aspect Option A - Sunbay pulls Option B - you push
Who initiates Sunbay (scheduled polls) Your system (own scheduler)
You implement Read-only invoice endpoint (+ optional PDF endpoint) A delivery job: per-invoice pushes, retries, backoff
Scheduling & retries Owned by Sunbay Owned by you
Cancellations Visible as Cancelled tombstones in API responses (§4.5) Require an explicit cancellation signal in incremental mode (§5.3)
Backfill / first load Sunbay crawls the history via the same API Bulk file upload or many individual pushes (§5.2)
PDFs (if enabled) Fetched by Sunbay on demand at each reminder send (no copies kept) Shipped by you with each push and stored by Sunbay
Tenant identification Implicit - credentials and base URL are client-specific (§7.2) tenantCode field in every payload (§7.3)
Result reporting HTTP responses of your API Acknowledgment design to be agreed (§5.5)

2.4 Common to both options


3. Data Model

This is the most important section. Each invoice exposed to (or pushed to) Sunbay should carry the following fields. Customer (debtor) data is embedded with each invoice (denormalized) - there is no separate customer feed.

Required column legend: Yes = mandatory · Rec. = recommended (strongly preferred) · Opt. = optional · Cond. = conditional.

3.1 Invoice identification

Field Type Required Description
invoiceId string Yes Stable, globally-unique identifier of the invoice in the source system. Used to recognise the same invoice across syncs (deduplication / update key). Must be stable - the same invoice must always carry the same id, even after edits.
invoiceNumber string Yes Human-readable invoice number (e.g. FV/2026/01/0123). Shown to the debtor in reminders.
documentType enum Yes Kind of document - see §3.1.1.
correctedInvoiceId string Cond. When documentType = CorrectiveInvoice: the invoiceId of the original invoice this document corrects.
issueDate date Yes Date the invoice was issued.
dueDate date Yes Payment due date - when the invoice becomes collectible.
paymentTermDays integer Opt. Payment term in days, if available.

3.1.1 documentType values

Value Meaning Collectible receivable?
Invoice Standard (VAT) invoice Yes
CorrectiveInvoice Corrective / adjustment invoice Adjusts an existing receivable
AdvanceInvoice Advance payment invoice Yes (advance)
FinalInvoice Final invoice Yes
Proforma Pro forma invoice No - not a legal receivable
CreditNote Credit note Reduces a receivable
DebitNote Debit note Increases a receivable

If your source system uses other document kinds, list them during onboarding so we can map them (§10).

3.1.2 Corrections

A corrective document carries documentType = CorrectiveInvoice and correctedInvoiceId pointing at the original invoice. It adjusts the outstanding amount of the original receivable. How your source system expresses correction amounts (the new corrected totals, the difference/delta, or “before/after”) must be confirmed during onboarding so the balance is interpreted correctly (§10).

3.2 Amounts & currency

Field Type Required Description
currency string (ISO 4217) Yes e.g. PLN, EUR.
amountNet decimal Yes Net amount.
amountVat decimal Yes VAT amount.
amountGross decimal Yes Gross total - the full amount of the receivable.
amountPaid decimal Yes Amount already paid against this invoice (0 if none). Enables partial-payment handling.
amountOutstanding decimal Yes Remaining balance still owed (amountGross - amountPaid). This is what collection chases.

3.3 Status & lifecycle

Field Type Required Description
status enum Yes Open · PartiallyPaid · Paid · Cancelled.
paidDate date Cond. Date the invoice was fully paid. Required when status = Paid.
isBlockedForCollection boolean Yes true if Sunbay must not chase this invoice (dispute, legal hold, internal block).
lastModifiedAt timestamp Yes (Option A) / Rec. (Option B) When the invoice record last changed in the source system (ISO-8601 UTC). Drives incremental fetching in Option A (§4.2): any data change - status, amounts, payments, cancellation, correction linkage - must update this timestamp.

3.4 Debtor (customer)

Embedded per invoice. This is the party Sunbay contacts.

Field Type Required Description
customerId string Yes Stable, unique identifier of the customer in the source system.
customerName string Yes Debtor name (company or person).
customerTaxId string Rec. Tax identifier (e.g. VAT ID / NIP).
customerEmail string Rec. Primary email. Required for email reminders.
customerEmailCcs string[] Opt. List of additional CC email addresses.
customerPhone string Opt. Phone number in international format including the country code, e.g. +48512345678. Required for SMS reminders.
customerAddress string Rec. Postal address.
customerCountryCode string (ISO 3166-1) Yes e.g. PL.
customerCommunicationLanguage string (ISO 639-1) Opt. Preferred language for reminders, e.g. pl, en, de. Sunbay selects the reminder template language per debtor; when absent, the client-wide default is used.
customFields object Opt. Arbitrary key-value pairs at customer level (see §3.6).

3.5 Seller & payment

Field Type Required Description
sellerName string Opt. Issuing entity name. A single installation may contain several legal entities/sellers.
sellerTaxId string Opt. Seller tax identifier.
sellerAddress string Opt. Issuing entity postal address. Useful for formal reminders and multi-entity installations.
bankAccount string Yes Bank account the debtor should pay into (IBAN/NRB). Included in reminders.

3.6 Custom fields & references

Field Type Required Description
customFields object Opt. Arbitrary key-value pairs at invoice level. Custom fields are supported at both invoice and customer level - send any extra attributes that may be useful (segment, region, contract code, cost centre, …).
externalReference string Opt. Any additional reference useful for reconciliation.

3.7 PDF (optional)

PDFs are optional. A PDF is needed only if you want Sunbay to attach the invoice document to reminder emails. If you do not need attachments, skip PDFs entirely - the integration is fully functional without them.

If PDF attachments are enabled:

One PDF per invoice. PDF specifics (always available? maximum size? PDFs for corrective documents?) are confirmed during onboarding (§10).

3.8 Line items (optional)

Invoice line items are optional but valuable - they enable richer analytics and more informative reminder content. The invoice is fully usable without them; when PDFs are exchanged, the PDF remains the authoritative document.

If provided, lineItems is an array where each line carries:

Field Type Required (within a line) Description
name string Yes Description of the goods/service.
quantity decimal Yes Quantity.
unit string Opt. Unit of measure, e.g. pcs, hours.
unitPriceNet decimal Yes Net unit price.
discountPercent decimal Opt. Line discount in percent, e.g. 10.0. The line totals below are already net of this discount - it is informational.
vatRate decimal Rec. VAT rate in percent, e.g. 23.0.
vatAmount decimal Opt. VAT amount for the line.
amountNet decimal Rec. Net total for the line.
amountGross decimal Yes Gross total for the line.

3.9 Example invoice object

The same invoice object is used in both options: it is the item shape returned by your API (Option A, §4.2) and the invoice part of a push payload (Option B, §5.1).

{
  "invoiceId": "ERP-2026-INV-000123",
  "invoiceNumber": "FV/2026/01/0123",
  "documentType": "Invoice",
  "correctedInvoiceId": null,
  "issueDate": "2026-01-10",
  "dueDate": "2026-01-24",
  "paymentTermDays": 14,

  "currency": "PLN",
  "amountNet": 1000.00,
  "amountVat": 230.00,
  "amountGross": 1230.00,
  "amountPaid": 0.00,
  "amountOutstanding": 1230.00,

  "status": "Open",
  "paidDate": null,
  "isBlockedForCollection": false,
  "lastModifiedAt": "2026-01-25T11:02:14Z",

  "seller": {
    "sellerName": "ACME Sp. z o.o.",
    "sellerTaxId": "5213001234",
    "bankAccount": "PL61109010140000071219812874"
  },

  "customer": {
    "customerId": "ERP-CUST-10001",
    "customerName": "Kowalski Handel Sp. z o.o.",
    "customerTaxId": "7010001234",
    "customerEmail": "ksiegowosc@kowalski.pl",
    "customerEmailCcs": ["zarzad@kowalski.pl", "biuro@kowalski.pl"],
    "customerPhone": "+48512345678",
    "customerAddress": "ul. Przykładowa 12, 00-001 Warszawa",
    "customerCountryCode": "PL",
    "customerCommunicationLanguage": "pl",
    "customFields": {
      "segment": "B2B",
      "region": "Mazowieckie"
    }
  },

  "lineItems": [
    {
      "name": "Consulting services - January 2026",
      "quantity": 10.0,
      "unit": "hours",
      "unitPriceNet": 80.00,
      "vatRate": 23.0,
      "vatAmount": 184.00,
      "amountNet": 800.00,
      "amountGross": 984.00
    },
    {
      "name": "License fee",
      "quantity": 1.0,
      "unit": "pcs",
      "unitPriceNet": 200.00,
      "vatRate": 23.0,
      "vatAmount": 46.00,
      "amountNet": 200.00,
      "amountGross": 246.00
    }
  ],

  "externalReference": "SRC-REF-998877",
  "customFields": {
    "costCenter": "CC-204",
    "salesRep": "A. Nowak"
  }
}

4. Option A: Client-Hosted Invoice API (Sunbay Pulls)

This is the contract Sunbay’s fetcher will code against. Host and base path are yours to choose - a versioned prefix is recommended, e.g. {baseUrl} = https://api.example.com/sunbay/v1. Everything below the base URL - paths, parameters, response shapes - should be implemented as specified here; deviations can be discussed during onboarding.

4.1 Overview & responsibilities

4.2 List invoices

GET {baseUrl}/invoices?modifiedSince=2026-01-24T09:30:00Z&page=1&pageSize=100
Authorization: <see §7.2>
Accept: application/json

Query parameters (all optional):

Parameter Type Semantics
modifiedSince ISO-8601 UTC timestamp Return only invoices with lastModifiedAt >= modifiedSince (inclusive). When omitted, return a full snapshot: all Open / PartiallyPaid invoices plus Paid / Cancelled ones within the agreed history window (§10).
page integer 1-based page number. Default 1.
pageSize integer Maximum items per page. Default 100; the server may cap it (suggested cap 500).

Response 200 OK, application/json:

{
  "items": [ { ...invoice objects exactly as defined in §3... } ],
  "page": 1,
  "pageSize": 100,
  "totalCount": 1234
}

Incremental fetching (watermarking). After each completed crawl Sunbay stores the highest lastModifiedAt seen, and polls next with modifiedSince = watermark - small overlap (a few minutes). Any duplicates this causes are harmless - invoiceId idempotency (§8) makes re-processing a safe update. Your obligations: every data change bumps lastModifiedAt, the filter is inclusive, and timestamps are UTC.

4.3 Invoice PDF (optional)

Implement this endpoint only if invoice documents should be attached to reminder emails. If you do not need attachments, skip it - the integration works fully without PDFs.

GET {baseUrl}/invoices/{invoiceId}/pdf
GET {baseUrl}/invoices/{invoiceId}

Returns 200 OK with one invoice object (§3), or 404 if unknown. Used for spot re-fetches and joint debugging; not required for the integration to work.

4.5 Snapshots, increments & cancellations

4.6 Errors & availability

4.7 Example exchange

GET /sunbay/v1/invoices?modifiedSince=2026-01-24T09:30:00Z&page=1&pageSize=100
Authorization: Bearer eyJhbGciOi...
Accept: application/json
{
  "items": [
    { ...the invoice object from §3.9... }
  ],
  "page": 1,
  "pageSize": 100,
  "totalCount": 1
}

And - only when PDF attachments are enabled (§3.7):

GET /sunbay/v1/invoices/ERP-2026-INV-000123/pdf
Authorization: Bearer eyJhbGciOi...

HTTP/1.1 200 OK
Content-Type: application/pdf

%PDF-1.7 ...binary...

5. Option B: Push to Sunbay

Use this option when your environment cannot expose an inbound endpoint: connectivity is one-way, your system can send data out to Sunbay over the public internet, and Sunbay cannot initiate connections back.

The endpoints below are a proposal to illustrate the intended shape. The exact paths, request/response bodies, acknowledgment mechanism, and retry behaviour are finalised together during onboarding - they depend on how your delivery job is built and on whether you want to read back per-invoice results (§5.5).

5.1 Per-invoice push (primary)

For each invoice, your system makes one call to Sunbay carrying the invoice’s structured data (§3). When PDF attachments are enabled (§3.7), the PDF travels together with the data in the same call as multipart/form-data; without PDFs, the push is a plain JSON request. Invoices are sent one after another on your interval - each call is small, so a standard HTTPS request is sufficient.

PDF storage. In push mode, when attachments are enabled, Sunbay stores each pushed PDF on its side - it has no way to fetch it back from your system when a reminder is sent later. This is the opposite of Option A, where PDFs are pulled on demand and never stored. Avoiding PDF storage (and keeping documents authoritative in your system) is one reason Option A is recommended.

POST /api/ingest/invoices:

POST /api/ingest/invoices
Authorization: <see §7.3>
Content-Type: multipart/form-data; boundary=----sunbay

------sunbay
Content-Disposition: form-data; name="metadata"
Content-Type: application/json

{
  "tenantCode": "ACME-PL",
  "syncMode": "Incremental",
  "invoice": { ...the invoice object from §3.9... }
}
------sunbay
Content-Disposition: form-data; name="pdf"; filename="FV-2026-01-0123.pdf"
Content-Type: application/pdf

%PDF-1.7 ...binary...
------sunbay--

The pdf part is optional - include it only when PDF attachments are enabled (§3.7).

Sunbay responds with an HTTP status indicating receipt (2xx accepted, 4xx for a malformed/invalid request). The precise success/error body is part of the acknowledgment design (§5.5).

5.2 Bulk data-only (backfill)

POST /api/ingest/bulk - a single compressed file (.zip of CSV or JSON Lines), data only, no PDFs - for initial historical backfill or very high volumes. The same logical fields from §3 apply, one record per invoice. This is an alternative to issuing thousands of individual calls for a first load.

5.3 Sync modes

Which invoices to send each cycle is chosen during onboarding:

5.4 Optional “sync session” framing

To bound a full snapshot and give a natural place to report results, calls in one cycle may be grouped in a session: a begin call returns a sessionId, per-invoice calls reference it, and a complete call closes the cycle. This is optional and subject to the same “to be agreed” note above.

5.5 Acknowledgment, errors & duplicates - to be agreed

Because Sunbay cannot call your system in this option, any per-invoice or per-batch result you need (accepted / rejected with reasons / duplicate) must be read back by your delivery job. Whether you want this at all, what response bodies Sunbay returns, how validation errors and duplicates are signalled, and how this ties into retries (§8) - all of this is agreed during onboarding.


6. Data Formats & Conventions

These conventions apply to both options - to your API responses in Option A, and to pushed payloads/files in Option B.

Aspect Convention
Text encoding UTF-8 for all text and for any CSV/JSON content. ⚠️ Some ERP exports default to regional encodings (e.g. Windows-125x) - convert to UTF-8.
Dates ISO-8601 calendar dates: YYYY-MM-DD (e.g. 2026-01-24).
Timestamps ISO-8601 in UTC with Z (e.g. 2026-01-24T09:30:00Z).
Decimal separator Dot (.). No thousands separators. ⚠️ Locales using a decimal comma must be normalised (1230,001230.00).
Currency ISO 4217 three-letter code.
Phone International format with country code, e.g. +48512345678.
Booleans true / false.
Missing values Omit the field or send null - do not send empty placeholder strings for numeric/date fields.

7. Security & Authentication

7.1 Transport

7.2 Option A - securing your API

You decide how your endpoint authenticates Sunbay; any of the following works, chosen per your security policy during onboarding:

Additionally:

7.3 Option B - authenticating to Sunbay

The method is agreed during onboarding and aligned with your security policy:

Tenant identification: each call carries a tenantCode together with the credential; Sunbay maps the pair to a single tenant. Data is isolated per tenant; a credential can only write data for its own tenant. For a single-client integration the tenantCode is a fixed constant provided at onboarding.

7.4 Data protection


8. Reliability

Idempotency (both options). invoiceId is the key: re-sending or re-fetching the same invoice is a safe update, never a duplicate. An invoice’s invoiceId must never change between syncs, edits or retries.

Option A - Sunbay retries

Option B - your delivery job retries


9. Scheduling & Volume

Option A

Option B


10. Points to Confirm During Onboarding

Note: these points are for the implementation/rollout phase itself - not something to resolve before reviewing or sharing this document. We work through them together when the integration is being built.

Common (both options)

  1. Stable identifiers - does the source system expose a stable, unique id per invoice and per customer that survives edits? What are they?
  2. Corrections - how does the source system represent corrective documents, and are their amounts the new corrected totals, the delta, or “before/after”? (§3.1.2)
  3. Partial payments - can amountPaid / amountOutstanding be provided, or only a binary paid flag?
  4. Document types - which document kinds exist and which are collectible; mapping of any kinds not listed in §3.1.1. Should proformas be excluded?
  5. Multi-company - can one installation hold several legal entities/sellers? If so, how is the seller disambiguated?
  6. Currencies - are multi-currency invoices expected?
  7. Volumes - expected daily and peak invoice counts.
  8. Formats - confirm UTF-8, dot decimals, ISO-8601 (including time-zone handling for dates), and phone numbers with country code can be guaranteed (§6).
  9. PDF attachments - yes or no? Should Sunbay attach invoice documents to reminder emails? Only if yes: PDF availability, maximum size, and PDFs for corrective documents (§3.7).

Option A

  1. API base URL, credential exchange and rotation procedure; chosen authentication method (§7.2).
  2. Your rate limits and maintenance windows.
  3. Initial load depth - how far back paid invoices are exposed (e.g. all open, plus paid within N months).
  4. lastModifiedAt semantics - which changes bump it, and with what precision?
  5. Test/sandbox environment availability.
  6. Poll schedule - incremental interval and full-snapshot cadence (§9).

Option B

  1. Acknowledgment - do you want to read back per-invoice/per-batch results? If so: response bodies, error/duplicate signalling, and the retry tie-in (§5.5).
  2. Push frequency and backfill mechanics (bulk file vs per-invoice) (§5.2, §9).
  3. Chosen authentication method (§7.3) and its feasibility from your environment.