Changelog
The API is versioned in the path (/external/v1). Breaking changes ship under a new major version; additive changes (new fields, new endpoints, new optional parameters) roll out within v1. Treat unknown response fields as forward-compatible: ignore what you don't recognise.
v1 (current)
2026-10-09: margin-scheme invoices
- Margin lines. The rate
vatRate: "marza"marks a line sold under the margin scheme (art. 119 and 120 of the VAT Act): the invoice shows gross amounts only, in KSeF the line has noP_12and its sum goes toP_13_11. The document needsannotations.marginProcedure(otherwise422 MARGIN_LINE_WITHOUT_PROCEDURE). Margin lines and regular rates can share one invoice. - Purchase amount and VAT on the margin. New line fields
marginPurchaseValue(gross purchase amount in PLN) andmarginTaxRate(23,8,5,0) inPOST,PUTandPATCH /documentsand inGET /documents/{id}responses. They never appear on the invoice or in KSeF; the margin and the VAT on it in the VAT register and JPK_V7 come from them. New codes:422 MARGIN_TAX_RATE_INVALID,422 MARGIN_PURCHASE_INVALID. Guide: Margin scheme. - Purchase amount after issue.
PATCH /documents/{id}/margin-purchases(scopedocuments:update, MCP toolupdateDocumentMarginPurchases) sets the purchase amount and the margin VAT rate of margin lines also after the KSeF send. Codes422 MARGIN_LINE_NOT_FOUNDand422 MARGIN_PURCHASES_INVALID.PUTandPATCH /documents/{id}without the margin fields on a line keep the stored values. - Margin sale in the preview.
POST /documents/validatereturnspreview.totals.marginSaleSum(the margin sale insidenetSum,P_13_11in KSeF), and the MCP toolprepareDocumentgives the net of the ordinary rates apart from the margin sale in its summary. The storednetSumkeeps its meaning. - Correcting a margin invoice downloaded from KSeF. A margin-scheme sales invoice issued in another program (lines without
P_12, the sum inP_13_11) gets lines with themarzarate once read and can be corrected.422 CORRECTED_INVOICE_MARGIN_LINESremains only for lines without a rate on an invoice without the margin procedure annotation.
2026-10-09: correcting a sales invoice downloaded from KSeF
- Correction of an invoice issued outside Fakturnia.
POST /documentsaccepts incorrectedInvoiceIda sales invoice downloaded from KSeF (source: "ksef",direction: "income", typeFakturaVAT). The API reads its lines, totals and buyer address from the invoice XML (fetching it from KSeF when needed), computes the correction as a difference and names the KSeF number of the original invoice in KSeF. New codes:422 CORRECTED_INVOICE_NOT_INCOME,422 CORRECTED_INVOICE_WITHOUT_POSITIONS;CORRECTED_INVOICE_TYPE_MISMATCHnow also covers imports of other types. Guide: Corrections. - Lines of invoices downloaded from KSeF.
GET /documents/{id}of an invoice downloaded from KSeF returnsproducts,netSumandvatSumonce its XML has been read (after it was opened in the app or corrected); such invoices used to carry onlygrossSum.
2026-10-09: contractor identifiers ready for KSeF
- One set of identifier rules for contractors and document parties.
POSTandPUT /clientsand a buyer and receiver given as data inPOST /documents,POST /documents/validate,PUTandPATCH /documents/{id}store identifiers in the form KSeF accepts: the NIP as 10 digits, the VAT UE number with its country prefix invatUE(GreeceEL),otherwith a country. Guide: Contractor identifiers. - A VAT UE number typed in
nipgoes tovatUE. WithoutidentifierTypethe numberDE123456789innipis stored asvatEuinvatUEwithcountryCodefrom the prefix, not as a NIP. - Warnings in
data.warnings. Contractor and document responses (alsovalidate) say how the identifiers were read: an inferred type, a moved number, an inferred country (code,field,message). The MCP toolprepareDocumentreturns them inidentifierNotes. - Contradictions are refused. Contractors:
422 VALIDATION_ERROR, documents: the new code422 PARTY_IDENTIFIER_INVALID, always naming the field. This also covers a NIP with a wrong check digit sent withoutidentifierType(accepted before) and anidWewin a form other thanNIP-NNNNN. - Data saved earlier stays editable. Identifiers equal to the stored ones are not re-checked on
PUT /clientsor onPUTandPATCHof a document.
2026-10-09: FA(3) dates, instalments, several advance receipts, the day of payment
- Sale period:
subDateTo. WithsubDateas its start it givesOkresFain KSeF (e.g. a service for a whole month).PATCHkeeps a stored period and date label. - Exchange rate with its NBP day and table:
exchangeRateDate,exchangeRateTable. An invoice's rate is the rate of the business day before the tax point, or before the issue date when the invoice comes first (art. 31a of the VAT Act). A correction withoutexchangeRatetakes the corrected invoice's rate, day and table (art. 31b ust. 1). - Tax point at the issue of the invoice:
taxPointRule. For construction services, books and press, utilities, telecommunications, rent, leasing, security and ongoing services (art. 19a ust. 5 pkt 3 and 4). It decides the period in VAT reports and the day of the rate. When the account has the setting on with a default rule, a document withouttaxPointRulegets it from the settings (preview.appliedDefaults:TAX_POINT_RULE);useAccountDefaults: falseor an explicitnullskips it. - Instalments and a due date in words:
paymentInstallments,paymentDeadlineTerm. Several due dates with amounts, or a term like "14 days from delivery of the invoice";TerminPlatnosciandTerminOpisin KSeF. Inconsistent instalments:422 PAYMENT_INSTALLMENTS_INVALID. Guide: Creating documents. - Equal instalments computed by the API:
paymentInstallmentsSplit.POST,PUTandPATCH /documentsandPOST /documents/validateaccept{ count, firstDate?, every? }; the API splits the amount due to the grosz (the remainder on the last instalment) and stores ordinarypaymentInstallments. Thevalidatepreview lists them inpreview.paymentInstallments, and the MCP toolsprepareDocumentandpatchDocumenttake the same field. Guide: Creating documents. - Several receipts on an advance invoice:
advanceReceipts. Each receipt with its date, amount and rate;ZaliczkaCzesciowain KSeF. Inconsistent receipts:422 ADVANCE_RECEIPTS_INVALID. - Correction dates:
correctionEffectDate,correctionConfirmationDate. The day the correction takes effect (an increase after the sale whose cause arose in another month givesTypKorekty3) and the day the buyer confirmed a correction issued outside KSeF. A correction withoutsubDatetakes the sale date or period of the corrected invoice. Guide: Correcting documents. - The day of payment when marking it.
PATCH /documents/{id}/payment-statusacceptspaymentDate(today in Poland by default, never in the future);GETreturns it aspayment.receivedPaymentDate. For the cash method it is the tax point. - Dates checked like in the app:
422 DOCUMENT_DATES_INVALID. A sale period starting after its end, a sale date more than 60 days after the issue, a payment date after the issue, a correction issued before the corrected invoice.PUTandPATCHalso check the date format. - KSeF: more dates in the XML. Place of issue (
P_1M), instalments and a due date in words, advance receipts. A date with a time is the day in Poland, and an unreadable date is a validation error instead of today's date.
All new fields are optional: integrations that do not send them work as before.
2026-10-09: correction of a correction
- One correction per document. A new correction of a document that already has one gets
409 CORRECTED_INVOICE_HAS_CORRECTIONwith the number and the id of the latest correction of the chain inerrors[0]. You issue the next change as a correction of that correction, so its "before" state includes the earlier changes and the amounts do not count them twice.PUTandPATCHanswer the same when you move a correction to a document that has another correction. Guide: Correcting documents. - A correction of a correction names the original invoice in KSeF.
DaneFaKorygowanejgives the number, date and KSeF number of the original invoice, not of the previous correction (KSeF 2.0 manual, part II, section 2.13.3). The printout shows the original invoice and the previous correction. - Original invoice without a KSeF number.
POST /documents/validatereturns notes that do not stop the document inpreview.warnings. On an account connected to KSeF, a correction whose original invoice has no KSeF number gets the codeCORRECTION_ORIGINAL_KSEF_PENDING,CORRECTION_ORIGINAL_NOT_SENT_TO_KSEForCORRECTION_ORIGINAL_OUTSIDE_KSEF. Sending to KSeF works as before. Guide: Correcting documents. - Correction of an advance correction.
FakturaKorygujacaZaliczkowacan correct a previous advance correction: the order and the advance before the correction are the state after it.
2026-10-09: cause and type of a correction, limit of the correction reason
- Cause of a correction (
correctionCause) and its KSeF type (correctionType). A correction can say why you issue it:after_sale(an event after the sale: discount, return, complaint) ormistake(an error on the corrected invoice). From the cause and the amounts Fakturnia works out theTypKorektysent to KSeF, until now always2;correctionType(1,2,3) sets it by hand.POST,PUTandPATCH /documentsaccept both fields, andGET /documents/{id}and the document webhooks return them. The cause also decides the period of the correction in the app's reports (VAT register, JPK_V7, KPiR). Integrations that do not send the new fields work as before. Guide: Correcting documents. - Correction reason up to 256 characters. That is what KSeF accepts in
PrzyczynaKorekty. A longercorrectionReasonnow gets a validation error right away (400onPOST,422onPUTandPATCH) instead of a rejection by KSeF when sending.
2026-10-02: KSeF connection with a token
- KSeF token as a connection method.
POST /ksef/connectionacceptsconnectionType: TOKENwith atokengenerated in the KSeF Taxpayer Application, or a certificate as before (connectionType: CERTIFICATE). Saving one method replaces the other.GET /ksef/connectionreportsconnectionType,hasTokenandhasCertificate.
2026-10-01: webhooks for documents from the app and from KSeF, rate limits, unique numbers
document.createdfor documents created in the app. A document saved in the web or mobile app (drafts and warehouse documents included) firesdocument.created, like a document from the API, MCP or a recurring rule. A correction issued in the app also firesdocument.updatedfor the corrected invoice. You no longer need to pollGET /documentsto see documents issued in the app. Guide: Webhooks.- Issuing a draft in the app fires
document.updated. The same event arrives when a document is turned back into a draft and when itsisSent,isPrintedorisDownloadedmark changes in the app (the first print or download included), always only on a real change. An integration knows right away when a draft became an issued document (isDraft: false). - Invoices downloaded from KSeF:
document.ksefImported. A KSeF sync reports new invoices (purchase invoices and sales invoices issued outside Fakturnia) with one event carryingdata.documentIds, up to 100 ids per delivery; a larger import arrives as several deliveries. These invoices do not firedocument.created. sourceanddirectionon documents.GET /documentsandGET /documents/{id}returnsource(localorksef) anddirection(income,expenseororder), so a purchase invoice from KSeF is not mistaken for your own sale.- More events from the app.
document.updatedafter a warehouse release is confirmed or reverted, after the last correction is deleted (for the corrected invoice), after a WZ is issued for an invoice (for the invoice), after a recurring rule e-mails its document and when a KSeF sync adds a KSeF number;client.createdfor a contractor saved from the buyer data of an API or MCP document;client.updatedwhen e-mail addresses are saved on a contractor. - Rate limits count per application. The counters in the Rate limits table now belong to the application (API account) identified by the token, not to the IP address, so several integrations behind one NAT no longer share a budget. A new general limit of 240 requests per minute per IP address is checked before authentication; requests with a missing, invalid or expired token count only against it. The
429 RATE_LIMIT_EXCEEDEDcode and the headers are unchanged. - Document numbers are unique across the account.
POST /documentsandPUT/PATCH /documents/{id}return409 DOCUMENT_NUMBER_EXISTSalso when a document of another type (e.g. a proforma and a proforma without VAT sharing a symbol) or a document moved to another month already has the same full number.PUTandPATCHcheck this when you change the number, and the message inerrors[0]names the document that holds it. - The document schema in the OpenAPI spec lists every field the API returns:
isDraft,invoiceName,externalSource,externalOrderId,externalOrderNumber,correctionAdvanceAmountAfter,correctionSettlementAmountAfter,ksefNumber,ksefReferenceNumber,ksefStatusandksefSent. API responses did not change: these fields were already there.
2026-09-27 (spec version 1.3.0): warehouse documents and account defaults
- Warehouse documents through the API.
POST /warehouse/documentsissues WZ, PZ, PW, RW and MM with catalogue lines and books the movements;POST /warehouse/documents/validatereturns a preview with the stock before and after. New scopewarehouse:documents:create. Guide: Warehouse. - Missing goods block an issue. WZ, RW and MM (including
wz-from-invoice) that would take stock below zero get422 STOCK_SHORTAGE, like in the app;allowNegativeStock: trueissues them anyway. - WZ for an invoice gets the WZ symbol and the account settings, checks the warehouse (
422 WAREHOUSE_INVALID) and stores the WZ number on the invoice (print and KSeF). - Account defaults when creating documents: comments, signatures, place of issue, automatic annotations (split payment with the VAT account, margin), exemption basis for the zw rate, payment method and status, line VAT rate, PKWiU display. New field
useAccountDefaults, previewpreview.appliedDefaultsandpreview.resolved. Guide: Creating documents. - Corrections take the buyer, receiver, currency and annotations from the corrected invoice; an invoice with a correction, a settled advance invoice and an order with advance invoices cannot be changed or deleted (
409 DOCUMENT_CORRECTED,409 ADVANCE_INVOICE_SETTLED,400 ORDER_HAS_ADVANCE_INVOICES). - Advance invoice without lines (the lines are the split of the advance) and without a sale date; proforma without VAT always has 0 VAT.
- KSeF: the margin procedure reaches the XML (
P_PMarzywith the procedure flag); an unknown procedure number is a validation error. A VAT exemption enabled without a type or legal basis is rejected. - Products: warehouse fields
productType,sku,ean,purchasePricein reads, creation and updates (updates only the ones sent);quantityoptional on creation. - Warehouse documents through
/documents: deleting reverses the movements, changing the date moves them, changing the lines returns409 WAREHOUSE_LINES_LOCKED. A stock adjustment withquantity: 0andunitCostis a revaluation (WYCENA).
2026-09-26: MCP server
- MCP server for AI assistants.
https://prod.api.fakturnia.pl/mcp(sandbox:https://sandbox.api.fakturnia.pl/mcp): ChatGPT, Claude, Claude Code and custom agents work on a user's account after an OAuth 2.1 sign-in (RFC 9728/8414 discovery, PKCE, dynamic registration, client ID metadata documents, refresh token rotation) or with anfmcp_…key. Tools generated from this specification plus guided document issuing (prepareDocument,issueDocument),confirm=trueon irreversible operations, employee permissions, plan gate. Guide: MCP server.
2026-09 (spec version 1.2.0)
- The REST API is a MAX plan module. API accounts, every
/external/v1endpoint and webhooks require an active MAX plan. The token endpoint answers403 access_deniedwitherror_code: SUBSCRIPTION_REQUIRED, calls with a token403 SUBSCRIPTION_REQUIRED. Described in Authentication. - Stable error codes across the envelope.
401returnsUNAUTHORIZEDorTOKEN_EXPIRED,403without a scopeNO_PERMISSIONS,429RATE_LIMIT_EXCEEDED; the explanatory sentence moves toerrors[0]. Body validation errors carry theVALIDATION_ERRORcode, usually with status422; creating documents (warehouse documents included) answers400for request-shape problems, so treat both statuses as a validation failure. New code table in Errors. - Revoking an API account and the IP allowlist take effect immediately, on every call, not only when the token expires (
401 UNAUTHORIZED,403 FORBIDDEN). - Webhooks: full management.
POST /webhookswith a choice of events,GET/PATCH/DELETE /webhooks/{id}, secret rotation, delivery history (/deliveries) and a test ping (/test). New scopeswebhooks:updateandwebhooks:delete. Guide: Webhooks. - Webhooks: new delivery body. Every delivery carries an
id(also in theX-Webhook-Deliveryheader) and adatablock with the id named after the resource type (documentId,clientId, ...).resourceId/resourceIdsstay for compatibility. SchemaWebhookEventPayloadin the spec. - New events
document.ksefRejected(KSeF rejected the document or the send failed) anddocument.paymentStatusChanged(payment marked or reverted).document.sentToKSeFnow also fires for sends from the app and the queue, anddocument.updatedafter an order link. - Email accounts (read-only).
GET /email-accountsandGET /email-accounts/{id}with the scopesemail-accounts:browseandemail-accounts:read; no secrets. Guide: Email accounts. - Complete OpenAPI specification. Every operation has a description, a response schema with the shape of
data, a request body schema with an example, and documented401/403/429/500. New headersX-Request-ID,X-RateLimit-*,Retry-After,Idempotent-Replayed. The Postman collection takes request examples from the spec. - History through the API.
GET /documents/{id}/history(document journal),GET /activity(whole-account activity, new scopeactivity:read),GET /employees/{id}/activity(employee activity) andGET /warehouse/movements(stock ledger). Guide: History & activity. - New reads by id:
GET /warehouse/{id},GET /employees/{id}; the stock report acceptsproductId. - Pagination for lists that lacked it:
GET /recurring-rules,GET /recurring-rules/{id}/historyandGET /webhooks/{id}/deliveriesreturncurrentPage,itemsPerPage,totalCount,totalPages(limitstill works as an alias ofitemsPerPage). - Lists up to 100 items per page (
itemsPerPage, previously 20) inGET /documents,/clients,/products. - Deletes return
data.idfor documents, contractors and products too;DELETE /documents/{id}/external-referencereturns the cleared link fields.
2026-07
- Recurring documents in the API. New
/recurring-rulesendpoints: rule list with a summary (statuses, next generation, monthly recurring gross), rule details, generation history, and pause/resume. Newrecurring:*scopes (3). Requires the MAX plan. Guide: Recurring documents. - Warehouse module in the API. New
/warehouseendpoints: warehouses (CRUD), stock adjustments (stocktaking), a stock report with theasOfparameter and automatic WZ documents for sales invoices. Requires the MAX plan. Guide: Warehouse. - Employees and permissions in the API. New
/employeesendpoints: permission registry, creating and updating employee accounts, deactivation and deletion. Guide: Employees & permissions. - New scopes:
warehouse:*(7) andemployees:*(4), described in Authentication. - The
documentTypefilter on the document list now also accepts warehouse types (e.g.WZ). - Document list filters.
GET /documentsacceptsdocumentType(a single type or a comma-separated list) and an issue-date range viadateFrom/dateTo. See Pagination and filtering. - The Postman collection and the CLI cover the whole API (products, settings, webhooks, KSeF connection,
auth/me, company lookup by NIP, order references). - New guides. Clients, Products, Settings, KSeF connection, Order references and Company lookup.
2026-06
- Beta available in the sandbox environment. The API can be tested at
sandbox.app.fakturnia.pl. - Amounts unified to grosz-exact, round half-up. Per-line and per-document totals now match the
fakturnia-sharedengine exactly.netValue + amountOfVat === grossValueon every line. FakturaRozliczeniowanow derivesgrossSumfromsettlementAmount(remaining to pay = lines − linked advances) instead of the full line total; linked advance metadata is populated automatically.FakturaZaliczkatotals derive from the proportional advance breakdown (grossSum === advancePaymentAmount).FakturaProforma/FakturaProformaBezVATaccepted byPOST /documents.- Advance/settlement corrections (
FakturaKorygujacaZaliczkowa,FakturaKorygujacaRozliczeniowa) compute the amount delta with proportional VAT. PUTandPATCH /documents/{id}; multiplebankAccounts[]on create/update.
Versioning policy
- Path-versioned.
v1is stable. Av2would only appear for breaking changes. - Additive within v1. New optional request fields and new response fields can appear without a version bump.
- Deprecations are announced here with a migration window before removal.
Subscribe to changes by watching this page or the OpenAPI spec (its info.version tracks releases).