Invoices, payments and sales
KSeF, payment gateways and what happens to the money after "Pay".
1
KSeF
KSeF is Poland's National e-Invoicing System, through which companies issue and receive structured invoices.
Since 1 February 2026 companies whose 2024 sales exceeded PLN 200 million issue invoices in KSeF, and since 1 April 2026 everyone else. An invoice exists in trade only once KSeF accepts it and gives it a KSeF number.
Invoices can be sent to KSeF by hand in the Ministry's app or automatically through API 2.0, from your own sales, accounting or ERP system.
How it works
- 1Authentication. The system signs in with a KSeF token or a certificate in the context of the company's NIP.
- 2Session and encryption. The XML invoice is encrypted with an AES-256 key that is sealed with the Ministry's key.
- 3Validation. KSeF checks the FA(3) schema and the content, and recognises a duplicate by the file hash.
- 4KSeF number and UPO. An accepted invoice gets a KSeF number, and the session ends with an official receipt.
An example from our work: The invoice does not wait for KSeF
Flaem
In Flaem issuing an invoice never depends on KSeF answering. The document is written together with a row in the ksef_submissions queue, and a separate worker sends it. An outage on the Ministry's side does not turn into a customer's failed purchase.
One invoice reaches KSeF once, guarded by three layers: the queue's primary key, a row lock when it is claimed, and KSeF's deduplication by file hash, status 440, which the worker records as success.
When it matters for a business
- You sell from your own system. A store, panel or platform that issues invoices has to send them to KSeF itself or through accounting software.
- You receive cost invoices. Supplier invoices are in KSeF too. An integration can fetch them instead of retyping.
- You issue many invoices. At hundreds of invoices a day, sending by hand in the app stops being possible.
What is often confused
Often heard: KSeF is just a new file format.In practice: It is a system that accepts the invoice, numbers it and decides whether it was issued at all.
Often heard: Sending to KSeF can be done synchronously at checkout.In practice: You can, but then a KSeF outage stops your sales. It is safer to queue sending in the background.
Related entries: UPO, Structured invoice, API, JWT
More: KSeF, KSeF API 2.0 step by step, KSeF integration: the mandatory e-invoicing timeline and connecting your own system to API 2.0
2
UPO
UPO is the official receipt from KSeF confirming that invoices have reached the system.
A UPO is proof for you, not for the customer: it shows that in a given session KSeF accepted particular invoices. After an online session is closed, KSeF prepares a collective UPO, and every accepted invoice also has an address to download its own.
How it works
- 1Sending invoices. Invoices go to KSeF in an online or a batch session.
- 2Closing the session. After closing, KSeF prepares a collective UPO for the whole session.
- 3Download. The UPO address has an expiry date, so the file is downloaded at once and stored with the invoice.
An example from our work: No empty sessions
Flaem
The KSeF worker in Flaem opens a session only when it has something to send. The code says it outright: an empty session is an extra round trip plus a UPO nobody asked for. Checking the status of invoices sent earlier needs no session.
When it matters for a business
- Audits and disputes. A UPO shows when KSeF accepted an invoice, which matters for deadlines and disputes with a counterparty.
- Archive. The download address expires, so the UPO has to live in your own archive next to the invoice.
What is often confused
Often heard: A UPO is the invoice.In practice: A UPO confirms KSeF accepted the invoices; it is not the invoice itself.
Often heard: You can always download the UPO later.In practice: The download address has an expiry date, so fetch the file straight away.
Related entries: KSeF, Structured invoice
More: KSeF, KSeF API 2.0 step by step, KSeF integration: the mandatory e-invoicing timeline and connecting your own system to API 2.0
3
Structured invoice
A structured invoice is an XML invoice following the FA(3) schema, issued through KSeF.
Instead of a PDF with any layout, a structured invoice is an XML file where every field has its place: seller, buyer, line items, VAT rates. That is why KSeF and accounting software can read it without retyping.
How it works
- 1Data from your system. The sale, buyer and line items come from an order or document in your system.
- 2The FA(3) schema. The XML must match the schema, including the order of elements.
- 3Sending to KSeF. Only a file accepted by KSeF is an issued invoice.
An example from our work: XML assembled by hand, in schema order
Flaem
Flaem builds the FA(3) invoice in frozcore/src/ksef/fa3.rs. The header is fixed by the schema: kodSystemowy "FA (3)", wersjaSchemy "1-0E", and the elements follow the order the xsd:sequence requires. Swapping two fields already makes an invoice KSeF will refuse.
frozcore/src/ksef/fa3.rsplaintext
1out.push_str("<KodFormularza kodSystemowy=\"FA (3)\" wersjaSchemy=\"1-0E\">FA</KodFormularza>");
When it matters for a business
- Your own sales system. Generating FA(3) is work for the system that issues the invoices.
- Invoices with unusual fields. Advances, corrections or foreign currencies have their own schema elements to handle.
What is often confused
Often heard: Generate a PDF and send it to KSeF.In practice: KSeF accepts XML following the schema, not a PDF.
Often heard: The order of fields in the XML does not matter.In practice: In FA(3) elements are a sequence, and their order is part of the schema.
Related entries: KSeF, UPO
More: KSeF, KSeF API 2.0 step by step, VAT calculator, KSeF integration: the mandatory e-invoicing timeline and connecting your own system to API 2.0
4
Payment gateway
A payment gateway is a service that takes a payment from the customer and tells the store the result.
A payment gateway takes a transfer, a card or BLIK from the customer and tells the store the result: paid or not. For the store the key part is not the redirect to payment but the confirmation that comes afterwards.
How it works
- 1Registration. The store registers a transaction with an amount and gets a token or a payment address.
- 2Payment. The customer pays on the gateway's page or with a BLIK code in the store.
- 3Notification. The gateway sends the store a signed transaction result.
- 4Verification. The store confirms the transaction with the gateway; only then is the money its own.
An example from our work: Seven gateways, one rule
Flaem
Flaem supports Przelewy24, PayU, Tpay, Stripe, PayPal, paysafecard and SimPay, each in its own module in frozcore/src/payments/gateways. The shared rule is written in the Przelewy24 comment: a notification alone is not a payment; verification is.
When it matters for a business
- You sell online. The gateway decides which methods customers can pay with and how fast you see the money.
- You integrate your own store. Every gateway has its own signature and notifications that must be handled correctly.
What is often confused
Often heard: The customer coming back from the payment page means they paid.In practice: The notification and verification decide, not the browser redirect.
Related entries: BLIK, Chargeback, Webhook, API
More: Przelewy24, Przelewy24 REST API, A Minecraft server store, VAT calculator, Margin and markup
5
BLIK
BLIK is a Polish mobile payment system where you pay with a six-digit code from your banking app.
A BLIK code is valid only briefly and you confirm it in your banking app. For a store BLIK is one of the methods in a payment gateway: either the customer picks it on the gateway's page, or types the code straight into the store, with no redirect.
How it works
- 1Code in the app. The customer generates a six-digit code in the banking app.
- 2Charge by code. The store passes the code to the gateway within a registered transaction.
- 3Confirmation in the bank. The customer approves in the app and the gateway notifies the store.
An example from our work: BLIK without leaving the store
Flaem
In Flaem's Przelewy24 integration the customer can pay on the Przelewy24 page or with a BLIK code typed into the store, through paymentMethod/blik/chargeByCode, the so-called BLIK level 0. The transaction is registered with the BLIK method, which in Przelewy24 is method 154.
When it matters for a business
- Customers without a card. BLIK works in the banking app, so the customer pays without a card and without logging in to online banking on the page.
- Payments on phones. A code typed into the store saves the redirect and the way back.
What is often confused
Often heard: BLIK is a separate payment gateway.In practice: A store usually accepts BLIK through a gateway such as Przelewy24, as one of its methods.
Related entries: Payment gateway, Chargeback
More: Przelewy24, Przelewy24 REST API
6
Chargeback
A chargeback is a card payment reversed by the customer's bank after a dispute, bypassing the store.
A customer who disputes a card payment can file a claim with their bank. The bank takes the money back, the store learns about it from the payment provider and can defend itself with proof that the goods or service were delivered.
How it works
- 1Claim at the bank. The cardholder reports a disputed payment.
- 2Dispute at the provider. The payment provider opens a dispute and informs the store.
- 3Outcome. The dispute is won or lost, and the money goes to one side.
An example from our work: A dispute recorded on the payment
Flaem
Flaem records a dispute on the payment it concerns: the provider's dispute id, the status open, won or lost, the reason, the disputed amount and the dates. The migration that introduced it carries the rule in its name: a dispute is recorded, and a refund made outside the system reconciles only once.
When it matters for a business
- You accept cards. Every store taking card payments can receive a chargeback.
- You sell digital services. With services that ship nothing, delivery is harder to prove, so collect evidence from the start.
What is often confused
Often heard: A chargeback is an ordinary refund.In practice: A refund is made by the store. A chargeback is forced by the customer's bank, and the store has to answer the dispute within the provider's deadline.
Related entries: Payment gateway, BLIK
More: Przelewy24 REST API
Websites and SEO
How a website reaches search engines, phones and every user.
7
Headless CMS
A headless CMS is a content editing system with no front end of its own that serves content through an API.
In a classic CMS such as WordPress, content editing and the site's look are one system. A headless CMS keeps only the editing: it serves content through an API, and the website, mobile app or store is built separately, in any technology.
How it works
- 1Editing. An editor writes in the CMS panel without touching the site's code.
- 2API. The content is available as data, for example JSON.
- 3Front end. The site or app fetches the data and decides the look itself.
An example from our work: There is no CMS here
vulcode.com
This site's blog runs on no CMS. Every post is a Markdown file in the repository, and the prerender turns it into static HTML at build time. Publishing is a new file and regenerating the pages, without rebuilding the app.
It works because the posts are written by people who work in the repository. A headless CMS makes sense when content is edited by people outside the dev team, or the same content has to reach several channels at once.
When it matters for a business
- Several channels. The same content goes to the website, the app and the store.
- Editors outside IT. Marketing publishes without waiting for a deployment.
- A fast site. The front end can be generated statically while the CMS stays behind the scenes.
What is often confused
Often heard: A headless CMS is always better than WordPress.In practice: It frees the front end at the cost of building it from scratch. For a simple company site a classic CMS can be cheaper.
Related entries: SSR and prerendering, SPA, API
More: Company Website, Landing Page, WordPress vs headless CMS: which architecture to choose for a company website
8
PWA
A PWA is a website you can install on a phone like an app, with an icon and notifications.
A PWA, a progressive web app, has a manifest with a name and icon and a service worker that runs in the background: it caches files and receives push notifications. You install it from the browser, without an app store.
How it works
- 1Manifest. manifest.webmanifest gives the name, icons and scope of the app.
- 2Service worker. A background script handles caching and push notifications.
- 3Install. Over HTTPS the browser offers to add an icon to the phone's screen.
An example from our work: One app for the site and the panel
Panel klienta VulCode
vulcode.com and the client panel form one installed app: there is one manifest for the whole domain, and the panel under /panel/ deliberately has none of its own, because a second manifest would put a second icon on the client's phone. Push notifications are handled by the panel's service worker.
Two service workers live on one domain: the site's and the panel's. We measured that navigator.serviceWorker.ready can resolve to the site's worker instead of the panel's, and the subscription landed on a worker with no push handler. The panel code now picks its registration explicitly.
When it matters for a business
- Customers on phones. An icon on the screen and notifications without store publishing.
- One codebase. The same app runs in the browser and once installed.
What is often confused
Often heard: A PWA works everywhere like a native app.In practice: Service workers and push only work in a secure context, HTTPS or localhost.
Related entries: SPA, SSR and prerendering
More: Mobile Apps, Panels & Dashboards, PWA vs native app: what to choose in 2026 and what a PWA still cannot do
9
SPA
An SPA is a single-page application: the browser loads it once and JavaScript draws every further view.
In an SPA the browser loads one HTML page with the app's code, and moving between views happens without reloads: JavaScript swaps the content and the address. Panels and apps feel fast, but without extra work a search engine sees an empty page.
How it works
- 1First visit. The browser downloads the HTML and the JavaScript bundles.
- 2Router. A change of address draws a new view without asking for a new page.
- 3Data from an API. Views fetch data from the back end in the background.
An example from our work: An SPA with ready HTML
vulcode.com
This site is a React SPA with a router, but every registered page also has ready HTML from the prerender. The first screen arrives as content, and only then does the app take over navigation. The VulCode and WaveHost client panels are SPAs too, and their screens after login should not reach search engines anyway.
When it matters for a business
- Panels and apps. Many views behind a login, where smoothness matters.
- Pages for search engines. Marketing content needs prerendering or SSR.
What is often confused
Often heard: An SPA cannot have good SEO.In practice: It can, if every page gets ready HTML from prerendering or SSR.
Related entries: SSR and prerendering, PWA, API
More: Company Website, Panels & Dashboards, Technical SEO checklist before launch: from staging to Search Console
10
SSR and prerendering
SSR and prerendering mean producing a page's finished HTML on the server before the browser sees it.
SSR renders HTML on the server on every visit, while prerendering does it once at build time and saves ready files. Either way the browser and the search engine get content straight away, and JavaScript only brings it to life afterwards.
How it works
- 1List of addresses. A script knows every page from the registry.
- 2Render. Each page is rendered to HTML with its title and metadata.
- 3Save and hydrate. The files go to the server, and in the browser React attaches to the ready HTML.
An example from our work: This site's prerender
vulcode.com
scripts/prerender.mjs renders every page in the registry to an index.html, with head tags and data state so the client does not flash on hydration. Pages load lazily, and renderToString does not support Suspense, so the script first does a throwaway pass that loads every bundle, and only the second pass writes files.
When it matters for a business
- Pages that should rank. Search engines and link previews get content without running JavaScript.
- A fast first screen. Users see content before the whole app downloads.
What is often confused
Often heard: Prerendering and SSR are the same.In practice: SSR computes HTML on every visit, prerendering once at build. Prerendering will not show data that changes every minute.
Related entries: SPA, Sitemap, Structured data
More: Company Website, Technical SEO checklist before launch: from staging to Search Console, Core Web Vitals in practice: how we deliver 95+ in PageSpeed
11
hreflang
hreflang is a tag that tells search engines which addresses are the same page in other languages.
On a site in several languages every version gets link rel="alternate" hreflang tags pointing to its counterparts in the other languages. The search engine then shows users the version in their language and does not treat translations as duplicates.
How it works
- 1Address pairs. Every page knows its address in other languages.
- 2Tags in the head. All versions point to each other, including themselves.
- 3Sitemap. The same pairs can go into sitemap.xml.
An example from our work: Addresses from the page registry
vulcode.com
On this site the address pairs come from the page registry: each page's Polish and English address. A page that exists only in Polish gets no English counterpart, so no link points at a page that is not there. The same registry produces the alternate addresses in sitemap.xml.
src/components/SEO.tsxtypescript
1{noindex && <meta name="robots" content="noindex,nofollow" />}2{!noindex && <link rel="canonical" href={canonicalUrl} />}3 4{SUPPORTED_LANGUAGES.filter(lang => alternatePaths[lang]).map(lang => (5 <link key={lang} rel="alternate" hrefLang={lang} href={`${SITE_URL}${alternatePaths[lang]}`} />6))}
When it matters for a business
- A site in several languages. Without hreflang the versions can compete with each other in results.
- Different addresses per language. When /pl/narzedzia matches /en/tools, only hreflang ties them together.
What is often confused
Often heard: hreflang translates the page.In practice: It only points at existing versions. You need the translation yourself.
Related entries: Canonical, Sitemap, noindex
More: Company Website, Multilingual website SEO and hreflang: URL structure, translation and the mistakes that break rankings
12
Canonical
Canonical is a tag naming a page's main address when the same content lives at several.
The same content is often reachable at several addresses: with and without a trailing slash, with parameters or at an old address. The link rel="canonical" tag tells search engines which one is the right one to show in results.
How it works
- 1One main address. The page picks its address without parameters or a trailing slash.
- 2A tag in the head. Every variant names that address as canonical.
An example from our work: Canonical or noindex, never both
vulcode.com
This site's SEO component strips the trailing slash and builds the canonical from that. A page flagged noindex gets no canonical at all, because pointing results at a page that should not be in them is a contradictory signal.
src/components/SEO.tsxtypescript
1{noindex && <meta name="robots" content="noindex,nofollow" />}2{!noindex && <link rel="canonical" href={canonicalUrl} />}
When it matters for a business
- Stores with filters. Sorting and filters create many addresses for one product list.
- A site migration. After addresses change, canonical and redirects make sure rankings move to the new ones.
What is often confused
Often heard: Canonical redirects the user.In practice: It is a hint for search engines. Moving people is what a 301 redirect is for.
Related entries: noindex, hreflang, Sitemap
More: Company Website, Website and store migration, Website migration without losing Google rankings: from URL inventory to monitoring, Technical SEO checklist before launch: from staging to Search Console
13
Sitemap
A sitemap is an XML file listing a site's addresses that helps search engines find every page.
A sitemap lists the addresses you want in search engines, with their change date and, on multilingual sites, their counterparts in other languages. It does not guarantee indexing, but it helps crawlers find pages few links lead to.
How it works
- 1List of pages. A generator takes every public address.
- 2XML file. The addresses go into sitemap.xml in the sitemaps.org format.
- 3Submission. You give the sitemap address in robots.txt or in the search engine's tools.
An example from our work: A sitemap from the same source as the pages
vulcode.com
This site's sitemap.xml is produced by the same script that prerenders the pages, from the same list of addresses. For each address it writes the language versions as xhtml:link and skips addresses that are only aliases. The HTML and the map come from the same list, so they cannot drift apart.
When it matters for a business
- Many pages. Guides, tools or products get lost easily without a map.
- A new site. A map speeds up discovering pages no outside links lead to yet.
What is often confused
Often heard: A page in the map is sure to reach results.In practice: The map is a suggestion. The search engine still judges the page itself.
Related entries: robots.txt, hreflang, Canonical
More: Company Website, Technical SEO checklist before launch: from staging to Search Console
14
robots.txt
robots.txt is a file at a site's root telling search engine crawlers what not to visit.
robots.txt sits at /robots.txt and holds Allow and Disallow rules for crawlers. It closes off, for example, the admin panel or the API. It is not security: it is a request that well-behaved crawlers respect, and anyone can read the addresses in it.
How it works
- 1A file at the root. A crawler fetches /robots.txt before visiting.
- 2Rules. User-agent says who the rules apply to, Disallow what not to visit.
An example from our work: What our robots.txt closes
vulcode.com
This site's robots.txt allows everything except a few paths: /auth, /admin, /api/, plus the admin panel and test pages in each language. These are places with no content for search engines, where crawler traffic only loads the server.
public/robots.txtplaintext
1User-agent: *2Allow: /3 4Disallow: /auth5Disallow: /admin6Disallow: /api/7Disallow: /pl/admin8Disallow: /en/admin
When it matters for a business
- Panel and API on the same domain. Crawlers do not need to roam login screens and endpoints.
- Test pages. Drafts should not compete with production.
What is often confused
Often heard: Disallow removes a page from Google.In practice: It blocks visits, but an address known from links can stay in the index. noindex is what removes it from results.
Often heard: robots.txt protects private pages.In practice: The file is public. Login protects private pages, not robots.txt.
Related entries: noindex, Sitemap
More: Company Website, Technical SEO checklist before launch: from staging to Search Console
15
noindex
noindex is an instruction telling search engines not to show a page in search results.
noindex goes in a robots meta tag or in the X-Robots-Tag HTTP header. The crawler has to be able to visit the page to see it, so a noindex page cannot also be blocked in robots.txt.
How it works
- 1The crawler visits. The page must be reachable for the crawler.
- 2Reads meta robots. The noindex value says not to show the page in results.
- 3Drops it from the index. After the next visit the page disappears from results.
An example from our work: One flag in the SEO component
vulcode.com
On this site noindex is one flag of the SEO component. It adds meta robots with noindex,nofollow and removes the canonical at the same time, so the page does not send two contradictory signals.
When it matters for a business
- Screens behind login. Login forms and account pages are not content for results.
- Technical pages. Thank-you pages after a form or internal search results.
What is often confused
Often heard: noindex and Disallow do the same thing.In practice: Disallow blocks the visit, noindex removes from results. Together they cancel out, because the crawler never sees the noindex.
Related entries: robots.txt, Canonical
More: Company Website, Technical SEO checklist before launch: from staging to Search Console
16
Structured data
Structured data describes a page's content in the schema.org format so search engines can read it.
Structured data is a JSON-LD block in the page code that says outright what the content is: an organisation, an article, questions and answers, a breadcrumb trail. Search engines use it to understand the page and for rich results.
How it works
- 1A schema.org type. You pick a type that fits the content, for example Article or FAQPage.
- 2JSON-LD in the head. A type="application/ld+json" script describes the page's fields.
- 3Matching the content. The data must describe what is visible on the page.
An example from our work: Three layers on every page
vulcode.com
Every page on this site carries the organisation description, a BreadcrumbList built from the page registry and data of its own. A guide, for example, has an Article with its check date and list of sources, and a FAQPage with the questions shown at the bottom of the guide.
When it matters for a business
- Articles and guides. Date, author and sources help search engines assess content.
- Questions and answers. FAQPage describes the question section you have on the page.
What is often confused
Often heard: Structured data improves rankings.In practice: They help a page be understood and may earn a rich result, but they do not replace content.
Related entries: SSR and prerendering, Sitemap
More: Company Website, Technical SEO checklist before launch: from staging to Search Console
17
WCAG
WCAG are the Web Content Accessibility Guidelines used to judge whether a website is accessible.
WCAG sets accessibility criteria at levels A, AA and AAA: contrast, keyboard operation, image descriptions, video captions, clear forms. Level AA is usually the legal requirement, for example in the Polish digital accessibility act for public bodies.
How it works
- 1Criteria. Every success criterion has a level and a condition to meet.
- 2Testing. Automated tools plus a manual review with a screen reader.
- 3Fixes. Failures become tasks, or go into the statement as inaccessible content.
An example from our work: Contrast computed the WCAG way
kontrast WCAG
Our free WCAG contrast tool computes the ratio from both colours' relative luminance and checks the thresholds: 4.5:1 for normal text and 3:1 for large at AA, 7:1 and 4.5:1 at AAA, and 3:1 for icons and field borders. Grey #7c8599 on white is 3.70:1, so it fails AA for normal text.
When it matters for a business
- Public bodies. The law requires accessibility and an accessibility statement.
- Online stores. The Polish Accessibility Act has covered e-commerce services since 28 June 2025.
- Every site. An accessible site is easier for everyone, not only people with disabilities.
What is often confused
Often heard: An accessibility button plugin is enough.In practice: An overlay does not fix the code: contrast, field labels and keyboard support must be fixed in the site itself.
More: Digital accessibility, WCAG colour contrast, Digital accessibility for websites and online stores: WCAG 2.2, the European Accessibility Act and Polish law
Business and collaboration
Terms that come up when a product is quoted and planned.
18
MVP
An MVP is the smallest version of a product that solves the core problem and lets you test it on people.
An MVP, a minimum viable product, answers one question: do people want this product and do they use it. So it contains only what the product cannot do its job without, and deliberately leaves the rest for later.
How it works
- 1One problem. You pick the main user problem the product solves.
- 2The shortest path. You build only the features the problem cannot be solved without.
- 3Real users. The product reaches people and you collect data on how they use it.
An example from our work: A system in two weeks for a startup
SafeBands
For SafeBands, a startup building smart rescue wristbands, we built the platform's operational core: accounts with access control, real-time device data monitoring, alerts and an emergency portal that works without logging in. We delivered it in two weeks.
A short deadline enforces what an MVP needs: a scope closed around what the product cannot work without.
When it matters for a business
- A new product. You test the idea on people before spending the budget on a full version.
- Investors. A working product says more than a pitch deck.
What is often confused
Often heard: An MVP is a sloppy version.In practice: It has few features, but the ones it has must work well, or the test tells you nothing.
Often heard: An MVP is a prototype.In practice: A prototype shows the idea. An MVP is used by real users.
Related entries: SaaS, White label
More: Startups and MVPs, Web Platforms, How to build an MVP: the first version of your product without burning through the budget, How to write a project brief for a software house: structure, example and common gaps
19
White label
White label is a product a client sells or offers under their own brand, colours and domain.
A white-label product runs under the client's brand: their name, logo, colours and domain, with the technology vendor invisible to users. The client does not build software from scratch yet still has a product of their own.
How it works
- 1A shared core. One codebase serves many brands.
- 2Brand theme. Colours, logo and copy are set without changing code.
- 3Own domain. Users see only the client's brand.
An example from our work: The same panel, another brand
Aphrodi, Flaem
The Aphrodi client panel is a twin of the VulCode panel: the same core, Aphrodi's full identity, another brand and palette. In Flaem the operator sets their brand in the panel, and frozcore accepts only strictly defined values: a colour, a font from a list, a file from their own uploads. Even custom CSS runs in a fenced layer and cannot fetch anything outside the brand's uploads.
When it matters for a business
- A hosting company. Customers see a panel with your brand, not the software vendor's.
- Several brands in a group. One product serves every brand without separate code.
What is often confused
Often heard: White label is just a logo swap.In practice: It is also colours, domain, emails and documents, everything the user sees.
Related entries: SaaS, MVP
More: Panels & Dashboards
20
SaaS
SaaS is software as a service: you use it in a browser on a subscription and the vendor runs it.
In the SaaS model the customer installs nothing: they pay a subscription and log in through a browser, while servers, updates and backups are on the vendor's side. The opposite is software you host yourself, on your own server.
How it works
- 1One installation. The vendor runs the system for all customers.
- 2Subscription. The customer pays for access, usually monthly or yearly.
- 3Updates. New versions reach everyone at once, with no work on the customer's side.
An example from our work: Deliberately not SaaS
Pharos
Pharos, our status page, is the opposite of SaaS: one Go binary with embedded SQLite that you set up on your own server with one command. Uptime monitoring, the public status page and incident handling run on your server, not ours.
When it matters for a business
- A fast start. SaaS works from sign-up, with no server or administration.
- Control over data. When data has to stay with you, self-hosted software is often the better fit.
What is often confused
Often heard: Every browser app is SaaS.In practice: You can host a web app yourself too. SaaS means the model where the vendor runs it.
Related entries: White label, MVP, VPS
More: SaaS companies, Web Platforms
Engineering
How systems talk to each other and how code reaches a server.
21
API
An API is the interface through which one program asks another for data or to perform an operation.
An API defines which requests can be sent, with what data, and what comes back. That is how a store creates a shipment with a carrier, a panel creates a server in a hosting system, and a sales system an invoice in KSeF, with no person in between.
How it works
- 1Key or token. The program identifies itself with a key that has permissions.
- 2Request. It sends an HTTP method, an address and data, usually JSON.
- 3Response. It gets the result or an error code saying what went wrong.
An example from our work: Two APIs of one system
WaveHost
The WaveHost panel talks to Pterodactyl through two APIs. The Application API with a ptla_ key creates users and servers, suspends and deletes them. The Client API with an admin ptlc_ key handles what the first does not expose: power, the console and live resource usage.
When it matters for a business
- Integrations. Store, accounting, courier and CRM exchange data on their own.
- Your own app. The website, mobile app and panel share one back end.
What is often confused
Often heard: Every system has an API for everything.In practice: An API exposes what its vendor planned. In Pterodactyl some operations exist only in the Client API.
Related entries: Webhook, Rate limit, OAuth, JWT
More: Integrations & Automation, Integrations, InPost ShipX API, Installing the Pterodactyl panel, JSON formatter, API integration: how to connect your website, online store or admin panel to ERP, CRM, accounting and payments
22
Webhook
A webhook is a notification one system sends another when something happens, without being asked.
Instead of asking another system every so often whether anything changed, you give it an address and it sends a request there when the event happens: a payment, a shipment status change, a store purchase. The receiver has to check the message is genuine.
How it works
- 1Address. You register an HTTPS address with the system that sends events.
- 2Event. The system posts JSON describing the event to that address.
- 3Verification. The receiver checks the signature or source, and only then acts.
An example from our work: The signature before anything else
Flaem
Flaem accepts webhooks from the Tebex and CraftingStore stores. Both sign the body with HMAC-SHA256, and Tebex computes it over the body's SHA-256 hash rather than the body itself, which frozcore handles separately. We compare the signature in constant time, and only after that does anything reach the delivery queue.
When it matters for a business
- Payments. The payment result arrives as a notification, not in the customer's browser.
- Order statuses. A courier or marketplace reports changes without polling.
What is often confused
Often heard: A webhook always has a signature.In practice: Not always. InPost gives the address range it sends from instead, and then it is worth confirming the data through the API.
Related entries: API, Rate limit, Payment gateway
More: Integrations, Integrations & Automation, InPost ShipX API, Przelewy24 REST API, A Minecraft server store, Discord webhook and embed, Checksums and hashes
23
Rate limit
A rate limit caps how many requests an API accepts in a period of time and refuses the rest.
Services cap the number of requests so one client cannot block the others. Past the limit they usually answer with code 429 and how long to wait. An integration that ignores this loses data or gets blocked.
How it works
- 1Limit. The service counts requests per second, minute or hour.
- 2Refusal. Past the limit it answers 429 or a similar code.
- 3Retry. The client waits the given time and tries again.
An example from our work: A separate queue per target
webhook-proxy
Our webhook-proxy relays notifications from our services to Discord webhooks. Discord counts the limit separately for each webhook, so the proxy keeps a queue per target, respects 429 answers and retries 5xx errors. A clogged alerts channel then does not block payment notifications.
When it matters for a business
- Integrations with registries. GUS BIR, for example, allows 3 requests a second during working hours.
- Large sends. Bulk notifications must go at a pace the service accepts.
What is often confused
Often heard: Just retry straight away.In practice: Retrying at once only prolongs the block. You have to wait as long as the service says.
Related entries: API, Webhook
More: Integrations & Automation, Integrations, A Discord bot in Python
24
OAuth
OAuth is the standard that lets you sign in to an app with an account from another service, without its password.
With OAuth an app never gets your password for another service. It redirects you there, you log in and consent, and the app receives a one-time code that its server exchanges for a token with limited permissions.
How it works
- 1Redirect. The app sends you to the service with the list of permissions it asks for.
- 2Consent. You log in and accept the permissions.
- 3Code and token. The app gets a code, and its server exchanges it for a token.
An example from our work: Signing in with Discord
Panel klienta VulCode
The VulCode client panel has Discord sign-in built on OAuth: after consent Discord returns to the panel with a code, the panel passes it to the back end, and only the back end exchanges it for a token. The browser never sees the app's secret. The panel also checks the authorisation was started in the same tab and rejects a foreign one.
The button stays hidden until the back end has the Discord app keys, so it never leads to an error page. On 6 October 2026 it was still switched off in production.
When it matters for a business
- Login without a password. The user does not create yet another account with a password.
- Access to other services' data. The app gets only the permissions the user agreed to.
What is often confused
Often heard: OAuth is login.In practice: OAuth grants access to resources. Login is built on top of it, for example with OpenID Connect or by fetching the profile.
Related entries: JWT, API
More: Discord, Panels & Dashboards, Bot invite link
25
JWT
A JWT is a signed JSON token carrying who you are and what you are allowed to do.
A JWT has three parts separated by dots: a header, a payload and a signature, each in Base64URL. The payload says, for example, who you are and until when the token is valid, and the signature lets the server check nobody changed it. The payload is not encrypted, so it holds no secrets.
How it works
- 1Issue. The server creates a token with a payload and signs it with its key.
- 2Use. The client sends the token in the Authorization: Bearer header.
- 3Check. The server verifies the signature and the expiry date.
An example from our work: A token from a real KSeF response
KSeF API
When we ran authentication on the KSeF test environment for our KSeF guide, the authentication token in the response began with eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9, the encoded JWT header with the HS256 algorithm. With that token in a Bearer header you check the authentication status and redeem the real access token.
When it matters for a business
- APIs without server sessions. The server does not need to remember sessions; checking the signature is enough.
- Security. A token must be protected like a password and given a short lifetime.
What is often confused
Often heard: A JWT is encrypted.In practice: It is signed, not encrypted. Anyone holding the token can read the payload.
Related entries: OAuth, API, KSeF
More: Integrations & Automation, KSeF API 2.0 step by step, Base64, URL and JWT
26
CI/CD
CI/CD is building, testing and deploying code automatically after every change in the repository.
CI, continuous integration, builds and tests code after every change. CD, continuous delivery or deployment, prepares or deploys the checked version straight away. That turns "it works on my machine" into a fact about the branch, not about somebody's computer.
How it works
- 1A change in the repository. A push or a pull request starts the pipeline.
- 2Gate. Compiling, formatting, linting and tests must pass.
- 3Release. The checked version reaches the server or waits for approval.
An example from our work: A gate on every push
Flaem
frozcore in Flaem runs CI on every push and pull request to dev and main: compiling with tests, formatting, clippy, tests against real PostgreSQL and Redis instead of mocks, a migration numbering check and a dependency audit. A comment in the CI file says outright what came before: images built on somebody's laptop.
scripts/gate.sh runs the same jobs locally when Actions is unavailable, and a change in one place must reach the other in the same commit.
When it matters for a business
- Several people in the code. One change's bug shows up before it reaches the others.
- Frequent releases. Deploying stops being a manual procedure with room for error.
What is often confused
Often heard: CI is just running the tests.In practice: It is the whole gate: compiling, analysis, tests against real services and checking what will be released.
Related entries: Docker, Pull request, Open source
More: Code audit
27
Docker
Docker packs an application with its dependencies into a container that runs the same anywhere.
A container holds the application with its libraries and configuration but shares the system kernel with other containers, so it starts fast and takes less than a virtual machine. An image built once runs the same on a laptop, a test server and production.
How it works
- 1Dockerfile. It describes the base image and what to install.
- 2Image. docker build turns the description into a runnable image.
- 3Container. docker compose runs containers with restart settings and volumes.
An example from our work: A bot in a container that restarts itself
mailcheck
Our mailcheck bot runs in a container from the python:3.9-slim image, and docker-compose.yml sets restart: always and mounts the data and a read-only configuration. After a server reboot the bot comes back with no manual start. Likewise in Pterodactyl and Flaem every game server is its own container.
boty/mailcheck/docker-compose.ymlyaml
1services:2 mailcheck:3 build: .4 container_name: mailcheck5 restart: always6 volumes:7 - ./data:/app/data8 - ./config.json:/app/config.json:ro
When it matters for a business
- Repeatable deployments. Production runs the same image that passed the tests.
- Many services on a server. Each service has its own dependencies and does not disturb the others.
What is often confused
Often heard: A container is a virtual machine.In practice: A container shares the kernel with the host; a VM has its own. That is why Docker does not run on every VPS.
Related entries: CI/CD, VPS, Pterodactyl
More: A Discord bot in Python, Installing the Pterodactyl panel
28
Open source
Open source is software whose code anyone may read, change and build on under its licence.
An open project's code is public, and its licence says what you may do with it: use, change, distribute, sometimes on condition of sharing your changes. Projects grow thanks to people outside the team who report bugs and send fixes.
How it works
- 1Public code. The repository is open to everyone.
- 2Licence. It sets the rights and duties of the code's users.
- 3Outside contributions. Anyone can propose a change, and maintainers decide whether to accept it.
An example from our work: Fixes in other people's projects
Kontrybucje VulCode
By 6 October 2026 maintainers had merged 97 of our pull requests in 55 projects on GitHub, plus 6 commits in Proxmox VE accepted through the project's mailing list. Every merged change is described on our contributions page, with a link to the code.
When it matters for a business
- Choosing technology. An active open source project means less risk of the tool being abandoned.
- Licences in a client project. Some licences require sharing changes, which you need to know before starting.
What is often confused
Often heard: Open source means free for any purpose.In practice: The licence can set conditions, for example sharing modified code.
Related entries: Pull request, Proxmox VE, CI/CD
More: Open source, Contributions, Why we contribute to open source: what a software house gains from fixing other people's code
29
Pull request
A pull request is a proposed code change that the project's maintainers review before merging it.
A pull request collects changes from one branch and asks to merge them into another. Maintainers read the code, comment and run the tests, and the author revises until the change is ready. Only then does it enter the project.
How it works
- 1Fork and branch. The author works on a copy of the repository, on a separate branch.
- 2Review. Maintainers comment, and automated tests check the change.
- 3Merge. An accepted change goes into the main branch.
An example from our work: 97 merged changes
Kontrybucje VulCode
Each of our 97 changes accepted into projects on GitHub went through this process: submission, maintainer review, revisions and merge. In Proxmox VE fixes go to the mailing list as patches instead of pull requests, but the review works much the same way.
When it matters for a business
- Code in a team. Every change gets a second pair of eyes before reaching production.
- A history of decisions. The description and discussion stay with the change for years.
What is often confused
Often heard: A pull request is a commit.In practice: It is a request to merge one or more commits, together with discussion and review.
Related entries: Open source, CI/CD
More: Contributions, Code audit
Servers and hosting
Machines, virtualisation and the panels services run on.
30
VPS
A VPS is a virtual private server: a slice of a physical machine with its own system and resources.
A physical server is split into many virtual machines. Each has its own system, IP address, CPU, memory and disk allocation, and full root access. To the customer a VPS behaves like a separate server, even though it shares hardware with others.
How it works
- 1Hypervisor. Software such as Proxmox VE with KVM splits the server into machines.
- 2Resource allocation. Each machine gets cores, memory and disk.
- 3Its own system. The customer installs and configures what they like as root.
An example from our work: A VPS ordered in the panel
WaveHost
In the WaveHost panel the customer configures a VPS and pays, and a separate worker creates the machine through the Proxmox API. The customer gets the console, firewall, backups and server settings in the panel, with no support contact.
When it matters for a business
- Your own services. A site, an API, a bot and a database on one server with full control.
- Virtualisation and Docker. On a KVM VPS Docker works; on OpenVZ and LXC it usually does not.
What is often confused
Often heard: A VPS is shared hosting.In practice: Shared hosting gives no root and no system of your own. A VPS gives both.
Related entries: Proxmox VE, Docker, Pterodactyl
More: Installing the Pterodactyl panel, An SCP:SL server from scratch, CIDR subnet calculator, chmod calculator, Business hosting: shared, VPS, dedicated server, cloud or PaaS
31
Proxmox VE
Proxmox VE is an open virtualisation platform that runs virtual machines and LXC containers.
Proxmox Virtual Environment combines KVM virtualisation for full virtual machines and LXC containers for lighter systems, with a browser panel, clusters, backups and an API. It is open source and often serves hosting companies as the base of their VPS offering.
How it works
- 1Nodes. Physical servers running Proxmox join a cluster.
- 2Machines and containers. KVM machines and LXC containers run on the nodes.
- 3API. Everything the panel does can be done through the API.
An example from our work: We use it and we fix it
WaveHost, Proxmox VE
WaveHost creates customers' VPSs through the Proxmox API. To Proxmox VE itself we contributed 6 fixes, accepted into the project's repositories on git.proxmox.com. We describe them on a separate page, together with what working on someone else's virtualisation code taught us.
When it matters for a business
- Your own infrastructure. Virtual machines on your own hardware without a licence per node.
- Automation. Selling VPSs in a panel needs an integration with the Proxmox API.
What is often confused
Often heard: An LXC container is the same as a KVM machine.In practice: LXC shares the host kernel and is lighter, but Docker, for example, runs in it only with nesting enabled.
Related entries: VPS, Open source, API
More: Contributions
32
Pterodactyl
Pterodactyl is an open panel for managing game servers that run in Docker containers.
Pterodactyl has two parts: a PHP panel where servers and users are managed, and the Wings daemon on each node, which runs servers in Docker containers. Server types are described by eggs, and the panel has an Application API and a Client API.
How it works
- 1Panel. Customers and admins manage servers in the browser.
- 2Wings. The daemon on the node creates containers and relays the console.
- 3Egg. A recipe says how to install and run a given server.
An example from our work: A game server from the cart
WaveHost
Buying a game server in the WaveHost panel creates a server in Pterodactyl through the Application API: the panel takes the Docker image, start command and variables from the egg, applies the package limits and assigns an allocation. Each WaveHost user has one Pterodactyl account, so further purchases go to the same account.
When it matters for a business
- A hosting company with games. Pterodactyl is a ready foundation instead of your own container system.
- Your own client panel. The API lets you hide Pterodactyl behind a panel with your own brand.
What is often confused
Often heard: Pterodactyl takes payments by itself.In practice: Pterodactyl manages servers. Sales, payments and invoices are done by a separate system, such as a client panel.
Related entries: Egg, Docker, VPS, API
More: Game servers, Installing the Pterodactyl panel, An SCP:SL server from scratch
33
Egg
An egg is a server recipe in a panel: the Docker image, the install script, the start command and variables.
An egg describes one kind of server: the Docker image it runs in, the install script, the start command, the variables the customer can set, how the panel knows the server has started and how to stop it. Pterodactyl's default eggs cover popular games, and you write your own for the rest.
How it works
- 1Install. A script in an installer container fetches the server files.
- 2Start. The panel runs the start command with the assigned port.
- 3Ready and stop. A console line marks start-up, and a command stops the server.
An example from our work: The SCP:SL server egg
Flaem
Flaem keeps eggs in the frozeggs repository for SCP:SL, Minecraft, Terraria, Palworld and Factorio, among others. The SCP:SL egg installs the server through SteamCMD with app 996560, starts ./LocalAdmin with the server port, treats the line "Waiting for players.." as started and stops the server with EXIT.
frozeggs/eggs/scp-sl/dedicated.jsonjson
1"startup_invocation": "./LocalAdmin ${SERVER_PORT}",2"process_configuration": {3 "startup": { "done": ["Waiting for players.."] },4 "stop": { "type": "command", "value": "EXIT" }5}
When it matters for a business
- A game not on the list. Without an egg the panel does not know how to install and run the server.
- Your own settings. Egg variables let customers pick a version or a map without console access.
What is often confused
Often heard: An egg is a Docker image.In practice: An egg points to an image, but also describes install, start, variables and stopping.
Related entries: Pterodactyl, Docker
More: Game servers, An SCP:SL server from scratch, Installing the Pterodactyl panel
Games and Discord
Game servers, plugins, stores and bots.
34
Minecraft plugin
A Minecraft plugin is a Paper or Spigot server add-on that changes the game with nothing installed by players.
A plugin runs on the server side, so players join with the ordinary game client. Plugins add commands, stores, minigames, protection and integrations, for example with Discord. They are written in Java against the server's API, these days most often Paper.
How it works
- 1A jar file. A plugin is a jar file in the server's plugins directory.
- 2Events and commands. The code reacts to game events and registers commands.
- 3The server thread. Operations on the world and players happen on the server thread.
An example from our work: A plugin that connects the server to the platform
Flaem (frozcraft)
Frozcraft is our Paper plugin that connects a Minecraft server to Flaem: the player list with skins, TPS and MSPT stats, moderation actions and handing over store purchases. It talks to the rest of the platform through a Unix socket on the server's volume, without opening any port.
When it matters for a business
- A server with its own game mode. Unique mechanics need a plugin written for the server.
- Integrations. A store, Discord or a panel connects to the game through a plugin.
What is often confused
Often heard: A plugin and a mod are the same.In practice: A mod usually needs installing on players' machines. A plugin runs only on the server.
Related entries: RCON, Item shop
More: Game plugins and scripts, Game servers, Your first Minecraft plugin on Paper, A Minecraft server store, /give command builder, /tellraw and /title builder
35
RCON
RCON is a game server's remote console protocol used to send commands over the network.
RCON lets another program send commands to the server console: you log in with a password, send a command and get its output. In Minecraft you enable it in server.properties, on port 25575 by default. The connection is not encrypted, so the port should not be reachable from the internet.
How it works
- 1Login. A type 3 packet with the password from rcon.password.
- 2Command. A type 2 packet with the command text.
- 3Response. The server returns the output with the same request id.
An example from our work: Deliberately without RCON
Flaem (frozcraft)
Frozcraft in Flaem does not use RCON. It talks to the platform through a Unix socket on the server's data volume, with no port and no network exposure, and fetches store deliveries itself over outbound HTTPS. RCON stays for simple admin tools on a private network.
When it matters for a business
- Simple automation. A restart, an announcement or a world backup from an outside script.
- Security. The RCON password travels in plain text, so the port must stay on a private network.
What is often confused
Often heard: RCON is good for an item shop.In practice: It does not know whether the player is online and does not protect against double delivery. A queue with a plugin is better for a shop.
Related entries: Item shop, Minecraft plugin
More: Game plugins and scripts, A Minecraft server store, server.properties generator
36
Item shop
An item shop is a game server store where players buy ranks and items that are delivered automatically.
The player picks a rank or an item, pays, and the server hands it over with no admin involved. The hard part of an item shop is not taking the payment but making sure every paid item reaches the right player exactly once, including when they are offline at the time.
How it works
- 1An order from the game. The plugin knows the player's UUID and opens the order.
- 2Payment. The gateway confirms the payment and the order joins the queue.
- 3Delivery. The plugin collects deliveries and hands them to online players.
An example from our work: A shop where players have no account
Flaem
In the Flaem shop players have no account or password. They are identified by what the game reports, such as the Minecraft account UUID, vouched for by the plugin with the server's token. An item carries no console command, only a delivery key, and the plugin leases deliveries for 10 minutes and acknowledges each with one conditional write.
When it matters for a business
- A server that pays its way. Selling ranks and cosmetics covers server costs, within Mojang's rules.
- Less admin work. Automatic delivery replaces typing commands by hand after every payment.
What is often confused
Often heard: A nickname field and an RCON command are enough.In practice: Anyone can type someone else's name, and RCON does not know whether the player is online. That invites complaints.
Related entries: RCON, Minecraft plugin, Payment gateway
More: Game plugins and scripts, Game servers, A Minecraft server store, Przelewy24 REST API
37
Slash commands
Slash commands are Discord bot commands typed after a slash, with suggestions and descriptions in the app.
After typing a slash, Discord shows the list of bot commands on the server, with descriptions and fields to fill in. The bot registers its commands with Discord, and each call reaches it as an interaction it has to answer within 3 seconds.
How it works
- 1Registration. The bot syncs its command tree to a server or globally.
- 2Call. The user picks a command and fills in the fields.
- 3Response. The bot answers at once, or defers and sends it later.
An example from our work: The mailcheck bot's commands
mailcheck
Our mailcheck bot in discord.py 2.7.1 has slash commands in three cogs, including /stats with mailbox statistics and the admin /addkonto with a direction choice: received, sent or both. Users see the field descriptions in Discord before sending the command.
When it matters for a business
- A bot on a community server. Commands with suggestions need no syntax to learn.
- Permissions. Admin commands can be limited to chosen roles.
What is often confused
Often heard: A bot has to read every message to have commands.In practice: Slash commands do not need the privileged Message Content intent.
Related entries: Webhook, OAuth
More: Discord bots, Discord, A Discord bot in Python, Slash command builder, Discord permissions calculator, Discord timestamps