Skip to main content

Bilko HR eRačun — sveRačun (PostLink) Integration & Status Model

Overview

Provider: sveRačun by PostLink d.o.o. (Velika Gorica, HR).
Contact: David Krišto [email protected], Ivan Jurić [email protected].
API docs: https://sveracun-public-api.redocly.app/

Replaces the abandoned Storecove plan (MC #8675, not approved). CEO accepted sveRačun partnership 2026-06-11.

Current state: adapter MERGED to main, GATED/DISABLED (SVERACUN_HR_LIVE=false, adapter_config sveracun-hr-fisk enabled=FALSE). Live activation pending (MC #103443).


API

OperationEndpointNotes
Submit documentPOST https://test.sveracun.hr/api/rest/v1/documents/sendAuth header: Authorization: <raw-api-key> (apiKey scheme, NOT Bearer). Body: raw UBL 2.1 XML (application/octet-stream). Response: {"documentId":"<hex>"}. PROD base URL differs from TEST.
Internal statusPOST /rest/v1/documents/getInternalStatusPoll only — no webhook.
External statusPOST /rest/v1/documents/getExternalStatusProvider also references documents/getStatus.

Two-Stage Processing (per David Krišto / PostLink)

Etapa 1 — Basic parse: the initiator OIB (the OIB that calls send, tied to the API key) MUST equal the sender OIB inside the UBL XML, plus recipient/document-type/process checks. Mismatch results in status FAILED.

Etapa 2 — Full routing: validation vs Porezna uprava validator; recipient access-point lookup; SBD preparation; AS4 exchange (waits 5 min for recipient access point; on unavailability retries up to 24× every 30 min); outbound fiscalization; archiving.


Status Model (Authoritative — correct as of 2026-06-11)

Internal statuses

StatusMeaning
NEWInbound-only — document available to pick up.
OKProcessed successfully by sveRačun.
FAILEDProcessing interrupted (e.g. sender OIB mismatch, parse error).
UNKNOWNCurrently being processed.
UNDELIVERABLERecipient not registered in AMS (access-point lookup failed).

External (fiscalization) statuses

StatusMeaning
FISCALIZATION:OKFiscalization succeeded.
FISCALIZATION:ERRORFiscalization failed.
nullNot yet forwarded to fiscalization.
FISCALIZATION_PAYMENT_REPORT:OK|ERRORPayment report fiscalization result.
FISCALIZATION_REJECTION_REPORT:OK|ERRORRejection report fiscalization result.
FISCALIZATION_NOT_DELIVERED_REPORT:OK|ERRORNot-delivered report fiscalization result.

Bilko decision: composite outcome classification

OutcomeCondition
SUCCESSinternal = OK AND external = FISCALIZATION:OK
FAILUREinternal = FAILED | UNDELIVERABLE, OR external = FISCALIZATION:ERROR | any REJECTION_REPORT | any NOT_DELIVERED_REPORT
PENDINGinternal = UNKNOWN | NEW, OR external = null

How do we know the invoice arrived? Poll until external status is FISCALIZATION:OK (success) or any *_REPORT/ERROR terminal state (failure). There is NO webhook from sveRačun.


Implementation

Source files

  • apps/api/src/main/kotlin/no/alai/bilko/country/hr/SveRacunHttpClient.kt — HTTP client (submit, getInternalStatus, getExternalStatus).
  • apps/api/src/main/kotlin/no/alai/bilko/country/hr/SveRacunHrEInvoiceAdapter.kt — serialize, submit, pollStatus; unified mapStatusPair(internal, external) logic.
  • PluginHR.ktEINVOICE_SUBMIT = BETA, gated by SVERACUN_HR_LIVE flag.
  • db/migrations/V74__sveracun_adapter_config.sql — Flyway migration; registers adapter_config record sveracun-hr-fisk.

Key implementation detail

serialize() forces UBL AccountingSupplierParty OIB to equal SVERACUN_SENDER_VAT (e.g. HR91276104352). If this env var is unset the method is fail-closed (throws before submitting). This prevents Etapa-1 sender-OIB mismatch failures.

Configuration & secrets

VariablePurposeWhere stored
SVERACUN_API_KEYAPI authentication (raw key, not Bearer)GCP Secret: bilko-sveracun-test-api-key (TEST); separate PROD secret to be provisioned.
SVERACUN_BASE_URLBase URL (test vs prod differs)Cloud Run env
SVERACUN_SENDER_VATSender OIB for UBL XML + Etapa-1 initiator matchCloud Run env
SVERACUN_HR_LIVEFeature gate (false = adapter disabled)Cloud Run env

SECURITY: Never commit or log the actual API key value. Always retrieve from GCP Secret Manager at runtime.

PRs & tests

  • PR #346 — initial integration.
  • PR #348 — status-model correction (MC #103445).
  • 42 unit tests: SveRacunHrEInvoiceAdapterTest.

Verification

Proveo independent PASS — live TEST submit returned HTTP 200, internalStatus=UNKNOWN (processing) after Etapa-1 sender-OIB fix. Prior FAILED result was caused by sender/initiator OIB mismatch before the serialize() fix. Evidence: /tmp/evidence-103445/.


Activation Checklist (MC #103443 — NOT yet done)


  • MC #103434 — sveRačun integration (build).
  • MC #103445 — Corrected status model (PR #348).
  • MC #103443 — Live activation (pending — do NOT mark done until activation checklist complete).
  • MC #8675 — Abandoned Storecove plan (not approved; superseded).

Document Metadata

  • Author: ALAI / Skillforge
  • Created: 2026-06-11
  • Status: LIVE REFERENCE — update when activation checklist progresses or API contract changes.