work/Backend · Integration

Pantheon Middleware

A production-grade integration service that connects a webshop to the Pantheon ERP - with automated Croatian fiscalization and invoice delivery by email. From order to fiscalized invoice, with no manual step.

Role

Backend architecture · integration build · delivery

Stack

NestJS · BullMQ · PostgreSQL · MS SQL Server

Year

2026

Status

In production

architecture · forward-only
SourceWebshop
canonical JSON
Process 01HTTP Receiver
202 · enqueue
BrokerRedis Queue
job
Process 02Worker
stored procs
ERPPantheon
└▶
FINAFiscalization · ZKI / JIR
headless Chromium
DocumentInvoice PDF
SMTP email
RecipientCustomer
0HTTP Accepted - instant ack, async work
0Independent processes, one codebase
0Manual steps: order → fiscalized invoice in the customer's inbox
The challenge

What it needed to solve.

In most installations a webshop and the Pantheon ERP are two separate worlds. Orders get re-keyed by hand, invoices are issued manually, and Croatian fiscalization - a legal requirement - either sits outside the flow or is handled by a separate tool.

The result is familiar: a lag between order and invoice, re-keying errors, and a dependency on someone running the same sequence of steps every day.

What was needed was a production-grade service that takes an order from the webshop and carries it all the way to a fiscalized invoice emailed to the customer - reliably, repeatably, and without anyone touching it.

Our approach

How we built it.

We built a forward-only integration service: the webshop sends orders in one direction and the middleware does the rest. A clean contract on the front, safe writes and fiscalization on the back - simple to reason about, hard to knock over.

  • Our own API contract. The middleware defines the order format, not the other way round. Canonical JSON published as an OpenAPI/Swagger spec, with Zod/DTO validation at the edge and example requests. The webshop integrates against a stable, documented, versioned interface - no adapters, no guesswork, no surprises later.
  • Safe ERP writes. Every write goes through Pantheon stored procedures - never a direct INSERT into ERP tables. Writes are wrapped in transactions, document numbering stays owned by the ERP, and access runs through a dedicated integration user with least privilege. The ERP never ends up in an inconsistent state because of the integration.
  • Croatian fiscalization, built in-house. ZKI generation, digitally signed XML (XML-DSig), exchange with FINA's service, JIR retrieval and a QR code on the invoice. No intermediary, no third-party fiscalization service. The demo → production certificate cutover is run as a controlled, documented procedure.
  • Automated invoicing. PDF invoices rendered by headless Chromium from templates, carrying the fiscal data and QR code, delivered to the customer by email over SMTP - with internal BCC copies.
  • Resilient & idempotent. A durable job queue with retries and exponential backoff. Order-level idempotency - the same order sent twice never creates two documents. Crash-safe state tracking, dead-letter handling with re-queueing, and automatic ERP reconnect after a dropped connection.
  • Observable. Structured JSON logging with a correlation ID across the whole request lifecycle - from HTTP request to sent email. Health and readiness probes for every dependency (ERP, database, queue, SMTP) and a job-queue dashboard.
  • Configurable business rules. Discounts, warehouse mapping, digital-item handling, tax rates, invoice templates - all of it is per-environment configuration, not code changes. The same image runs for different clients with different settings.
Architecture

Two processes, one codebase.

The service runs as two independent processes from a single codebase, so each can scale and fail on its own without taking the other down.

Process 01

HTTP Receiver

Authenticates and validates incoming orders, checks for duplicates, enqueues the job and returns 202 Accepted immediately. The webshop never waits on the ERP - an ERP outage doesn't break checkout.

Process 02

Worker

Ensures the customer, syncs the order into Pantheon, runs fiscalization, renders the PDF invoice and sends the email - with retries and backoff at every step, and a dead-letter record when even that doesn't get through.

Local state - idempotency keys, ID correlation between the order and the ERP document, and an audit record of every sync - lives in PostgreSQL. The message broker is Redis. The ERP is the source of truth; the middleware holds no business data, only what it needs to never lose or repeat a job.
Security & handoff

Least privilege, nothing in the clear.

  • Token authentication on incoming requests, rejecting anything that fails the schema.
  • No direct writes into ERP tables; a dedicated integration user instead of an admin account.
  • Secrets and certificates come from the environment only - never in the repository or the image.
  • Source-free delivery: the app is packaged into the image compiled to V8 bytecode, so readable source never reaches the client's infrastructure. Only the image ships.
Hosting

Two ways to host it.

The service ships as a Docker image, so it runs the same anywhere - and the client picks where.

Option 01

On the client's infrastructure

The service runs inside their network, next to Pantheon, without exposing the ERP outward. They get the image, docker-compose configuration and runbooks for deploy, backup and rollback. Data never leaves their environment, and we stay available for support and upgrades.

Option 02

On ours, as a managed service

We run, monitor and maintain the service, with separate production and test environments. The client gets a URL and a token, and never has to think about the server, updates or certificates. All it takes is a secure network path to their Pantheon instance.

Either way it is the same code, API contract and documentation - the only difference is who holds the server. Moving from one option to the other needs no changes to the webshop or the ERP.
The stack

Chosen for reliability.

Runtime / languageNode.js 20+ · TypeScript 5 (strict)
FrameworkNestJS 10
Job queueBullMQ + Redis
State storePostgreSQL + Prisma
ERP accessMS SQL Server - direct TDS, stored procedures
FiscalizationSigned XML (XML-DSig) · node-forge · QR codes
Invoice PDFHeadless Chromium (Puppeteer) + Handlebars templates
EmailSMTP (Nodemailer)
Observabilitypino · Swagger / OpenAPI · Bull Board
DeliveryDocker + Docker Compose
Engineering quality

Built to be handed over.

  • TypeScript strict mode with extra safety flags; typed error classes with cause chains.
  • Unit, integration (against a live Pantheon instance) and end-to-end test suites.
  • Two deployment paths - a self-contained handoff package for external operators, or repo-based deploy with redeploy, backup and rollback tooling.
  • Separate test and production environments, with a demo fiscalization certificate on test.
  • Bilingual (EN / HR) documentation: API spec, technical docs, deploy and go-live runbooks.
Status

Where it stands.

The service is in production. The whole flow runs with no manual steps: order ingest → customer ensure → ERP order & invoice → fiscalization → PDF → email to the customer.

Alongside production there is a separate test environment with demo fiscalization, where integrations are developed and verified before they reach real invoices.

in production · live Pantheon instance
  • order ingest
  • customer ensure
  • ERP order & invoice
  • fiscalization (ZKI / JIR)
  • invoice PDF rendered
  • email delivery
  • containerized + observable
  • production cert cutover
  • separate test environment
Who it's for

Middleware, not a one-off integration.

The service is built as a product, not as a bespoke build for a single client. The contract facing the webshop, the Pantheon access layer and the fiscalization layer are all generic; what differs from client to client - credentials, certificate, warehouses, tax rates, invoice templates, business rules - is environment configuration.

In practice that means onboarding a new Pantheon user comes down to configuration and a check on the test environment, not a new development cycle.

A fit for merchants running Pantheon ERP who want webshop orders to end up as fiscalized invoices without manual work - whatever platform powers the webshop, because the webshop integrates against our published spec.

Next project

Webshop × Pantheon

OPEN FOR NEW PROJECTS

Have a project like this one?

Tell us what you're building. We'll come back within one business day with a clear plan, a timeline, and a real human to talk to.