Subiekt Nexo ERP
Sync orders and stock with Subiekt nexo
Subiekt nexo by Koda Plus
Connect Medusa to Subiekt nexo PRO (InsERT), the most common ERP of Polish shops. Orders become ZK documents in Subiekt seconds after checkout, the WZ the warehouse issues comes back to the order, the invoice (FS) or receipt (PA) is issued in Subiekt with its KSeF number shown on the order, company buyers land on their own contractor by NIP, and stock and prices flow from Subiekt to Medusa. Your team keeps working in Subiekt; Medusa stays the storefront. Nothing new is written anywhere until a person allows it.
Live demo: Medusa admin medusa.koda.plus/app/subiekt, signed in to a public demo account by the link itself. The demo runs the plugin with its simulated bridge, so every screen has data, including the setup guide at Copy to clipboard?view=guide.
How it works
Subiekt nexo has no web API. Its SDK, Sfera, is a Windows .NET library that runs next to the Subiekt database. So the integration has two parts that talk over one signed, documented HTTP contract:
1234567Medusa (anywhere) Windows machine next to Subiekt+----------------------------+ HTTPS +----------------------------+ Sfera SDK +------------------+| this plugin | --------> | bridge (Windows service) | ----------> | Subiekt nexo PRO || task queue, plans, | signed | contract/openapi.yaml | | SQL Server || writers, admin, guide | <-------- | event feed, WZ and KSeF | +------------------++----------------------------+ webhook | watchers |+----------------------------+
- This plugin (MIT) is everything on the Medusa side: when to send an order, retries, plans, writers, the admin and the setup guide.
- The bridge implements Copy to clipboard
contract/openapi.yaml(version 1.1.0). Koda Plus builds and runs a production bridge on the Sfera SDK (commercial, see The bridge); any bridge that follows the contract works, and the plugin ships a demo bridge so you can evaluate everything without Subiekt.
The bridge usually sits behind a Cloudflare Tunnel, so the Subiekt machine opens no inbound port. The plugin reads what the bridge can do from Copy to clipboardcapabilities in Copy to clipboardGET /v1/health and uses only that, so you can update the plugin before the bridge: a contract 1.0 bridge keeps doing orders, WZ, stock and events, and the admin says what needs the update.
What it syncs
- Orders to ZK (zamówienie od klienta): Medusa to Subiekt, on Copy to clipboard
order.placed. Prepaid orders (card, BLIK, Przelewy24, PayU...) wait for the capture first, so the warehouse never packs an order that may still fail to pay. Lines are matched by EAN first, then SKU against the product symbol, with the gross price the customer paid. - Company buyers by NIP (new in 0.2.0): the plugin finds the buyer's NIP where your checkout keeps it (Copy to clipboard
nipSources), checks its checksum and sends it with the order. The bridge issues the ZK to the contractor with that NIP and, when allowed, creates a missing one, never a second one for the same NIP. An invalid NIP goes to the retail buyer with a warning in the admin. - Cancellations: Medusa to Subiekt, on Copy to clipboard
order.canceled. Refused once a WZ or a sales document exists. Sfera cannot set every ZK status, so the bridge marks what it can and the admin says honestly when someone must finish it in Subiekt. - WZ issued in the warehouse: Subiekt to Medusa, through the bridge event feed. The WZ number lands in the order metadata, the plugin emits Copy to clipboard
subiekt.document_issued, and with Copy to clipboardfulfillOnWzit creates the Medusa fulfillment. - WZ from Medusa fulfillments (optional, Copy to clipboard
issueWzOnFulfillment): Medusa to Subiekt. - Sales documents with KSeF (new in 0.2.0, Copy to clipboard
salesDocument): the FS or PA of each order, issued in Subiekt after the WZ (or right after the ZK), exactly once. The KSeF number appears on the order and in the admin as soon as Subiekt has sent the e-invoice. - Stock: Subiekt to Medusa, every 10 minutes, into the inventory levels of one stock location.
- Products and prices (new in 0.2.0): Subiekt to Medusa, every hour, planned first. Prices of one Subiekt price level go to the variant prices or to a price list; Subiekt products meant for the online shop and missing in Medusa can become draft products.
Features
- Write safety. Every write added in 0.2.0 (prices, new products, sales documents, new contractors) has two switches: its option in Copy to clipboard
medusa-config.ts(false wins, the admin cannot override it) and a writer a person arms in the admin, recorded with who and when. All of them ship off. - Plan first. Prices and new products are computed as a plan (what changes, from what to what) and shown in the admin before anything is written. An incomplete read from the bridge plans nothing. Each run applies at most Copy to clipboard
maxPriceChangesPerRunprices and Copy to clipboardmaxProductsPerRunproducts, reads every item again right before it writes, skips what changed meanwhile, and quarantines an item that failed three runs in a row until a person releases it. - Exactly once. One task row per order and operation before anything goes to the network, claimed atomically. The bridge writes the order tag Copy to clipboard
[medusa:order_...]into every document and looks for it before it creates one, under the order lock and again under the Sfera lock. An unclear answer (a timeout) becomes "Answer unclear" and the next attempt asks the bridge first. - Outbox with retries. Every call to the bridge is a row first and a request second, retried with backoff for about two and a half days, so a bridge machine switched off over a weekend loses nothing. A task fails for good only on a non-retryable error, and then it waits in the admin with a Send again button.
- Setup guide in the admin ("Panel" | "Setup guide", Copy to clipboard
?view=guide), in English and Polish: what you need, how the parts talk, twelve steps from an empty Windows machine to production with live states, a go-live checklist ticked from the live status, and troubleshooting from real failure modes. The same guide as Markdown: docs/guide-en.md, docs/guide-pl.md. - Bridge diagnostics: bridge, contract, nexo SDK and database versions, the Subiekt licence state, round trip, clock skew (signatures fail beyond five minutes, the admin warns from one), the result of the last signed request, the last event, what the bridge can do and what it cannot yet, with the reason and the setting to change.
- Admin page with the connection, the writers, the stock plan, the products and prices plan with filters and quarantine, the queue, documents (ZK, WZ, FS, PA with KSeF numbers) and the history of background runs. "Running in production" cards from the Copy to clipboard
referencesoption. - Order widget: the ZK, WZ and FS or PA of the order with the KSeF number, the contractor Subiekt got, warnings, Send to Subiekt now and Issue invoice or Issue receipt.
- Safe stock sync. Ambiguous matches (one EAN on two products, one inventory item pulled two ways) are reported and never written. Products missing from a reading are never zeroed. Kit components are matched by their own SKU. Copy to clipboard
stockDryRunrecords the plan without writing. - Signed both ways. HMAC-SHA256 over timestamp, method, path and raw body, with secret rotation and a 5 minute window. Optional Cloudflare Access service token.
- Demo mode. A simulated bridge inside Medusa: ZK numbers in seconds, a WZ about three minutes later, FS or PA after it with a KSeF number two minutes later, contractors by NIP, stock and prices computed from your catalog (with price levels and a few EAN conflicts), health with every capability and a small clock skew. Writers armed in the demo only simulate.
- Workflows included, in the spirit of the Medusa ERP recipe: Copy to clipboard
sendOrderToSubiektWorkflow, Copy to clipboardcancelOrderInSubiektWorkflow, Copy to clipboardcreateSubiektWzWorkflow, Copy to clipboardissueSubiektDocumentWorkflow, Copy to clipboardsyncSubiektStockWorkflow, Copy to clipboardsyncSubiektProductsWorkflow, Copy to clipboardpullSubiektEventsWorkflow, Copy to clipboardcheckSubiektConnectionWorkflow, Copy to clipboardprocessSubiektTasksWorkflow.
Requirements
- Medusa 2.12 or newer (tested on 2.15.3), Node.js 20+.
- For a real Subiekt: Subiekt nexo PRO (it includes "Sfera dla Subiekta nexo"; the separate Sfera PRO+ module is not needed), the nexo SDK of the same version as your Subiekt database, and a Windows machine that runs all the time with access to the nexo SQL Server, .NET 8 SDK and the bridge. Contract 1.1 features need bridge 0.2.0 or newer.
Installation
1npm install @koda-plus/medusa-plugin-subiekt-nexo
Add the plugin to Copy to clipboardmedusa-config.ts:
1234567891011121314module.exports = defineConfig({// ...plugins: [{resolve: "@koda-plus/medusa-plugin-subiekt-nexo",options: {bridgeUrl: process.env.SUBIEKT_BRIDGE_URL, // https://subiekt-bridge.your-shop.plsecret: process.env.SUBIEKT_SECRET, // the same value as Bridge:SecretstockDryRun: true, // plan stock first// demo: true, // simulated bridge, no Subiekt needed},},],})
Generate the shared secret with Copy to clipboardopenssl rand -hex 32 and put the same value in the bridge configuration. Then run the migrations and open Subiekt nexo in the admin sidebar:
1npx medusa db:migrate
Options
Connection:
- Copy to clipboard
bridgeUrl: base URL of the bridge. Use an origin; a path prefix must reach the bridge unchanged. - Copy to clipboard
secret: shared HMAC secret, 16 characters at least, 64 hex characters recommended. - Copy to clipboard
previousSecret: accepted on incoming webhooks while you rotate the secret. - Copy to clipboard
cfAccessClientId, Copy to clipboardcfAccessClientSecret: Cloudflare Access service token, when the tunnel is protected by Access. - Copy to clipboard
timeoutMs(default Copy to clipboard30000): one bridge request. - Copy to clipboard
demo(default Copy to clipboardfalse): the simulated bridge.
Orders and WZ:
- Copy to clipboard
prepaidProviders(default: Stripe, Przelewy24, PayU, Tpay, PayPal, Adyen, Mollie prefixes): payment providers whose orders wait for the capture. Prefix match on the provider id. - Copy to clipboard
codProviders(default Copy to clipboardpp_cod, Copy to clipboardpp_cash): providers meaning cash on delivery. - Copy to clipboard
issueWzOnFulfillment(default Copy to clipboardfalse): a Medusa fulfillment asks the bridge for a WZ. - Copy to clipboard
fulfillOnWz(default Copy to clipboardfalse): a WZ from Subiekt creates the Medusa fulfillment for the remaining items. - Copy to clipboard
eventsEnabled(default Copy to clipboardtrue): read the bridge event feed. - Copy to clipboard
omitLinesWithoutCode(default Copy to clipboardfalse): leave lines without EAN and SKU (services, gift cards) off the ZK instead of failing the order. - Copy to clipboard
forwardMetadataKeys(default none): order metadata passed to the bridge.
Buyers and sales documents (0.2.0):
- Copy to clipboard
nipSources(default: Copy to clipboardmetadata.tax_id, Copy to clipboardmetadata.nip, Copy to clipboardmetadata.vat_id, Copy to clipboardmetadata.invoice_nip, Copy to clipboardmetadata.company_tax_id, the same keys under Copy to clipboardbilling_address.metadata., then Copy to clipboardbilling_address.company): where to look for the buyer's NIP, in this order. A NIP failing the checksum is reported, never sent. - Copy to clipboard
taxIdMetadataKeys: the 0.1.0 way to name the metadata keys; when set and Copy to clipboardnipSourcesis not, the sources are built from it. - Copy to clipboard
createContractors(default Copy to clipboardfalse, Copy to clipboardtruein demo mode): hard switch of the contractors writer; lets the bridge create a contractor that does not exist yet. The bridge must allow it too (Copy to clipboardBridge:Subiekt:BuyerModeCopy to clipboardcustomer, Copy to clipboardBridge:Subiekt:CreateContractorsCopy to clipboardtrue). - Copy to clipboard
salesDocument(default Copy to clipboard"none", Copy to clipboard"auto"in demo mode): Copy to clipboard"fs"(always an invoice), Copy to clipboard"pa"(always a receipt), Copy to clipboard"auto"(FS with a valid NIP, PA otherwise) or Copy to clipboard"none". The hard switch of the documents writer. - Copy to clipboard
salesDocumentAfter(default Copy to clipboard"wz"): issue the sales document after the WZ (the goods left) or right after the ZK (Copy to clipboard"zk").
Stock:
- Copy to clipboard
stockSyncEnabled(default Copy to clipboardtrue), Copy to clipboardstockLocationId(optional when the store has one location), Copy to clipboardstockField(Copy to clipboardquantity, physical, default, or Copy to clipboardavailable, minus ZK reservations), Copy to clipboardstockDryRun(default Copy to clipboardfalse). - Copy to clipboard
stripSkuSuffixes(default none): SKU suffixes removed before matching stock, for example Copy to clipboard["-WH"]for wholesale variants of one Subiekt product. Not used for prices.
Products and prices (0.2.0):
- Copy to clipboard
productSyncEnabled(default Copy to clipboardtrue): read products and prices every hour and plan. Read only. - Copy to clipboard
priceLevel(default: the first level the bridge publishes): the Subiekt price level (symbol or name) the prices come from. - Copy to clipboard
priceType(default Copy to clipboard"gross"): Copy to clipboard"gross"or Copy to clipboard"net". - Copy to clipboard
priceCurrency(default Copy to clipboard"pln"): the currency written; a level in another currency plans nothing. - Copy to clipboard
priceTarget(default Copy to clipboard"variant"): the variant's own price, or Copy to clipboard"price_list"with Copy to clipboardpriceListId(Copy to clipboardplist_...). - Copy to clipboard
priceWriter(default Copy to clipboardfalse, Copy to clipboardtruein demo mode): hard switch of the price writer. - Copy to clipboard
maxPriceChangesPerRun(default Copy to clipboard200). - Copy to clipboard
createMissingProducts(default Copy to clipboardfalse, Copy to clipboardtruein demo mode): hard switch of the product creator. Subiekt products meant for the online shop ("Sklep internetowy"), with a price in the level and missing in Medusa become draft products with one variant. - Copy to clipboard
maxProductsPerRun(default Copy to clipboard20).
Admin:
- Copy to clipboard
references: stores that run the integration in production, shown as cards under the counters and at the end of the guide: Copy to clipboard[{ name, url, description?, metrics?: [{ label, value }], links?: [{ label, url }], soon? }], every text either a string or Copy to clipboard{ en, pl }. Copy to clipboardsoon: truemarks a store that starts on Medusa soon: it is shown with a "Soon" badge and no link, and its Copy to clipboardurlis optional. Entries without a name, or live entries without an https URL, are dropped.
Missing options never break the boot: the module registers, the admin lists what is missing, and nothing is queued until the plugin is configured, so a store configured a week after installing does not flood Subiekt with a week of old orders. In demo mode the 0.2.0 hard switches default to on, because the writers only touch the simulation there; nothing is armed until a person arms it, except the documents and contractors writers the demo arms once as "demo (automatic)".
Setup in brief
The full guide with live states is in the admin (Copy to clipboard/app/subiekt?view=guide) and in docs/guide-en.md.
- Subiekt nexo PRO: an operator for the bridge, the warehouse for new ZK, the retail buyer and its NIP, the price level to publish; note the exact Subiekt version.
- nexo SDK and .NET 8 on a Windows machine that runs all the time next to the database; the SDK version must equal the database version.
- The bridge as a Windows service: Copy to clipboard
deploy\install-service.ps1 -ServiceUser "SERWER\integracja", fill in Copy to clipboardappsettings.Local.json, run it again (it runs Copy to clipboard--checkbefore it creates the service). - Cloudflare Tunnel: Networking, Tunnels, Create a tunnel; route a published application to Copy to clipboard
http://127.0.0.1:5280. - Cloudflare Access (optional): a service token and a Service Auth policy; set Copy to clipboard
cfAccessClientIdand Copy to clipboardcfAccessClientSecret. - The plugin: Copy to clipboard
bridgeUrl, Copy to clipboardsecret, Copy to clipboardstockDryRun: true, every writer off; Copy to clipboardnpx medusa db:migrate. - Check connection: versions, licence, signatures accepted, clock skew under a minute.
- Read stock and products: review the stock plan, unmatched codes and the price plan.
- Test order: the ZK in seconds, the WZ issued from it comes back.
- Invoices, receipts, contractors: Copy to clipboard
salesDocument, Copy to clipboardnipSources, Copy to clipboardcreateContractors, arm the writers. - Prices and new products: Copy to clipboard
priceWriter, Copy to clipboardcreateMissingProducts, read the plan, arm the writers. - Go live: Copy to clipboard
stockDryRun: false, the bridge webhook, alerts on Copy to clipboardsubiekt.task_failed, the go-live checklist complete.
The order lifecycle
- Copy to clipboard
order.placed: the order gets an Copy to clipboardorder.createtask. Due at once for cash on delivery, bank transfer, trade credit and manual payments; waiting for prepaid providers until Copy to clipboardpayment.captured. - The queue sends it right away (the scheduled job every minute is the safety net and the retry clock). The bridge matches the lines, finds or creates the contractor for a company buyer, and creates the ZK; the plugin stores it, writes Copy to clipboard
subiekt_zk_numberinto the order metadata and emits Copy to clipboardsubiekt.document_issued. - The warehouse issues the WZ from the ZK in Subiekt. The bridge watcher announces it in the event feed (and nudges Medusa through Copy to clipboard
POST /hooks/subiekt); the plugin writes Copy to clipboardsubiekt_wz_numberand, with Copy to clipboardfulfillOnWz, fulfills the order. - With Copy to clipboard
salesDocumentset and the documents writer armed, the WZ (or the ZK, with Copy to clipboardsalesDocumentAfter: "zk") queues the Copy to clipboardorder.documenttask: the bridge issues the FS or PA realizing the WZ (or the ZK), the plugin writes Copy to clipboardsubiekt_sales_document_numberand Copy to clipboardsubiekt_sales_document_kind. When Subiekt has sent the e-invoice, the bridge publishes Copy to clipboarddocument.updatedwith the KSeF number; the plugin writes Copy to clipboardsubiekt_ksef_numberand emits Copy to clipboardsubiekt.document_updated. - Copy to clipboard
order.canceled: if the ZK was never attempted, the queued create is simply canceled; otherwise the bridge cancels the ZK, or refuses with Copy to clipboarddocument_lockedonce a WZ or a sales document exists.
There is deliberately no compensation that deletes a document. The ERP recipe compensates a remote create by deleting the remote record; here the bridge is idempotent per order, so a retry after a local failure gets the same document back, while a deleted ZK or invoice would leave a hole in the number series and might already be on the warehouse's desk or in KSeF.
Products and prices from Subiekt
- Every hour (or on Read products) the plugin reads Copy to clipboard
GET /v1/productspage by page from one bridge snapshot. A read that did not reach the last page plans nothing. - Each Medusa variant finds its Subiekt product by EAN (Copy to clipboard
ean, Copy to clipboardbarcodeor Copy to clipboardupc), then by SKU equal to the symbol, case-insensitive. SKU suffixes are not stripped here: a wholesale Copy to clipboard-WHvariant keeps its own price. One EAN on two Subiekt products is a conflict and never guessed. - The price of the configured level (net or gross, in Copy to clipboard
priceCurrency) is compared with the current one in the target (the variant's plain price without rules or quantities, or the price list price). Equal amounts are left alone. - The plan is stored and shown in the admin. Only an armed price writer applies it, through Copy to clipboard
upsertVariantPricesWorkflow(sending back every existing price of the variant, so other currencies and region prices stay intact) or Copy to clipboardbatchPriceListPricesWorkflow. - Subiekt products with the "Sklep internetowy" flag, a price in the level, not a kit, and no match in Medusa become creation candidates. An armed product creator makes them draft products with one variant (SKU = symbol, EAN, weight); a person adds images and a sales channel and publishes.
The bridge
Copy to clipboardcontract/openapi.yaml (1.1.0) is the whole contract: Copy to clipboardGET /v1/health (with Copy to clipboardcapabilities, versions, licence, last event, queue sizes and server time), Copy to clipboardPOST /v1/orders (optional Copy to clipboardbuyer block), Copy to clipboardGET /v1/orders/{id}, Copy to clipboardPOST /v1/orders/{id}/cancel, Copy to clipboardPOST /v1/orders/{id}/fulfillments, Copy to clipboardPOST /v1/orders/{id}/documents (FS or PA, idempotent), Copy to clipboardGET /v1/stock, Copy to clipboardGET /v1/products, Copy to clipboardGET /v1/events, and the webhook Copy to clipboardPOST /hooks/subiekt. Version 1.1 is additive: a 1.0 bridge keeps working with this plugin. Request and response examples and cross-language signature test vectors live in Copy to clipboardcontract/examples.
Koda Plus provides a production bridge for Subiekt nexo PRO: a Windows service on .NET 8 and the Sfera SDK, with a dedicated Sfera thread (no desktop heap exhaustion after days of uptime), incremental WZ and KSeF watchers, a SQLite event feed, install, upgrade and uninstall scripts, a read-only Copy to clipboard--check and a local status page. It is available commercially from Koda Plus, write to kontakt@koda.plus. You can also build your own bridge from the contract.
Stock matching
- Each Subiekt product is indexed by EAN (digits only, 8 to 14) and by symbol (case-insensitive).
- A variant that manages inventory with exactly one inventory item finds its product by EAN (Copy to clipboard
ean, Copy to clipboardbarcodeor Copy to clipboardupcof the variant), then by SKU against the symbol, after removing Copy to clipboardstripSkuSuffixes. - Inventory items of kits get a second chance by their own SKU.
- A duplicated EAN in Subiekt, or one inventory item matched to two products with different stock, is a conflict: reported in the admin, never written.
- Only matched items are written, through Medusa's Copy to clipboard
batchInventoryItemLevelsWorkflow. Negative Subiekt stock becomes 0.
Admin API
- Copy to clipboard
GET /admin/subiekt: connection, bridge diagnostics, writers, counters, the last run of each kind, references. Reads the database only. - Copy to clipboard
POST /admin/subiekt/check: Copy to clipboardGET /v1/healthnow. - Copy to clipboard
POST /admin/subiekt/syncwith Copy to clipboard{ "what": "stock" | "events" | "tasks" | "products" }: run a job now (202, background). - Copy to clipboard
POST /admin/subiekt/writerswith Copy to clipboard{ "writer": "prices" | "products" | "documents" | "contractors", "armed": true | false }: arm or disarm a writer (recorded with the admin user). - Copy to clipboard
GET /admin/subiekt/products?kind=price|create&status=&q=: the product and price plan; Copy to clipboardPOST /admin/subiekt/products/releasewith Copy to clipboard{ "id" }: release a quarantined item. - Copy to clipboard
GET /admin/subiekt/tasks?filter=attention|open|done|all&q=, Copy to clipboardPOST /admin/subiekt/tasks/:id/retry. - Copy to clipboard
GET /admin/subiekt/documents?kind=ZK|WZ|FS|PA&q=, Copy to clipboardGET /admin/subiekt/runs?kind=. - Copy to clipboard
GET /admin/subiekt/orders/:id, Copy to clipboardPOST /admin/subiekt/orders/:id/send, Copy to clipboardPOST /admin/subiekt/orders/:id/documentswith Copy to clipboard{ "kind"?: "fs" | "pa" }(needs Copy to clipboardsalesDocumentother than Copy to clipboardnone). - Copy to clipboard
POST /hooks/subiekt: the bridge webhook. Public, signed.
There is no DELETE route: nothing in the admin removes data.
Use it from your code
12345678910import { sendOrderToSubiektWorkflow, issueSubiektDocumentWorkflow } from "@koda-plus/medusa-plugin-subiekt-nexo/workflows"const { result } = await sendOrderToSubiektWorkflow(container).run({input: { order_id: "order_01J..." },})// result.document.number === "ZK 128/MAG/2026"await issueSubiektDocumentWorkflow(container).run({input: { order_id: "order_01J...", kind: "fs", reconcile: true },})
Subscribe to Copy to clipboardsubiekt.document_issued (Copy to clipboard{ order_id, kind, number, status, source }) to react to a WZ or an invoice, for example to send the shipping e-mail, to Copy to clipboardsubiekt.document_updated for the KSeF number, and to Copy to clipboardsubiekt.task_failed to alert your team.
How this maps to the Medusa ERP recipe
- ERP module with a client: the Copy to clipboard
subiekt_nexomodule, Copy to clipboardHttpBridgeClient, Copy to clipboardDemoBridge. - Sync orders to the ERP on Copy to clipboard
order.placed: the Copy to clipboardsubiekt-order-placedsubscriber, the outbox, Copy to clipboardsendOrderToSubiektWorkflow. - Restrict purchase by ERP data: stock into inventory levels; Medusa's own inventory checks do the rest.
- Sync from the ERP via webhook: the signed Copy to clipboard
POST /hooks/subiektplus the cursor-based event feed. - Scheduled product sync job: Copy to clipboard
subiekt-sync-stock(stock, every 10 minutes) and Copy to clipboardsubiekt-sync-products(prices and missing products, hourly, plan first).
What this plugin does not do
- No payments on sales documents. The FS or PA takes its payment method and term from Subiekt (the document defaults, or what it copies from the WZ or ZK); the online payment is not booked as a settlement in Subiekt. The ZK notes describe the payment in words.
- No fiscalization and no KSeF sending. Subiekt prints receipts on its fiscal printer and sends e-invoices to KSeF; the bridge only reads the KSeF number back.
- No partial WZ and no corrections. A WZ from Medusa releases the whole ZK; returns, corrections (KWZ, FSK) and partial shipments are handled in Subiekt.
- No full product sync. Prices of one level go to one target; new products are minimal drafts (title, SKU, EAN, weight, price). Descriptions, images, categories, attributes and customer group prices stay in Medusa. Nothing goes from Medusa to the Subiekt product catalog.
- No unattended contractor changes. The bridge creates a contractor only when none has the NIP and both switches allow it; it never edits or merges existing contractors.
- No Unieważnione status. Sfera cannot set it; the bridge marks the ZK and a person sets the status.
- No bridge without Windows. Sfera is a Windows .NET library; the bridge needs a Windows machine with access to the nexo SQL Server, and one bridge serves one Subiekt company database.
Security and data
- Every request is signed in both directions; a captured request cannot be replayed against another endpoint or after five minutes.
- Secrets live only in the plugin options and are masked in every stored error.
- The admin never calls the bridge while rendering; network calls sit behind explicit actions and jobs.
- Stored data: documents, tasks, plans and counters; about buyers only the order id and number, and for company buyers the NIP and the name of the Subiekt contractor that got the ZK (shown in the queue and on the order). The buyer block sent to the bridge (NIP, company, address, e-mail, phone) is used to find or create the contractor and is not stored by the plugin. The writers record the admin user who armed them.
Roadmap
- Partial WZ and corrections (KWZ) for returns.
- Payments on sales documents (settlement of online payments).
- Customer group prices from further Subiekt price levels.
License
MIT, see LICENSE. Built and maintained by Koda Plus.
Subiekt nexo, nexo PRO and Sfera are trademarks of InsERT S.A. This project is independent and not affiliated with InsERT.
Changelog
0.2.1 (2026-10-07)
- References: stores that start soon on Medusa can be listed with Copy to clipboard
soon: true(a Soon badge, no link, Copy to clipboardurloptional); the since date is no longer shown, and an old Copy to clipboardsincein the options is ignored.
0.2.0 (2026-10-06)
- Contract 1.1.0, additive: Copy to clipboard
capabilitiesand versions in Copy to clipboard/v1/health, Copy to clipboardGET /v1/products, the Copy to clipboardbuyerblock of an order, Copy to clipboardPOST /v1/orders/{id}/documents(FS or PA, idempotent), Copy to clipboardksef_numberon documents and the Copy to clipboarddocument.updatedevent. The plugin feature-detects every one of them. - Products and prices from Subiekt, plan first: EAN then SKU matching, price level, net or gross, variant prices or a price list, optional draft products, per-run caps, re-read before write, quarantine after three failed runs.
- Contractors by NIP: Copy to clipboard
nipSources, checksum validation, existing contractor or (allowed) a new one, invalid NIP to the retail buyer with a warning. - Sales documents: Copy to clipboard
salesDocument(Copy to clipboardnone, Copy to clipboardfs, Copy to clipboardpa, Copy to clipboardauto) and Copy to clipboardsalesDocumentAfter, exactly once with an atomic claim and reconciliation of unclear answers; KSeF numbers on the order, in the documents view and in the order metadata. - Writers: every new write has an option (hard switch) and an admin toggle recorded with who and when; all off by default.
- Admin: "Panel" | "Setup guide" switch, the bridge diagnostics section, writers, the products and prices plan, FS and PA with KSeF in the documents view and the order widget, "Running in production" references (Copy to clipboard
referencesoption). - Setup guide in English and Polish, in the admin with live states and as docs/guide-en.md and docs/guide-pl.md.
- Demo bridge simulates all of it from the store catalog.
- Bridge fix worth knowing: bridge 0.1.0 ignored Copy to clipboard
address_1and Copy to clipboardaddress_2of the order addresses (it expected Copy to clipboardaddress1), so ZK notes lacked the street; bridge 0.2.0 reads the contract names.
0.1.0 (2026-10-05)
First release: contract 1.0.0, orders to ZK, cancels, WZ both ways, stock sync with dry run, signed webhook, the outbox queue, the admin page and order widget in English and Polish, the demo bridge. See CHANGELOG.md.
