Poland E-Invoice KSeF Fa(3)
How to get “API Key” from Portal ?
To obtain the API key to be used in the request body of the login endpoint, navigate to Settings > ERP Management > API Management in the Portal and use the "Generate" button.
Login and Authorization Configuration
Technical Details
| Property | Value |
|---|---|
| Endpoint | /auth/login |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | None (Initial access) |
Request Body (JSON)
The following fields are used to define login criteria:
| Field | Type | Description |
|---|---|---|
| apiKey | String | A unique key assigned specifically to the user for portal access, verifying the system identity. (it is explained in previous section “How to get API Key from portal”) |
| String | The registered email address in the system belonging to the authorized user performing the operation. |
Response Details
Upon a successful request, a 200 OK code is returned with the following details:
| Field | Type | Description |
|---|---|---|
| jwt | — | The secure session token that must be used as a 'R-Auth' API Key in all subsequent API calls. |
| expirationDate | DateTime | Indicates the exact time the session key will expire; the ERP system can use this data to manage automatic re-login processes. |
The JWT token successfully obtained during the authentication step (auth/login) acts as a key to access the secure endpoints of the APIs. After the first successful login, the JWT token obtained from the response of a successful login is used as the R-Auth value in the authorization section of other queries. This configuration ensures that every data exchange between the ERP and the portal occurs over an authenticated and secure channel.
Technical Details
| Property | Value |
|---|---|
| Key | Enter R-Auth in the Key field. |
| Value | {{apiKey}} or {{jwt}} (Copy the jwt string returned from the login endpoint.) |
| Header Setting | Navigate to the "Headers" tab of the request to be sent. |
1. Introduction
efakturapolska is a cloud-based e-invoicing management portal developed by Melasoft, fully aligned with Poland's e-invoicing requirements and designed to support integration with the KSeF (Krajowy System e-Faktur — National e-Invoice System) framework, operated by the Polish Ministry of Finance (Ministerstwo Finansów) under the National Revenue Administration (Krajowa Administracja Skarbowa — KAS).
This API documentation is intended to help your ERP systems integrate smoothly with Poland's e-invoicing process.
Our portal abstracts complex invoice data structures and KSeF transmission workflows, providing developers with an easy-to-use, secure, and scalable interface. By using the efakturapolska API, you can submit invoices asynchronously, track real-time processing statuses, manage incoming invoices, and automatically process technical responses and validation results — including official acceptance receipts (UPO — Urzędowe Poświadczenie Odbioru) — back into your ERP system.
Our compliance-oriented architecture supports the legal validity of every document, ensures data integrity, and provides an end-to-end traceable audit trail.
efakturapolska also manages the submission of invoices to KSeF as part of the compliance flow. After validation checks are completed, invoices are transmitted asynchronously to KSeF and the acceptance or rejection result is returned with detailed status information for automatic processing in your ERP
2. Authentication POST
Purpose of Use: The /auth/login endpoint serves as the central authentication gateway for the Docnova platform. It supports two usage scenarios:
-
API Key Authentication: Sending only an apiKey in the request body causes the system to issue a JWT access token for the associated account. This approach is recommended for automation systems, background jobs, or integration services that do not require direct user interaction.
-
API Key + Email Authentication: When an email field is sent alongside the apiKey, the login is performed within the context of a specific user. This is used in multi-user API key scenarios to specify which user is performing the operation.
A successful authentication returns a JWT Access Token (valid 24 hours, used with the R-Auth header on protected endpoints), a Refresh Token (for /auth/refresh when the access token expires), a Company List, User Profile, and MFA Status metadata.
Endpoint Information
| Property | Value |
|---|---|
| URL | /auth/login |
| Method | POST |
| Authorization | Not required (public endpoint) |
Example Request
curl --location 'https://api-stage.docnova.ai/auth/login' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--data-raw '{
"apiKey": "{{your_api_key}}",
"email": "user@example.com"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | Unique key used for API-based authentication. Sufficient on its own when email is not provided. |
| string | Conditional | Email address of the user to authenticate as. Sent alongside apiKey when a specific user context is required. |
Note: The password, recaptchaToken, portalType, and currentCountry fields are not applicable to the API key authentication flow and have been excluded from this documentation.
Parameter Values
| Field | Accepted Values | Example |
|---|---|---|
| apiKey | System-generated alphanumeric API key string | YOUR_API_KEY |
| Valid email format string | user@example.com | |
| Content-Type | application/json | application/json |
Responses
200 - Login Successful
Full Response (AccountInfo)
{
"id": "a1b2c3d4-e5f6-7890-abcd-...",
"superAdmin": false,
"companies": [
{
"id": "f0e1d2c3-b4a5-6789-0fed-...",
"name": "Example Company GmbH",
"taxNumber": "5252800076",
"vatNumber": "PL5252800076",
"email": "info@example.com",
"country": "PL",
"credit": 500,
"remainingDocumentPercentage": 75.5,
"remainingPromotionDays": 14,
"sftp": false,
"trialUsed": true
}
],
"jwt": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyQGV4YW1wbGUuY29tIn0.xxxxx",
"expirationDate": "2026-02-28T10:30:00.000+00:00",
"refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4=",
"refreshTokenExpiration": "2026-03-01T10:30:00.000+00:00",
"user": {
"id": "a1b2c3d4-e5f6-7890-abcd-...",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"phoneNumber": "+49123456789",
"mailLang": "EN",
"lastLoginTime": "2026-02-27T08:00:00"
},
"mfaEnabled": false,
"mfaType": null,
"secretImageUri": null,
"lastCompanyId": "f0e1d2c3-b4a5-6789-0fed-...",
"active": true,
"isAppLogin": false,
"requiresRecaptchaV2": false,
"message": null
}
Response Fields
Account Information Fields
| Field | Type | Description |
|---|---|---|
| id | String | User unique identifier |
| superAdmin | Boolean | Whether user has super admin privileges |
| companies | Array<AuthorizedCompany> | List of companies user is authorized to access |
| jwt | String | JWT access token. Used in R-Auth header for API requests |
| expirationDate | DateTime | JWT token expiration date |
| refreshToken | String | Refresh token for obtaining new access tokens |
| refreshTokenExpiration | DateTime | Refresh token expiration date |
| user | Object | User detail information |
| mfaEnabled | Boolean | Whether multi factor authentication is enabled |
| mfaType | Enum | MFA type (GOOGLE, WHATSAPP) |
| secretImageUri | String | Google Authenticator QR code URI |
| lastCompanyId | String | Last selected company ID |
| requiresRecaptchaV2 | Boolean | Whether reCAPTCHA v2 verification is required |
| message | String | Status message (e.g., "MFA required") |
| active | Boolean | Whether user account is active |
| isAppLogin | Boolean | Whether this is a mobile app login |
Parameter Values Reference Table
currentCountry Values
| Value | Description |
|---|---|
| DE | Germany |
| AT | Austria |
| RO | Romania |
| KZ | Kazakhstan |
| TR | Turkey |
| FI | Finland |
| FR | France |
| IT | Italy |
| NL | Netherlands |
| ES | Spain |
| SE | Sweden |
| PL | Poland |
| BE | Belgium |
| DK | Denmark |
| NO | Norway |
| MY | Malaysia |
| SG | Singapore |
| AU | Australia |
| NZ | New Zealand |
| JP | Japan |
| EG | Egypt |
| RS | Serbia |
| GLOBAL | Global (default) |
Company Information Fields
| Field | Type | Description |
|---|---|---|
| id | String | Company unique identifier |
| name | String | Company name |
| taxNumber | String | Tax number |
| vatNumber | String | VAT number |
| String | Company email address | |
| website | String | Company website |
| address | String | Address |
| city | String | City |
| state | String | State or Region |
| country | Enum | Country code |
| postalCode | String | Postal code |
| phoneNumber | String | Phone number |
| faxNumber | String | Fax number |
| credit | Integer | Available credit |
| userCount | Integer | Total user count |
| portalType | Enum | Portal type |
| mailLanguage | Enum | Email language |
| currencyCode | String | Currency code |
| sftp | Boolean | Whether SFTP integration is active |
| isSubCompany | Boolean | Whether it's a sub company |
| featureAllowed | Boolean | Whether feature access is granted |
| participants | Array | Peppol participant information |
User Information Fields
| Field | Type | Description |
|---|---|---|
| id | String | User unique identifier |
| String | User email address | |
| firstName | String | User first name |
| lastName | String | User last name |
| phoneNumber | String | User phone number |
| photoUrl | String | User photo URL |
| mailLang | Enum | User email language |
| isSuperAdmin | Boolean | Whether user has super admin privileges |
| lastLoginTime | DateTime | Last login time |
| featureAllowed | Boolean | Whether feature access is granted |
Enum Values
mfaType Values
| Value | Description |
|---|---|
| Google Authenticator verification | |
| WhatsApp verification |
portalType Values
| Value | Description |
|---|---|
| DEFAULT | Default portal |
| RECHNUNG | Germany main portal |
| KZ | Kazakhstan portal |
| RO | Romania portal |
| AU | Australia portal |
| AT | Austria portal |
| BE | Belgium portal |
| DK | Denmark portal |
| EG | Egypt portal |
| FI | Finland portal |
| FR | France portal |
| IT | Italy portal |
| MY | Malaysia portal |
| NL | Netherlands portal |
| NO | Norway portal |
| PL | Poland portal |
| RS | Serbia portal |
| SE | Sweden portal |
| SG | Singapore portal |
mailLanguage Values
| Value | Description |
|---|---|
| DE | German |
| EN | English |
| TR | Turkish |
| RO | Romanian |
| PL | Polish |
| FR | French |
| IT | Italian |
| ES | Spanish |
| NL | Dutch |
400 - Bad Request
The request body does not conform to JSON format, a required field is missing, or a field value is not of the expected type.
{
"errorMessage": "Required request body is missing or malformed",
"errorType": "errorClientMessage",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "b2c3d4e5-f6a1-2345-6789-...",
"timestamp": "2026-02-27T10:30:00.123",
"path": "/auth/login",
"details": null,
"validationErrors": null
}
401 - Unauthorized
The provided apiKey is invalid, expired, or not registered in the system. Alternatively, the combination of email and apiKey does not match any existing record.
{
"errorMessage": "Invalid login attempt!",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "c3d4e5f6-a1b2-3456-7890-...",
"timestamp": "2026-02-27T10:30:00.123",
"path": "/auth/login",
"details": null,
"validationErrors": null
}
422 - Unprocessable Entity
The request is technically valid but violates a business rule. Examples include: account suspended, email not verified, or account deactivated.
{
"errorMessage": "Account is not active or registration is not confirmed.",
"errorType": "errorClientMessege",
"errorTitle": "UNPROCESSABLE_ENTITY",
"status": 422,
"errorId": "e5f6a1b2-c3d4-5678-90ab-...",
"timestamp": "2026-02-27T10:30:00.123",
"path": "/auth/login",
"details": null,
"validationErrors": null
}
500 - Internal Server Error
An unexpected server-side error occurred. This may be caused by a database connectivity issue, service outage, or configuration fault. If the condition is transient, retry the request; if it persists, notify the system administrator.
{
"errorMessage": "An unexpected error occurred",
"errorType": "SERVER_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "f6a1b2c3-d4e5-6789-0abc-...",
"timestamp": "2026-02-27T10:30:00.123",
"path": "/auth/login",
"details": null,
"validationErrors": null
}
3. Search Processing History POST
Purpose of Use: This endpoint is used to query document processing records (invoices, waybills, etc.) belonging to a company with advanced filtering. It is designed to monitor document processing lifecycles for documents received or sent via ERP systems, portals, or the Peppol network – enabling teams to identify failed operations and audit batch processes.
Primary use cases include:
- Error management: Identifying records in FAILED, SENDING_FAILED, or PERMANENT_FAILED states
- Monitoring dashboards: Reporting the processing status of inbound/outbound documents within a date range
- Source-based filtering: Listing documents originating from a specific integration channel such as ERP, PORTAL, or PEPPOL
- Batch auditing: After bulk submissions, verifying which documents were processed and which remain pending
Results are returned in a paginated (Pageable) format. Default sorting is createdAt DESC.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/document-process/search |
| Method | POST |
| Authorization | JWT Bearer Token via r-auth header |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/document-process/search?paged=true&pageNumber=0&pageSize=20&sort.sorted=true&sort.unsorted=false' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"companyId": "<COMPANY_UUID>",
"createdAt": {
"from": "2025-01-01",
"to": "2026-02-28"
},
"direction": "OUTGOING",
"source": "ERP",
"status": "FAILED"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | UUID | Yes | Unique identifier of the company to query |
| direction | String (Enum) | No | Document direction. See allowed values below |
| source | String (Enum) | No | Source system that originated the document. See allowed values below |
| status | String (Enum) | No | Document processing status. See allowed values below |
| filename | String | No | Exact match filter by filename |
| createdAt | DateRange | No | Date range filter based on record creation time |
| createdAt.from | String (ISO 8601) | No | Range start date — format: YYYY-MM-DD |
| createdAt.to | String (ISO 8601) | No | Range end date — format: YYYY-MM-DD. The end of the specified day (23:59:59.999) is inclusive |
Enum Values
Document Direction
| Value | Description |
|---|---|
| INCOMING | Inbound document (received invoice, waybill, etc.) |
| OUTGOING | Outbound document (sent invoice, waybill, etc.) |
Processing Status
| Value | Description |
|---|---|
| PENDING | Queued, not yet processed |
| PROCESSING | Currently being processed |
| FAILED | Processing failed, awaiting retry |
| SENDING_FAILED | Transmission to target system failed |
| PERMANENT_FAILED | Permanent failure — will not be retried by the system |
| COMPLETED | Successfully completed |
Target System
| Value | Description |
|---|---|
| ERP | ERP system integration |
| PORTAL | Upload via web portal |
| PORTAL_OCR | Automatic recognition via portal OCR |
| Document received via email | |
| EMAIL_OCR | Email attachment processed via OCR |
| PEPPOL | Peppol e-document network |
| SFTP | Transfer via SFTP protocol |
| KSEF | Poland KSeF e-invoice system |
| ANAF | Romania ANAF e-invoice system |
| ETA | Egypt ETA e-invoice system |
| LHDNM | Malaysia LHDNM e-invoice system |
| NEMHANDEL | Denmark NemHandel infrastructure |
| ERACUN | Slovenia e-Račun system |
| RS_API | Direct REST API integration |
| SHOPIFY | Shopify e-commerce integration |
| AMAZON_SP | Amazon Selling Partner API integration |
| EBAY | eBay integration |
| HUBSPOT | HubSpot CRM integration |
| LAZADA | Lazada e-commerce integration |
| STRIPE | Stripe payment integration |
| HARVEST | Harvest time-tracking integration |
| SERVICE | Internal service-based processing |
Responses
200 - Successful Response
{
"content": [
{
"trackingId": "a1b2c364-e5f6-7890-abcd-...",
"companyId": "341ea08e-930a-46f9-9025-...",
"direction": "OUTGOING",
"documentType": "KSEF",
"waybillType": null,
"source": "ERP",
"target": null,
"status": "FAILED",
"filename": "Invoice_2025_001.xml",
"invoiceNumber": "INV-2025-0001",
"documentId": "f1e2d3c4-b5a6-7890-abcd-...",
"sendingResult": null,
"errorType": null,
"errors": ["Target endpoint unreachable", "Retry limit exceeded"],
"additionalData": null,
"createdAt": "2025-03-15T08:30:00",
"statusUpdatedAt": "2025-03-15T08:32:15",
"completedAt": null
}
],
"totalElements": 47,
"totalPages": 3,
"number": 0,
"size": 20,
"numberOfElements": 20,
"first": true,
"last": false,
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
}
}
Response Fields
Pagination Fields
| Field | Type | Description |
|---|---|---|
| content | Array<DocumentProcessRecord> | List of matching records |
| totalElements | Long | Total number of records matching the filters |
| totalPages | Integer | Total number of pages |
| number | Integer | Current page number (0-indexed) |
| size | Integer | Page size |
| numberOfElements | Integer | Number of records on the current page |
| first | Boolean | Whether this is the first page |
| last | Boolean | Whether this is the last page |
| sort | Object | Applied sorting information |
Document Process Record Fields
| Field | Type | Description |
|---|---|---|
| trackingId | UUID | Unique tracking identifier for the document processing record |
| companyId | UUID | Identifier of the company the document belongs to |
| direction | String (Enum) | Document direction: INCOMING or OUTGOING |
| documentType | String (Enum) | Document type (invoice, waybill, etc.) |
| waybillType | String (Enum) | Waybill type (populated only for waybill documents) |
| source | String (Enum) | Source system that originated the document |
| target | String (Enum) | Target system the document was delivered to |
| status | String (Enum) | Current processing status |
| filename | String | Name of the uploaded or processed file |
| invoiceNumber | String | Invoice number |
| documentId | UUID | Reference identifier of the processed document |
| sendingResult | String | Transmission result detail (success or error message) |
| errorType | String (Enum) | Error category for failed records |
| errors | Object | Error details. May be ValidationError[], String[], or a plain String |
| additionalData | Object | Country-specific or integration-specific additional metadata |
| createdAt | String (ISO 8601 DateTime) | Timestamp when the record was created |
| statusUpdatedAt | String (ISO 8601 DateTime) | Timestamp of the most recent status update |
| completedAt | String (ISO 8601 DateTime) | Timestamp when processing completed (null if not yet completed) |
400 - Bad Request
Returned when companyId is not provided or is in an invalid UUID format.
{
"message": "Validation failed",
"errorClientMessage": "Required fields are missing",
"validationErrors": [
{
"field": "companyId",
"message": "must not be null"
}
],
"details": null
}
400 - Bad Request — Invalid Enum Value
Returned when an undefined value is passed to direction, source, or status.
{
"message": "JSON parse error: Cannot deserialize value of type 'DocumentProcessStatus' from String \"INVALID_STATUS\"",
"errorClientMessage": "Invalid value provided for field 'status'. Accepted values: PENDING, PROCESSING, FAILED, SENDING_FAILED, PERMANENT_FAILED, COMPLETED",
"validationErrors": null,
"details": "Field: status, Rejected value: INVALID_STATUS"
}
400 - Bad Request — Invalid Date Format
Returned when createdAt.from or createdAt.to does not conform to YYYY-MM-DD format, or a future date is provided (@PastOrPresent constraint violation).
{
"message": "Validation failed",
"errorClientMessage": "Date format is invalid or the date is in the future",
"validationErrors": [
{
"field": "createdAt.from",
"message": "must be a date in the past or in the present"
}
],
"details": null
}
401 - Unauthorized
Returned when the R-Auth header is absent or the token signature cannot be verified.
{
"message": "Unauthorized",
"errorClientMessage": "Authentication token is missing or invalid",
"validationErrors": null,
"details": "JWT signature does not match"
}
401 - Unauthorized — Token Expired
Returned when the JWT token's exp claim is in the past.
{
"message": "Unauthorized",
"errorClientMessage": "Authentication token has expired",
"validationErrors": null,
"details": "JWT expired at 2025-01-01T00:00:00Z"
}
403 - Forbidden
Returned when the authenticated user does not hold any of the required roles (ADMIN, INCOMING_INVOICE_DISPLAY, OUTGOING_INVOICE_DISPLAY) for the specified company.
{
"message": "Forbidden",
"errorClientMessage": "You do not have permission to access this company's data",
"validationErrors": null,
"details": "User does not have required authority for company: 343ea08e-930a-4619-9029-a13ee3d482b6"
}
500 - Internal Server Error
Returned when a database connection failure or unexpected system error occurs.
{
"message": "Internal Server Error",
"errorClientMessage": "An unexpected error occurred. Please try again later.",
"validationErrors": null,
"details": null
}
4. Document Status GET
Purpose of Use: The GET /invoice/document-status/{trackingId} endpoint is used to query the processing status of documents (invoices, waybills, etc.) that were submitted asynchronously.
When a document is submitted through any of the send-document-async, send-document-async-json, send-by-file-async, or send-portal-new-async endpoints, the system immediately returns a trackingId and begins processing the document in the background.
Polling stops when the status becomes COMPLETED or FAILED.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/document-status/{trackingId} |
| Method | GET |
| Authorization | JWT Bearer Token via R-Auth header |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/document-status/{trackingId}' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>'
Request Parameters
Path Parameter
| Field Name | Type | Required | Format | Description |
|---|---|---|---|---|
| trackingId | UUID | Yes | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX | The tracking ID returned by the async document submission. Unique identifier for the document processing record |
Enum Value
DocumentProcessStatus Values
| Value | Description |
|---|---|
| PENDING | Process queued, not yet started. |
| PROCESSING | Document is actively being processed. |
| COMPLETED | Process completed successfully. |
| FAILED | Process failed (may be retried). |
| SENDING_FAILED | Document was prepared but could not be sent to the target system. |
| PERMANENT_FAILED | Process permanently failed, will not be retried (terminal state). |
DocumentType Values
| Value | Description |
|---|---|
| INCOMING | Inbound document. |
| OUTGOING | Outbound document. |
DataType Values
| Value | Description |
|---|---|
| PEPPOL_BIS | Peppol BIS invoice format (UBL-based). |
| XRECHNUNG | German XRechnung invoice format (UBL). |
| XRECHNUNG_CII | XRechnung CII format. |
| RO_IFACTURA | Romanian e-invoice format. |
| MY_INVOIS | Malaysian MyInvois format. |
| MY_PINT | Malaysian PINT format. |
| DK_OIOUBL | Danish OIOUBL format. |
| EG_INVOICE | Egyptian e-invoice format. |
| HR_INVOICE | Croatian eRačun format. |
| UAE_PINT | UAE PINT format. |
| ZUGFeRD | ZUGFeRD (PDF/A-3 embedded XML) format. |
| FACTUR_X | French Factur-X format (ZUGFeRD family). |
| CII | UN/CEFACT CII format. |
| CID | CID invoice format. |
| KZ_ESF_V2 | Kazakhstan ESF v2 format. |
| KSEF | Polish KSeF format (online model). |
| KSEF_OFFLINE | Polish KSeF format (offline model). |
InvoiceSource Values
| Value | Description |
|---|---|
| ERP | Enterprise resource planning system integration. |
| PORTAL | Submission via web portal. |
| PORTAL_OCR | Document processed via portal OCR. |
| Document received via email. | |
| EMAIL_OCR | Document processed via email OCR. |
| PEPPOL | Document received from Peppol network. |
| SFTP | SFTP integration. |
| KSEF | Polish KSeF system. |
| ANAF | Romanian ANAF system. |
| ETA | Egyptian ETA system. |
| FRACUN | Croatian eRačun system. |
| LHDNM | Malaysian LHDNM system. |
| NEMHANDEL | Danish NemHandel system. |
| RS_API | Serbian API integration. |
| SERVICE | Internal service channel. |
| HARVEST | Harvest time tracking integration. |
| SHOPIFY | Shopify e-commerce integration. |
| AMAZON_SP | Amazon Selling Partner integration. |
| EBAY | eBay integration. |
| HUBSPOT | HubSpot CRM integration. |
| LAZADA | Lazada marketplace integration. |
| STRIPE | Stripe payment integration. |
Responses
200 - Successful Response
{
"trackingId": "f3972835-4692-4fda-ae77-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "KSEF",
"waybillType": null,
"source": "ERP",
"target": null,
"status": "COMPLETED",
"filename": "invoice_2024_001.xml",
"invoiceNumber": "INV-2024-001",
"documentId": "d9e8f7a6-b5c4-3210-fedc-...",
"sendingResult": "SUCCESS",
"errorType": null,
"createdAt": "2024-11-15T10:30:00",
"statusUpdatedAt": "2024-11-15T10:31:45",
"completedAt": "2024-11-15T10:31:45",
"errors": null,
"additionalData": {
"sessionReferenceNumber": "20250615-SE-ABC123",
"invoiceReferenceNumber": "20250615-IR-DEF456",
"ksefNumber": "1234567890-20250615-..."
}
}
Error State Response Example (FAILED)
{
"trackingId": "f3972835-4692-4fda-ae77-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "KSEF",
"waybillType": null,
"source": "ERP",
"target": null,
"status": "FAILED",
"filename": "Invoice_2024_002.xml",
"invoiceNumber": "INV-2024-002",
"documentId": null,
"sendingResult": null,
"errorType": "VALIDATION_FAILED",
"createdAt": "2024-11-15T11:00:00",
"statusUpdatedAt": "2024-11-15T11:00:12",
"completedAt": null,
"errors": [
{"field": "invoiceDate", "code": "NOT_NULL", "message": "Invoice date cannot be null"},
{"field": "buyerParty", "code": "NOT_EMPTY", "message": "Buyer party information is required"}
],
"additionalData": null
}
Response Fields
| Field | Type | Description |
|---|---|---|
| trackingId | UUID | Document tracking ID. Same as the trackingId in the request. |
| companyId | UUID | The identifier of the company that owns this document. |
| direction | DocumentType | Direction of the document. See DocumentType values. |
| documentType | DataType | Format/type of the document. See DataType values. |
| waybillType | WaybillDataType | Sub-type if the document is a waybill. May be null for Invoice processes. |
| source | InvoiceSource | Source channel through which the document entered the system. See InvoiceSource values. |
| target | InvoiceSource | Target channel the document is delivered to. |
| status | DocumentProcessStatus | Current processing status. See DocumentProcessStatus values. |
| filename | String | Original file name. |
| invoiceNumber | String | Invoice number contained in the document. |
| documentId | UUID | Internal identifier of the saved document in the system. |
| sendingResult | String | Raw result message received from the external system during delivery. |
| errorType | ErrorType | Error type if any. See ErrorType values. |
| createdAt | LocalDateTime | Creation time of the document process record (ISO 8601). |
| statusUpdatedAt | LocalDateTime | Time of the last status update (ISO 8601). |
| completedAt | LocalDateTime | Time the process was completed (ISO 8601). null if not yet completed. |
| errors | Object | Error information. Varies by type: List<ValidationError>, List<string>, or string. |
| additionalData | Object | Country specific additional metadata. Structure varies by country/document type (e.g., Poland KSeF: ksefNumber, Romania: submissionId) |
401 - Unauthorized
The R-Auth header is missing, expired, or has an invalid signature.
Returned when the token's exp claim has passed, the R-Auth header is absent, or the token signature cannot be verified.
{
"status": 401,
"error": "Unauthorized",
"message": "JWT token is expired or invalid"
}
404 - Not Found
The given trackingId was not found in the database (INVOICE_PROCESS_NOT_FOUND).
Returned when the trackingId format is valid (UUID) but no document process record exists for that ID in the system. This error may also be returned when querying a trackingId belonging to a different company.
{
"status": 404,
"message": "INVOICE_PROCESS_NOT_FOUND",
"data": null
}
500 - Internal Server Error
An unexpected system error occurred.
Returned on system-level failures such as database connectivity issues or unexpected exceptions in the service layer.
{
"status": 500,
"error": "Internal Server Error",
"message": "An unexpected error occurred"
}
5. Search Document With Filter POST
Purpose of Use: This endpoint allows multi-criteria search across e-invoices and electronic documents for registered companies, returning paginated results. It is designed for KSeF (Krajowy System e-Faktur — Poland's National e-Invoice System) integration.
Queries can be based on invoice status, date range, document direction (incoming/outgoing), and invoice format. The response includes an invoice list, total amount summaries, and record counts. It serves as a central search point for accounting reconciliation, status tracking, and reporting workflows.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/search-documents |
| Method | POST |
| Authorization | R-Auth: <JWT Token> |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/search-documents' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"companyId": "341ea08e-930a-46f9-9029-...",
"documentType": "OUTGOING",
"startDate": "2025-01-01",
"endDate": "2026-02-28",
"status": "KSEF_ACCEPTED",
"type": "KSEF",
"page": 1,
"size": 20
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | UUID | Yes | Unique identifier of the company to query |
| documentType | DocumentType | No | Document direction — incoming or outgoing invoice |
| type | DataType | No | Invoice format (KSeF, PEPPOL_BIS, XRECHNUNG, etc.) |
| status | InvoiceStatus | No | Invoice status filter |
| startDate | date (yyyy-MM-dd) | No | Search start date (inclusive) |
| endDate | date (yyyy-MM-dd) | No | Search end date (inclusive) |
| page | integer | No | Page number (0-based). Default: 0 |
| size | integer | No | Number of records per page. Default: 20, Max: 100 |
| tin | string | No | Filter by Tax Identification Number |
| uit | string | No | Filter by Unique Invoice Token |
| referenceDocument | string | No | Filter by reference document number |
Enum Value
documentType — Document Direction
| Value | Description |
|---|---|
| INCOMING | Received invoices |
| OUTGOING | Sent invoices |
type — Invoice Format (DataType)
| Value | Description |
|---|---|
| KSEF | Poland KSeF standard format |
| KSEF_OFFLINE | Poland KSeF offline format |
| PEPPOL_BIS | Peppol BIS 3.0 (UBL-based) |
| XRECHNUNG | Germany XRechnung (UBL) |
| XRECHNUNG_CII | Germany XRechnung (CII) |
| ZUGFERD | ZUGFeRD hybrid PDF/XML |
| FACTUR_X | France Factur-X (ZUGFeRD compliant) |
| RO_EFACTURA | Romania e-Factura |
| MY_INVOIS | Malaysia e-Invois |
| MY_PINT | Malaysia Peppol PINT |
| EG_INVOICE | Egypt ETA e-Invoice |
| HR_INVOICE | Croatia eRačun |
| UAE_PINT | UAE Peppol PINT |
| DK_OIOUBL | Denmark OIOUBL |
| CII | UN/CEFACT CII |
| CID | CID format |
| Unstructured PDF (paper/image invoices) | |
| KZ_ESF_V2 | Kazakhstan ESF v2 |
Responses
200 - Successful Response
{
"totalCount": 142,
"netTotal": 98540.00,
"Total": 121204.20,
"invoiceList": [
{
"id": "f3a1b2c4-0001-4abc-8def-...",
"companyId": "341ea08e-930a-46f9-9029-...",
"invoiceNumber": "FV/2025/001",
"status": "KSEF_ACCEPTED",
"documentType": "OUTGOING",
"type": "KSEF",
"supplierName": "Example Sp. z o.o.",
"supplierVat": "PL1234567890",
"supplierCountryCode": "PL",
"customerName": "Odbiorca S.A.",
"customerVat": "PL0987654321",
"customerCountryCode": "PL",
"taxExclusiveAmount": 1000.00,
"taxInclusiveAmount": 1230.00,
"payableAmount": 1230.00,
"currency": "PLN",
"issueDate": "2025-03-15",
"dueDate": "2025-04-14",
"statusTime": "2025-03-15T14:32:10",
"createdTime": "2025-03-15T13:00:00",
"sendViaPeppol": false,
"isActive": true,
"countrySpecificData": null
}
]
}
Response Fields
Invoice Object Fields
| Field | Type | Description |
|---|---|---|
| id | string (UUID) | Unique identifier of the invoice |
| companyId | string (UUID) | ID of the company the invoice belongs to |
| userId | string (UUID) | ID of the user who created the invoice |
| invoiceNumber | string | Invoice number |
| status | InvoiceStatus | Current status of the invoice |
| documentType | DocumentType | Document direction: INCOMING / OUTGOING |
| type | DataType | Invoice format |
| supplierName | string | Supplier / seller name |
| supplierId | string | Supplier system ID |
| supplierVat | string | Supplier VAT number |
| supplierCountryCode | string | Supplier country code (ISO 3166-1 alpha-2) |
| supplierEndpoint | string | Supplier Peppol endpoint address |
| customerName | string | Customer / buyer name |
| customerId | string | Customer system ID |
| customerVat | string | Customer VAT number |
| customerCountryCode | string | Customer country code (ISO 3166-1 alpha-2) |
| customerEndpoint | string | Customer Peppol endpoint address |
| taxExclusiveAmount | double | Amount excluding tax |
| taxInclusiveAmount | double | Amount including tax |
| lineExtensionAmount | double | Line total (before discounts) |
| payableAmount | double | Net payable amount |
| allowanceTotalAmount | double | Total discount amount |
| currency | string | Currency code (ISO 4217, e.g. PLN, EUR) |
| typeCode | string | Invoice type code (e.g. 380 - Commercial invoice) |
| issueDate | date | Invoice issue date (YYYY-MM-DD) |
| deliveryDate | date | Delivery date (YYYY-MM-DD) |
| dueDate | date | Payment due date (YYYY-MM-DD) |
| statusTime | datetime | Last status change timestamp (UTC) |
| localStatusTime | datetime | Last status change timestamp (local time) |
| createdTime | datetime | Record creation timestamp (UTC) |
| localCreatedTime | datetime | Record creation timestamp (local time) |
| lastUpdatedTime | datetime | Last update timestamp (UTC) |
| localLastUpdatedTime | datetime | Last update timestamp (local time) |
| fileName | string | Name of the uploaded file |
| errorMessage | string | Error description in case of failure |
| uploadAncarare | string | Romania ANAF upload ID |
| downloadAncarare | string | Romania ANAF download ID |
| source | InvoiceSource | Origin source of the invoice |
| sendViaPeppol | boolean | Whether the invoice was delivered via Peppol |
| profileType | ProfileType | ZUGFeRD profile type |
| ocrParser | OcrParser | OCR parsing engine used |
| isActive | boolean | Whether the record is active |
| paymentDetails | object | Payment details (may be hidden for certain statuses) |
| countrySpecificData | object | Country-specific additional data fields |
400 - Bad Request
Returned when an invalid parameter value is sent in the request body — e.g., an out-of-enum value for status or type, or a companyId that does not conform to UUID format.
{
"errorMessage": "Invalid value for field 'status'. KSEF_UNKNOWN",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-xxxx-xxxx-xxxx-000000000001",
"timestamp": "2026-02-28T10:15:00",
"path": "/invoice/search-documents",
"details": null,
"validationErrors": null
}
401 - Unauthorized
The R-Auth header is missing, the JWT token has expired, or the token is otherwise invalid.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "a1b2c3d4-xxxx-xxxx-xxxx-000000000002",
"timestamp": "2026-02-28T10:16:00",
"path": "/invoice/search-documents",
"details": null,
"validationErrors": null
}
404 - Not Found
No company is found for the given companyId, or the authenticated user does not have access to that company.
{
"errorMessage": "Company not found with id: 341ea08e-9302-4619-9029-a13ee3d482c6",
"errorType": "COMPANY_NOT_FOUND",
"errorTitle": "NOT_FOUND",
"status": 404,
"errorId": "a1b2c3d4-xxxx-xxxx-xxxx-000000000003",
"timestamp": "2026-02-28T10:17:00",
"path": "/invoice/search-documents",
"details": null,
"validationErrors": null
}
422 - Unprocessable Entity
The request is technically valid but cannot be processed due to a business rule violation — e.g., startDate is after endDate, or the company's license state does not permit the query operation.
{
"errorMessage": "startDate must not be after endDate",
"errorType": "INVALID_DATE_RANGE",
"errorTitle": "UNPROCESSABLE_ENTITY",
"status": 422,
"errorId": "a1b2c3d4-xxxx-xxxx-xxxx-000000000004",
"timestamp": "2026-02-28T10:18:00",
"path": "/invoice/search-documents",
"details": null,
"validationErrors": null
}
500 - Internal Server Error
System-level issues such as a database connectivity failure, an unexpected server-side exception, or an external service communication error (KSeF, Peppol network).
{
"errorMessage": "An unexpected error occurred",
"errorType": "SERVER_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "a1b2c3d4-xxxx-xxxx-xxxx-000000000005",
"timestamp": "2026-02-28T10:19:00",
"path": "/invoice/search-documents",
"details": null,
"validationErrors": null
}
6. Send Document Async POST
Purpose of Use: This endpoint is used to asynchronously submit XML/UBL/PDF-formatted invoice documents — generated by ERP systems or external applications — to the relevant country's official e-invoicing platform.
The document is not processed immediately upon request; instead, the full processing pipeline (validation, transformation, and transmission) is managed in the background via a message queue (Kafka). Upon receipt of the request, the endpoint immediately returns a trackingId. This identifier can be used to query the processing status at any time via the /invoice/document-status/{trackingId} endpoint.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/send-document-async |
| Method | POST |
| Authorization | R-Auth: JWT Token |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"apiKey": "<API_KEY>",
"compId": "<COMP_ID>",
"base64Document": "<BASE64_ENCODED_XML>",
"businessType": "B2C",
"invoiceSource": "ERP",
"invoiceType": "KSEF",
"receiverEmails": ["<RECEIVER_EMAIL>"]
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | String | Conditional | API key used to identify the company in the system. Required when compId is not provided. |
| compId | String (UUID) | Conditional | Unique identifier of the company in the system. Required when apiKey is not provided. |
| base64Document | String (Base64) | Conditional | Base64-encoded XML/UBL e-invoice document. Required when base64Pdf is not provided. |
| base64Pdf | String (Base64) | Conditional | Base64-encoded PDF document.Required when base64Document is not provided. |
| invoiceType | DataType | Conditional | Format of the invoice document. Required when waybillType is not provided. |
| waybillType | WaybillDataType | Conditional | Type of the waybill document. Required when invoiceType is not provided. |
| businessType | BusinessModelType | No | Business model of the transaction (B2B, B2C, B2G). |
| invoiceSource | InvoiceSource | No | The channel or system from which the document originates (e.g. ERP, PORTAL). |
| receiverEmails | String[] | No | List of email addresses to receive a notification upon processing completion. |
| mailTemplateId | String | No | System identifier of the email template to use for the notification message. |
Enum Values
invoiceType — DataType
| Value | Description |
|---|---|
| KSEF | Poland KSeF e-invoice format |
| PEPPOL_BIS | PEPPOL BIS Billing 3.0 (European e-invoicing network) |
| XRECHNUNG | Germany XRechnung e-invoice standard |
| RO_EFACTURA | Romania e-Factura format |
| MY_INVOIS | Malaysia MyInvois platform |
| MY_PINT | Malaysia PINT e-invoice format |
| DK_OIOUBL | Denmark OIOUBL format |
| EG_INVOICE | Egypt e-invoice (ETA) format |
| HR_INVOICE | Croatia eRačun format |
| UAE_PINT | UAE PINT e-Invoice format |
| ZUGFERD | ZUGFeRD — Germany hybrid PDF/XML format |
| FACTUR_X | FACTUR-X — France hybrid PDF/XML format |
| XRECHNUNG_CII | XRechnung CII (Cross Industry Invoice) sub-format |
| CII | Cross Industry Invoice format |
| CID | CID format |
| KZ_ESF_V2 | Kazakhstan ESF v2 format |
waybillType — WaybillDataType
| Value | Description |
|---|---|
| RS_WAYBILL_DESPATCH | Serbia e-waybill — dispatch document |
| RS_WAYBILL_RECEIPT | Serbia e-waybill — receipt document |
| RS_APPLICATION_RESPONSE | Serbia application response document |
| RO_ETRANSPORT | Romania e-Transport transport declaration |
businessType — BusinessModelType
| Value | Description |
|---|---|
| B2B | Business to Business |
| B2C | Business to Consumer |
| B2G | Business to Government |
invoiceSource — InvoiceSource
| Value | Description |
|---|---|
| ERP | Document originating from an Enterprise Resource Planning system |
| PORTAL | Document uploaded via the DocNova web portal |
| PORTAL_OCR | Document uploaded via portal and processed using OCR |
| Document received as an email attachment | |
| EMAIL_OCR | Document received via email and processed using OCR |
| PEPPOL | Document received from the PEPPOL network |
| KSEF | Document originating from the Poland KSeF system |
| SFTP | Document fetched from an SFTP server |
| NEMHANDEL | Document from the Denmark NemHandel network |
| LHDNM | Document from the Malaysia LHDN system |
| SHOPIFY | Shopify e-commerce integration |
| AMAZON_SP | Amazon Seller Partner API integration |
| EBAY | eBay integration |
| HUBSPOT | HubSpot CRM integration |
| ANAF | Romania ANAF tax authority |
| LAZADA | Lazada e-commerce integration |
| STRIPE | Stripe payment system integration |
| HARVEST | Harvest project management integration |
| SERVICE | Document originating from an internal service call |
| RS_API | Serbia API integration |
| ETA | Egypt ETA tax authority |
| ERACUN | Croatia eRačun platform |
Responses
200 - Successful Response
{
"trackingId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": "PENDING",
"message": "Document received and queued for processing."
}
400 - Bad Request
Scenario 1 — Both apiKey and compId are missing
{
"message": "Document process required fields: apiKey or companyId",
"errorClientMessage": "Document process required fields: apiKey or companyId",
"data": null,
"details": null
}
The request body must contain at least one of apiKey or compId to identify the company. Provide either field to resolve this error.
Scenario 2 — Both invoiceType and waybillType are missing
{
"message": "Document process required fields: invoiceType or waybillType",
"errorClientMessage": "Document process required fields: invoiceType or waybillType",
"data": null,
"details": null
}
The type of the submitted document must be specified. Provide either invoiceType (for invoices) or waybillType (for waybills).
Scenario 3 — Both base64Document and base64Pdf are missing
{
"message": "Document process required fields: base64Document or base64Pdf",
"errorClientMessage": "Document process required fields: base64Document or base64Pdf",
"data": null,
"details": null
}
A document payload must be provided. Supply either base64Document (Base64-encoded XML) or base64Pdf (Base64-encoded PDF) in the request body.
Scenario 4 — Unrecognized apiKey
{
"message": "At least one of apiKey or companyId fields must be filled.",
"errorClientMessage": "At least one of apiKey or companyId fields must be filled.",
"data": null,
"details": null
}
The provided apiKey value does not match any registered API key in the system, or no associated company record was found for it.
Scenario 5 — Invalid enum value (e.g., unrecognized invoiceType)
{
"message": "Invalid argument! Argument: invoiceType",
"errorClientMessage": "Invalid argument! Argument: invoiceType",
"data": null,
"details": null
}
One of the enum fields (invoiceType, waybillType, businessType, or invoiceSource) was supplied with a value that is not in the accepted values list. Refer to the Enum Values tables above for valid options.
401 - Unauthorized
The R-Auth header is either missing, contains a malformed JWT token, or the provided token has expired. Obtain a fresh token and retry the request.
{
"message": "Unauthorized",
"errorClientMessage": "Unauthorized",
"data": null,
"details": null
}
402 - Payment Required
The company's account has insufficient credits to proceed with the operation. Top up the account. For assistance, contact Melasoft GmbH support.
{
"message": "Out Of Credit! Please contact with Melasoft GmbH Support.",
"errorClientMessage": "Out Of Credit! Please contact with Melasoft GmbH Support.",
"data": null,
"details": null
}
403 - Forbidden
The authenticated user does not possess the required access rights to the company identified by compId. Verify that the JWT token belongs to a user who is authorized for that specific company.
{
"message": "Forbidden",
"errorClientMessage": "Forbidden",
"data": null,
"details": null
}
500 - Internal Server Error
An unexpected error occurred on the server side during the creation or persistence of the document processing record. Retrying the same request is recommended. If the issue persists, contact Melasoft GmbH support with the request details.
{
"message": "Invoice is NULL and/or could not be saved!",
"errorClientMessage": "Invoice is NULL and/or could not be saved!",
"data": null,
"details": null
}
7. Send Document Async JSON POST
Purpose of Use: This endpoint accepts invoice and document data in JSON format, adhering to the UBL (Universal Business Language) structure. It is designed to receive data from ERP systems or external integrations.
The client sends the document as a JSON body. The system internally converts the JSON data to UBL XML format, base64-encodes the document, and routes it via a Kafka message queue to the relevant country integration (e.g., KSeF, PEPPOL, e-Invoice). Processing is asynchronous. Upon submission, the endpoint immediately returns a trackingId. This trackingId can be used to monitor the processing status through a separate endpoint: GET /invoice/document-status/{trackingId}.
A valid JWT (JSON Web Token) is required and must be included in the R-Auth header for every request. To identify the company, either apiKey or ublDto.CompanyId must be provided.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/send-document-async-json |
| Method | POST |
| Authentication | R-Auth header (JWT token) |
Example Request
curl -X POST 'https://api-stage.docnova.ai/invoice/send-document-async-json' \
-H 'Content-Type: application/json' \
-H 'r-auth: {{jwt_token}}' \
-d '{
"apiKey": "{{your_api_key}}",
"receiverEmails": ["user@example.com"],
"ublDto": {
"CompanyId": "{{company_uuid}}",
"Type": "KSEF",
"Format": "EASY_INVOICE",
"ProfileType": "KSEF_FA3",
"IsPeppolParticipant": false,
"DraftUuid": "{{draft_uuid}}",
"PartnerUuid": "{{partner_uuid}}",
"ID": { "Value": "INV-2026-001" },
"IssueDate": { "Value": "2026-03-05" },
"DueDate": { "Value": "2026-03-13" },
"TaxPointDate": { "Value": "2026-03-05" },
"DocumentCurrencyCode": { "Value": "PLN" },
"TaxCurrencyCode": { "Value": "PLN" },
"InvoiceTypeCode": { "Value": "VAT" },
"CustomizationID": { "Value": "urn:cen.eu:en16931:2017" },
"ProfileID": { "Value": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0" },
"UBLVersionID": { "Value": "2.1" },
"BuyerReference": { "Value": "buyer" },
"AccountingCost": { "Value": "1600" },
"Note": [{ "Value": "Thank you for your order." }],
"AccountingSupplierParty": {
"Party": {
"EndpointID": { "Value": "pl84600...", "schemeID": "9945" },
"PartyName": [{ "Name": { "Value": "Poland Test" } }]
}
},
"AccountingCustomerParty": {
"Party": {
"PartyName": [{ "Name": { "Value": "Buyer Company" } }],
"PartyTaxScheme": [{ "CompanyID": { "Value": "PL5222917..." }, "TaxScheme": { "ID": { "Value": "VAT" } } }]
}
},
"InvoiceLine": [{
"ID": { "Value": "1" },
"InvoicedQuantity": { "Value": "2", "unitCode": "XBA" },
"LineExtensionAmount": { "Value": 1600, "currencyID": "PLN" },
"Item": { "Name": { "Value": "Product Name" } },
"Price": { "PriceAmount": { "Value": "800" } }
}],
"LegalMonetaryTotal": {
"LineExtensionAmount": { "Value": "1600", "currencyID": "PLN" },
"TaxExclusiveAmount": { "Value": "1600", "currencyID": "PLN" },
"TaxInclusiveAmount": { "Value": "1952.00", "currencyID": "PLN" },
"PayableAmount": { "Value": "1952.00", "currencyID": "PLN" }
},
"TaxTotal": [{
"TaxAmount": { "Value": "352.00", "currencyID": "PLN" },
"TaxSubtotal": [{
"TaxableAmount": { "Value": "1600.00", "currencyID": "PLN" },
"TaxAmount": { "Value": "352.00", "currencyID": "PLN" },
"TaxCategory": { "ID": { "Value": "S" }, "Percent": { "Value": "22" }, "TaxScheme": { "ID": { "Value": "VAT" } } }
}]
}],
"PaymentMeans": [{ "PaymentMeansCode": { "Value": "30" }, "PaymentDueDate": { "Value": "2026-03-13" } }]
}
}'
Request Parameters
Body Parameters
Root Object
| Field Name | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | API key for company identification. Required if ublDto.CompanyId is not provided |
| ublDto | object (UblDocument) | Yes | Invoice/document data in UBL format |
ublDto — Document Object (UblDocument)
| Field Name | Type | Required | Description |
|---|---|---|---|
| Type | enum (DocumentType) | Yes | Document format / country integration type |
| IsPeppolParticipant | boolean | No | Whether the recipient is a PEPPOL network participant |
| CompanyId | string (UUID) | Conditional | Company UUID. Required if apiKey is not provided |
| ProfileType | enum (ProfileType) | Yes | UBL validation profile |
| CustomizationID.Value | string | Yes | Document customization identifier (URN format) |
| ID.Value | string | Yes | Invoice number / document identifier |
| IssueDate.Value | string (date) | Yes | Invoice issue date. Format: YYYY-MM-DD |
| DueDate.Value | string (date) | No | Payment due date. Format: YYYY-MM-DD |
| InvoiceTypeCode.Value | enum (InvoiceTypeCode) | Yes | Invoice type code |
| Note[].Value | string | No | Free-text notes on the invoice |
| DocumentCurrencyCode.Value | string (ISO 4217) | Yes | Document currency code (e.g. EUR, PLN, USD) |
| BuyerReference.Value | string | No | Buyer's own reference number |
| OrderReference.ID.Value | string | No | Order reference number |
| OrderReference.SalesOrderID.Value | string | No | Sales order number |
ublDto.AccountingSupplierParty.Party — Supplier Party (Podmiot 1)
| Field Name | Type | Required | Description |
|---|---|---|---|
| PartyIdentification[].ID.Value | string | Yes | Supplier's tax identification number or company number |
| PartyName[].Name.Value | string | Yes | Supplier's trading name |
| PostalAddress.StreetName.Value | string | Yes | Street / address line |
| PostalAddress.CityName.Value | string | Yes | City name |
| PostalAddress.PostalZone.Value | string | Yes | Postal/ZIP code |
| PostalAddress.Country.IdentificationCode.Value | string (ISO 3166-1 alpha-2) | Yes | Country code (e.g. PL, DE, BE) |
| PartyTaxScheme[].CompanyID.Value | string | Yes | VAT number (with country prefix, e.g. PL8460002329) |
| PartyTaxScheme[].TaxScheme.ID.Value | string | Yes | Tax scheme identifier (fixed: VAT) |
| PartyLegalEntity[].RegistrationName.Value | string | Yes | Company's registered legal name |
| PartyLegalEntity[].CompanyID.Value | string | Yes | Company legal registration number |
| Contact.Name.Value | string | No | Contact person name |
| Contact.Telephone.Value | string | No | Phone number |
| Contact.ElectronicMail.Value | string | No | Email address |
ublDto.AccountingCustomerParty.Party — Customer Party (Podmiot 2)
| Field Name | Type | Required | Description |
|---|---|---|---|
| PartyIdentification[].ID.Value | string | Yes | Buyer's tax identification number or company number |
| PartyName[].Name.Value | string | Yes | Buyer's trading name |
| PostalAddress.StreetName.Value | string | Yes | Street / address line |
| PostalAddress.CityName.Value | string | Yes | City name |
| PostalAddress.PostalZone.Value | string | Yes | Postal/ZIP code |
| PostalAddress.Country.IdentificationCode.Value | string (ISO 3166-1 alpha-2) | Yes | Country code |
| PartyTaxScheme[].CompanyID.Value | string | Yes | VAT number |
| PartyTaxScheme[].TaxScheme.ID.Value | string | Yes | Tax scheme identifier (fixed: VAT) |
| PartyLegalEntity[].RegistrationName.Value | string | Yes | Buyer's registered legal name |
| PartyLegalEntity[].CompanyID.Value | string | Yes | Buyer's company legal registration number |
| Contact.ElectronicMail.Value | string | No | Buyer's email address |
ublDto.Delivery[] — Delivery Information
| Field Name | Type | Required | Description |
|---|---|---|---|
| ActualDeliveryDate.Value | string (date) | No | Actual delivery date. Format: YYYY-MM-DD |
| DeliveryLocation.Address.StreetName.Value | string | No | Street name of delivery address |
| DeliveryLocation.Address.CityName.Value | string | No | City name of delivery address |
| DeliveryLocation.Address.PostalZone.Value | string | No | Postal code of delivery address |
| DeliveryLocation.Address.Country.IdentificationCode.Value | string (ISO 3166-1 alpha-2) | No | Country code for delivery location |
| DeliveryParty.PartyName[].Name.Value | string | No | Name of delivery recipient |
ublDto.PaymentMeans[] — Payment Means
| Field Name | Type | Required | Description |
|---|---|---|---|
| PaymentMeansCode.Value | string | No | Payment method code (e.g. "58" for SEPA credit transfer) |
| PaymentMeansCode.name | string | No | Descriptive name for payment method |
| PayeeFinancialAccount.ID.Value | string | No | IBAN of the payee |
| PayeeFinancialAccount.Name.Value | string | No | Account holder name |
ublDto.PaymentTerms[] — Payment Terms
| Field Name | Type | Required | Description |
|---|---|---|---|
| Note[].Value | string | No | Textual description of payment terms |
ublDto.TaxTotal[] — Tax Totals
| Field Name | Type | Required | Description |
|---|---|---|---|
| TaxAmount.currencyID | string (ISO 4217) | Yes | Currency for total tax amount |
| TaxAmount.Value | decimal | Yes | Total amount of tax |
| TaxSubtotal[].TaxableAmount.currencyID | string (ISO 4217) | Yes | Currency for taxable amount |
| TaxSubtotal[].TaxableAmount.Value | decimal | Yes | Taxable amount (net before tax) |
| TaxSubtotal[].TaxAmount.currencyID | string (ISO 4217) | Yes | Currency for tax amount |
| TaxSubtotal[].TaxAmount.Value | decimal | Yes | Calculated tax amount for subtotal |
| TaxSubtotal[].TaxCategory.ID.Value | string | Yes | Tax category code (e.g. S) |
| TaxSubtotal[].TaxCategory.Percent.Value | decimal | Yes | VAT rate as percentage |
| TaxSubtotal[].TaxCategory.TaxScheme.ID.Value | string | Yes | Tax scheme identifier (fixed: VAT) |
ublDto.LegalMonetaryTotal — Legal Monetary Totals
| Field Name | Type | Required | Description |
|---|---|---|---|
| LineExtensionAmount.currencyID | string (ISO 4217) | Yes | Currency code |
| LineExtensionAmount.Value | decimal | Yes | Sum of all line extension amounts (net, excl. VAT) |
| TaxExclusiveAmount.Value | decimal | Yes | Total amount excluding VAT |
| TaxInclusiveAmount.Value | decimal | Yes | Total amount including VAT |
| AllowanceTotalAmount.Value | decimal | No | Total allowance/discount (use 0 if none) |
| ChargeTotalAmount.Value | decimal | No | Total charge amount (use 0 if none) |
| PrepaidAmount.Value | decimal | No | Total prepaid amount (use 0 if none) |
| PayableAmount.Value | decimal | Yes | Net amount payable |
ublDto.InvoiceLine[] — Invoice Lines
| Field Name | Type | Required | Description |
|---|---|---|---|
| ID.Value | string | Yes | Line number (e.g. "1", "2") |
| InvoicedQuantity.unitCode | string (UN/ECE Rec 20) | Yes | Unit of measure (e.g. MTQ, PCE, KGM) |
| InvoicedQuantity.Value | decimal | Yes | Invoiced quantity |
| LineExtensionAmount.currencyID | string (ISO 4217) | Yes | Currency code |
| LineExtensionAmount.Value | decimal | Yes | Line total amount (excl. VAT) |
| Item.Name.Value | string | Yes | Product / service name |
| Item.SellersItemIdentification.ID.Value | string | No | Seller's product/item code |
| Item.ClassifiedTaxCategory[].ID.Value | string | Yes | Line-level tax category code |
| Item.ClassifiedTaxCategory[].Percent.Value | decimal | Yes | Line-level VAT rate (%) |
| Item.ClassifiedTaxCategory[].TaxScheme.ID.Value | string | Yes | Tax scheme identifier (fixed: VAT) |
| Price.PriceAmount.currencyID | string (ISO 4217) | Yes | Unit price currency |
| Price.PriceAmount.Value | decimal | Yes | Unit price |
| Price.BaseQuantity.Value | decimal | No | Base quantity for unit price (default: 1) |
| DocumentReference[].ID.Value | string | No | Referenced document ID |
| DocumentReference[].DocumentTypeCode.Value | string | No | Document type code (e.g. 130 - invoiced object) |
Field Values — Enum Reference Tables
DocumentType (ublDto.Type)
| Value | Description |
|---|---|
| KSEF | Poland electronic invoice system (KSeF) |
| PEPPOL_BIS | PEPPOL BIS Billing 3.0 (pan-European) |
| XRECHNUNG | Germany XRechnung (UBL format) |
| XRECHNUNG_CII | Germany XRechnung (CII format) |
| ZUGFERD | ZUGFeRD / Factur-X (Germany/France) |
| FACTUR_X | Factur-X (PDF/A-3 embedded) |
| RO_EFACTURA | Romania e-Factura |
| MY_INVOIS | Malaysia e-Invoice |
| MY_PINT | Malaysia PINT |
| DK_OIOUBL | Denmark OIOUBL |
| HR_INVOICE | Croatia e-Invoice |
| UAE_PINT | UAE PINT |
| CII | UN/CEFACT CII (Cross Industry Invoice) |
ProfileType (ublDto.ProfileType)
| Value | Description |
|---|---|
| EN16931 | European standard invoice profile (EN 16931) |
| EXTENDED | Extended profile (ZUGFeRD Extended / Factur-X Extended) |
| BASIC | Basic profile |
| KSEF_FA2 | Poland KSeF FA(2) profile |
InvoiceTypeCode (ublDto.InvoiceTypeCode.Value)
| Value | Description |
|---|---|
| VAT | Standard VAT invoice (UBL 380) |
| CREDIT_NOTE | Credit note (UBL 381) |
| DEBIT_NOTE | Debit note (UBL 383) |
| PROFORMA_INVOICE | Proforma invoice (UBL 325) |
| KSEF_BASIC | KSeF standard invoice |
| KSEF_CORRECTIVE | KSeF corrective invoice |
| KSEF_PREPAYMENT | KSeF advance payment invoice |
| KSEF_BILLING | KSeF clearance invoice |
TaxCategory.ID Values
| Value | Description |
|---|---|
| S | Standard VAT rate |
| Z | Zero-rated VAT |
| E | VAT exempt |
| AE | Reverse charge mechanism |
| G | Export (delivery outside the country) |
| O | Outside scope of VAT |
Responses
200 - Successful Response
Returned when the document has been successfully submitted to the processing queue.
{
"trackingId": "3fa85f64-5717-4562-b3fc-...",
"status": "PENDING",
"message": "Document processing request submitted successfully"
}
Response Fields
| Field Name | Type | Description |
|---|---|---|
| trackingId | string (UUID) | Processing tracking identifier. Use with GET /invoice/document-status/{trackingId} to monitor status |
| status | enum (ProcessStatus) | Processing status. Always PENDING on the initial response |
| message | string | Human-readable message describing the current state |
Process Status Values
| Value | Description |
|---|---|
| PENDING | Request queued; processing has not yet started |
| PROCESSING | Document is actively being processed |
| COMPLETED | Document successfully processed and delivered |
| FAILED | Processing failed |
| SENDING_FAILED | Document generated but could not be sent to the target system |
| PERMANENT_FAILED | Permanent failure, retry is not possible |
400 - Bad Request
Trigger: Both apiKey and ublDto.CompanyId are absent or null.
{
"message": "Required fields are missing: apiKey or companyId",
"errorClientMessage": "DOCUMENT_PROCESS_REQUIRED_FIELDS",
"httpStatus": 400,
"details": null,
"validationErrors": null
}
Description: The system requires at least one of apiKey or CompanyId to identify the company.
400 - Bad Request — Null Document Object
Trigger: ublDto is null, or ublDto.Type / ublDto.InvoiceTypeCode.Value are missing or blank.
{
"message": "UBL data object or invoice type code cannot be null",
"errorClientMessage": "NULL_DATA_OBJECT",
"httpStatus": 400,
"details": null,
"validationErrors": null
}
400 - Bad Request — Invalid Document Type or Conversion Failure
Trigger: ublDto.Type contains an unsupported format, or validation error during UBL JSON + XML conversion.
{
"message": "UBL conversion failed: unsupported document type or invalid field structure",
"errorClientMessage": "INVOICE_COULD_NOT_CONVERT",
"httpStatus": 400,
"details": "Field 'InvoiceTypeCode' value 'UNKNOWN' is not a valid invoice type code",
"validationErrors": [
{
"field": "InvoiceTypeCode.Value",
"code": "INVALID_VALUE",
"message": "Provided value is not a recognized invoice type code"
}
]
}
400 - Bad Request — Invalid UUID Format
Trigger: ublDto.CompanyId is not a valid UUID format.
{
"message": "Invalid UUID format for companyId",
"errorClientMessage": "INVALID_FIELD_FORMAT",
"httpStatus": 400,
"details": "CompanyId must be a valid UUID (e.g. 3fa85164-5717-4562-b3fc-...)",
"validationErrors": null
}
401 - Unauthorized
Trigger: The R-Auth header is missing, malformed, or the token has expired.
{
"message": "Authentication token is invalid or expired",
"errorClientMessage": "UNAUTHORIZED",
"httpStatus": 401,
"details": null,
"validationErrors": null
}
401 - Unauthorized — Company Authorization Failure
Trigger: The token is valid, but the authenticated user does not have access to the company specified in the request.
{
"message": "User is not authorized to perform operations for the specified company",
"errorClientMessage": "COMPANY_AUTHORIZATION_FAILED",
"httpStatus": 401,
"details": null,
"validationErrors": null
}
404 - Not Found
Trigger: apiKey was provided but does not match any registered key in the database.
{
"message": "Api Key Didnt Match",
"errorClientMessage": "NOT_FOUND",
"httpStatus": 404,
"details": null,
"validationErrors": null
}
422 - Unprocessable Entity
Trigger: The document structure is technically valid, but violates business rules (e.g., tax total mismatch, currency inconsistency).
{
"message": "Document cannot be processed due to business rule validation failure",
"errorClientMessage": "DOCUMENT_PROCESS_FAILED",
"httpStatus": 422,
"details": "TaxTotal amount does not match sum of TaxSubtotal amounts",
"validationErrors": null
}
500 - Internal Server Error
Trigger: Connection to the Kafka message broker fails or the message cannot be sent.
{
"trackingId": "3fa85f64-5717-4562-b3fc-...",
"status": "FAILED",
"message": "Failed to submit document processing request: Kafka broker unavailable"
}
Description: Returns HTTP 200 with status FAILED in the response body. A trackingId is still returned.
500 - Internal Server Error — Unexpected Server Error
Trigger: Any unexpected server-side error not matching the above cases.
{
"message": "An unexpected error occurred. Please try again later.",
"errorClientMessage": "INTERNAL_SERVER_ERROR",
"httpStatus": 500,
"details": null,
"validationErrors": null
}
8. Attach. Permission Status POST
Purpose of Use: This endpoint is used to query whether a company has permission to send invoices with structured XML attachments (Zalacznik) through the Polish KSeF (Krajowy System e-Faktur — National e-Invoice System). KSeF is Poland's centralized e-invoicing infrastructure, which has been mandatory since January 2025.
Sending invoices with structured attachments requires a specific permission obtained through the KSeF portal. Attempting to send an invoice with an attachment without this required permission will result in a 415 error from KSeF, accompanied by the message: "Brak możliwości wysyłania faktury z załącznikiem" (Unable to send invoice with attachment).
Internally, the endpoint authenticates using the company's registered certificate, calls checkPermissionAttachmentInvoiceStatus against the KSeF system, and returns the company's current permission status via the boolean field isAttachmentAllowed. If the permission has been revoked, a revokedDate is also returned when applicable.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/attachment/permission-status |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/attachment/permission-status' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"companyId": "<COMPANY_UUID>"
}'
Request Body
{
"companyId": "341ea08e-930a-46f9-9029-..."
}
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | string (UUID v4) | Yes | Unique identifier of the company registered with its certificate in KSeF. Must be a valid UUID defined in the system. |
Parameter Value Reference
| Field | Format | Valid Example | Invalid Example |
|---|---|---|---|
| companyId | RFC 4122 UUID v4 (xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx) | 341ea08e-930a-46f9-9029-a13ee3d482c6 | null, "", "12345", missing hyphens |
Responses
200 - Successful Response
{
"isAttachmentAllowed": true,
"revokedDate": "2026-02-27T11:20:09.700Z"
}
Response Fields
| Field | Type | Nullable | Description |
|---|---|---|---|
| isAttachmentAllowed | boolean | No | Indicates whether the company has permission to send invoices with attachments in KSeF. true means attachment submission is permitted. |
| revokedDate | string (ISO 8601 date) | Yes | If the permission was revoked, this field contains the revocation date. Returns null when permission is active. |
400 - Bad Request
This error is fired when the companyId field is null or not provided in the request body.
{
"status": 400,
"error": "Bad Request",
"message": "companyId field must be filled.",
"timestamp": "2026-02-27T10:00:00Z"
}
401 - Unauthorized
This error is returned when the R-Auth header is missing, malformed, or contains an expired JWT.
{
"status": 401,
"error": "Unauthorized",
"message": "Invalid or expired authentication token.",
"timestamp": "2026-02-27T10:00:00Z"
}
415 - KSeF Permission Denied
This error is thrown internally when the KSeF API reports that the company does not have permission to send invoices with attachments. This maps to KSeF's own error code 415, which translates to "Brak możliwości wysyłania faktury z załącznikiem" (No permission to send invoice with attachment).
{
"status": 500,
"error": "Internal Server Error",
"message": "Attachment permission not granted in KSeF. Error code 415: 'Brak możliwości wysyłania faktury z załącznikiem'. Please ensure attachment sending permission is granted for this company in KSeF portal or use the test endpoint to grant permission in test environment.",
"timestamp": "2026-02-27T10:00:00Z"
}
500 - Internal Server Error
This error is returned when certificate-based authentication against KSeF fails, or when the KSeF API is temporarily unreachable.
{
"status": 500,
"error": "Internal Server Error",
"message": "Error checking attachment permission status: <KSeF error details>",
"timestamp": "2026-02-27T10:00:00Z"
}
9. Close Batch Session POST
Purpose of Use: This endpoint is used to close a batch invoice submission session that was previously opened via /invoice/PL/batch/open-session.
KSeF (Krajowy System e-Faktur — Poland's National e-Invoicing System) operates on a batch processing model: a session is first opened and all invoice parts are uploaded, then the session must be closed to signal KSeF to begin processing. This endpoint is the mandatory final step in the Polish batch invoice workflow. Invoices will not be processed by KSeF until the session is explicitly closed.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/batch/close-session |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/batch/close-session' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"companyId": "<COMPANY_UUID>",
"referenceNumber": "<BATCH_REFERENCE_NUMBER>"
}'
Request Body
{
"companyId": "341ea08e-930e-4619-9029-...",
"referenceNumber": "20260227-SB-21613FF000-...-.."
}
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | string (UUID) | Yes | Unique identifier of the company for which the batch session is being closed. Used for KSeF certificate-based authentication. |
| referenceNumber | string | Yes | The reference number of the batch session to be closed. Returned in the referenceNumber field of the /invoice/PL/batch/open-session response. |
Parameter Value Reference
| Field | Format | Example | Rule |
|---|---|---|---|
| companyId | UUID v4 (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) | 341ea08e-930a-4619-9029-a13ee3d48206 | Must be a valid UUID v4 string. Cannot be null. Invalid format returns HTTP 500. |
| referenceNumber | KSeF Batch Reference ID | 20260227-SB-21613FF000-9202689D38-29 | Must be the KSeF-generated reference number obtained from the /batch/open-session response. A previously closed or non-existent reference will result in an error. |
| R-Auth | JWT (HS512) | eyJhbGciOiJIUzUxMiJ9... | Must be a valid, non-expired JWT token. |
Responses
200 - Successful Response
No response body is returned. The 200 status code indicates that the session was successfully closed and KSeF has begun processing the invoices.
400 - Bad Request
The companyId field is absent or null in the request body. Validated at the controller level before the service is invoked.
{
"errorMessage": "companyId field must be filled.",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:30:00",
"path": "/invoice/PL/batch/close-session"
}
400 - Bad Request
The session close operation against KSeF fails at the service layer. Possible underlying causes:
- The provided referenceNumber does not exist in KSeF
- The session has already been closed previously
- The company's KSeF certificate is not registered or is invalid
- A network or communication error with the KSeF API
{
"errorMessage": "Close batch session error: Session not found for reference: 20260227-SB-INVALID-REF",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:30:00",
"path": "/invoice/PL/batch/close-session"
}
The errorMessage carries the original error message thrown by KSeF or the certificate service, prefixed with "Close batch session error:".
401 - Unauthorized
The R-Auth header is not provided, the JWT signature is invalid, or the token has expired. This validation is enforced at the Spring Security filter layer before the controller is reached.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:30:00",
"path": "/invoice/PL/batch/close-session"
}
500 - Internal Server Error
The companyId value does not conform to UUID format (causing a parse failure at the controller level), or an unexpected system-level exception occurs.
{
"errorMessage": "Invalid UUID string: not-a-valid-uuid",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:30:00",
"path": "/invoice/PL/batch/close-session"
}
10. Open Batch Session POST
Purpose of Use: This endpoint initiates and completes the batch submission of multiple invoices to KSeF (Krajowy System e-Faktur Poland's National e-Invoicing System). It is an alternative to the standard "online" mode for single-invoice submission.
Batch mode allows multiple invoices to be packaged, encrypted, and transmitted to KSeF within a single session. This approach offers significant performance and reliability advantages for high-volume invoice operations (e.g., monthly bulk invoicing runs).
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/batch/open-session |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/batch/open-session' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"apiKey": "<API_KEY>",
"companyId": "<COMPANY_UUID>",
"invoiceXmlList": [
"<BASE64_ENCODED_INVOICE_XML>"
]
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | API key used to identify the company. Required if companyId is not provided. |
| companyId | string (UUID v4) | Conditional | Universally unique identifier used to identify the company. Required if apiKey is not provided. |
| invoiceXmlList | array<string> | Yes | Array of Base64-encoded invoice XMLs. Each element is the Base64 representation of a valid Polish KSeF <Faktura> XML. Must contain at least one element. |
At least one of apiKey or companyId must be provided. If both are sent, the system resolves the company via companyId; if only apiKey is sent, the system looks up the company by the key.
Parameter Value Reference
| Field | Format / Constraints | Example |
|---|---|---|
| apiKey | Case-sensitive alphanumeric string | F9NBGSFDtQOcddN10gKCJ2ENZHlwmEGI |
| companyId | RFC 4122 UUID v4 format (hyphenated, 36 characters) | 341ea08e-930a-46f9-9029-a13ee3d482c6 |
| invoiceXmlList | Array of Base64-encoded strings; each element must contain a KSeFFA (3) schema compliant <Faktura> XML; empty array ([]) must not be sent | PD94bWwg... |
| R-Auth | HS512-signed JWT beginning with eyJ....; token must not be expired | eyJhbGciOiJIUzUxMiJ9... |
Responses
200 - Successful Response
{
"referenceNumber": "202512171431370000012345678",
"timestamp": "2025-12-17T14:31:37.000",
"totalInvoices": 1,
"savedInvoices": 1,
"message": "Batch session closed and processing started."
}
Response Fields
| Field | Type | Description |
|---|---|---|
| referenceNumber | string | Batch session reference number assigned by KSeF. Used to query session status and close the session. |
| timestamp | string (ISO 8601 OffsetDateTime) | Timestamp when the batch session was opened in KSeF. Example: '2025-12-17T14:31:37Z' |
| totalInvoices | integer | Total number of invoices submitted in the request. |
| savedInvoices | integer | Number of invoices successfully saved to the database. |
| message | string | Status message describing the outcome of the session. Example: 'Batch session closed and processing started.' |
400 - Bad Request
Scenario 1: Both apiKey and companyId Are Empty
This error occurs when neither apiKey nor companyId is provided, or both are sent as null. At least one is required to identify the company.
{
"status": 400,
"message": "At least one of apiKey or companyId fields must be filled.",
"errorClientMessage": "INVALID_REQUEST"
}
Scenario 2: Invoice XML Validation Failure
One or more invoice XMLs in invoiceXmlList violate the KSeF XSD schema or business rules. The validationErrors array provides details for each failing field. A batch session will not be opened until all invoices pass validation.
{
"status": 400,
"message": "Invoice validation failed",
"errorClientMessage": "VALIDATION_FAILED",
"validationErrors": [
{
"field": "Faktura/Naglowek/DataWytworzeniaFa",
"code": "SCHEMA_VIOLATION",
"message": "cvc-datatype-valid.1.2.1: '2025-13-17' is not a valid value for 'date'."
}
]
}
401 - Unauthorized
Scenario 1: Invalid or Expired JWT Token
The JWT token in the R-Auth header is invalid, expired, or malformed. Obtain a new token and retry. The token must be sent without a "Bearer" prefix.
{
"status": 401,
"message": "Unauthorized",
"errorClientMessage": "UNAUTHORIZED"
}
Scenario 2: No Active Certificate Found for KSeF
The required X.509 certificate for KSeF authentication is not registered or not active. Verify that the certificate has been uploaded, has not expired, and its NIP number matches the company's NIP. The system first tries the user's individual certificate, then falls back to the company certificate.
{
"status": 401,
"message": "No active certificate found for user or company",
"errorClientMessage": "CERTIFICATE_NOT_FOUND"
}
Scenario 3: KSeF Authentication Failed
The authentication request to the KSeF API was rejected. The message field contains the raw error from KSeF. Verify the certificate is authorized in KSeF, the NIP matches the company's registered NIP, and the certificate has not been revoked.
{
"status": 401,
"message": "Authentication error: [KSeF error message]",
"errorClientMessage": "KSEF_AUTH_FAILED"
}
404 - Not Found
No company record matching the provided companyId UUID or apiKey was found. Verify the UUID format, that the company is registered, and that the correct environment URL is used.
{
"status": 404,
"message": "Company not found",
"errorClientMessage": "COMPANY_NOT_FOUND"
}
500 - Internal Server Error
Scenario 1: Batch Session Open Error
An error occurred while opening the batch session in KSeF — during transmission of encrypted ZIP parts or because KSeF rejected the session request. The message field contains the raw error from KSeF. Check KSeF operational status and verify submitted content complies with size and format constraints.
{
"status": 500,
"message": "Batch session error: {KSeF error detail}",
"errorClientMessage": "BATCH_SESSION_ERROR"
}
Scenario 2: Batch Session Close Error
Session opening and encrypted file upload completed successfully, but an error occurred during the closeBatchSession call. The session may remain open on the KSeF side. Manual closure may be required via the KSeF portal or POST /invoice/PL/batch/close-session.
{
"status": 500,
"message": "Close batch session error: {KSeF error detail}",
"errorClientMessage": "CLOSE_BATCH_SESSION_ERROR"
}
Note: If the batch submission to KSeF completed successfully but one or more invoices could not be saved to the database or S3, KSeF records are updated and the referenceNumber is valid; however, local records may be incomplete. Contact support to reconcile missing records.
11. Generate Invoice Pdf POST
Purpose of Use: This endpoint generates a PDF document from an invoice stored in KSeF (Krajowy System e-Faktur Poland's National e-Invoice System), identified by its KSeF reference number.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/generate-pdf |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/generate-pdf' \
--header 'Accept: */*' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"apiKey": "<API_KEY>",
"companyId": "<COMPANY_UUID>",
"ksefNumber": "<KSEF_REF_NUMBER>"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | Company API key. Can be used as an alternative to companyId to identify the company. |
| companyId | string | Conditional | Company UUID. The KSeF certificate is resolved based on this company. |
| ksefNumber | string | Yes | The unique reference number assigned to the invoice by the KSeF system. The PDF is fetched and generated using this. |
Condition: At least one of apiKey or companyId must be provided. If both are given, companyId takes precedence.
ksefNumber Format Reference
| Segment | Example | Description |
|---|---|---|
| NIP (Tax ID) | 8460002329 | 10-digit Polish Tax Identification Number assigned to the company. |
| Date | 20260227 | Invoice date in YYYYMMDD format. |
| Unique Identifier | 3CFD80000000 | Session/operation-level unique identifier assigned by KSeF. |
| Suffix Code | E8 | KSeF internal classification code. |
Full Example: 8460002329-20260227-...-..
Responses
200 - Successful Response
HTTP Status: 200 OK
| Header | Value |
|---|---|
| Content-Type | application/pdf |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Content-Disposition | attachment; filename=invoice_(ksefRefNumber).pdf |
Body: byte[] — Binary PDF file (directly downloadable / saveable format)
400 - Bad Request
Scenario 1: Missing Identity Field
Neither apiKey nor companyId is provided in the request body.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
Scenario 2: Invalid UUID Format
The companyId field contains a value that does not conform to UUID format (e.g., "abc-123").
{
"errorMessage": "Invalid UUID string: abc-123",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
Scenario 3: Company Not Found for API Key
No registered company is found in the system matching the provided apiKey value.
{
"errorMessage": "Company not found",
"errorType": "COMPANY_NOT_FOUND",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
Scenario 4: Invoice Not Found in KSeF or Not Yet Processed
No invoice exists in KSeF for the given ksefReferenceNumber, or the invoice has not yet been processed by KSeF. May be triggered when KSeF returns "No content to map due to end-of-input" or an empty byte array.
{
"errorMessage": "Invoice not found in KSeF or not yet processed: 8460002329-20260227-3CFD80000000-E8",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
Scenario 5: PDF Generation Error
An unexpected error during XML-to-HTML transformation or HTML-to-PDF conversion. May reflect XML transformation failure, iText rendering error, or QR code generation failure.
{
"errorMessage": "PDF generation error: <error detail>",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
401 - Unauthorized
The R-Auth header contains an invalid, expired, or signature-verification-failed JWT token.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
404 - Not Found
No active digital certificate is found for the company identified by companyId (or any user under that company). KSeF authentication is certificate-based; this error prevents PDF generation.
{
"errorMessage": "No active certificate found for user or company: 341ea08e-930a-46f9-9029-a13ee3d482c6",
"errorType": "USER_CERTIFICATE_NOT_FOUND",
"errorTitle": "NOT_FOUND",
"status": 404,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
500 - Internal Server Error
Scenario 1: KSeF Authentication Timeout
The KSeF auth token polling fails to receive success status after a maximum of 3 attempts with exponential backoff.
{
"errorMessage": "Authentication timeout after 3 attempts",
"errorType": "API_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
Scenario 2: Internal KSeF Authentication Error
An unexpected error during certificate parsing, private key reading, or the KSeF auth challenge flow.
{
"errorMessage": "Internal authentication error: <error detail>",
"errorType": "API_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
Scenario 3: IO / File Read Error
An I/O-level error occurs while reading the XSLT template file or writing the PDF byte stream.
{
"errorMessage": "File operation failed",
"errorType": "IO_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/generate-pdf"
}
12. Get Invoice POST
Purpose of Use: This endpoint retrieves the raw XML content of a specific invoice from KSeF (Krajowy System e-Faktur — Poland's National e-Invoice System). Invoices belonging to a registered company are queried via their KSeF reference number.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/get-invoice |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/get-invoice' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"ksefReferenceNumber": "9876543210-20260227-...-..",
"companyId": "<COMPANY_UUID>"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| ksefReferenceNumber | string | Yes | The unique reference number of the invoice in the KSeF system. |
| companyId | string (UUID v4) | Conditional | The unique identifier of the company in the system. |
| apiKey | string | Conditional | The API access key assigned to the company. |
Conditional Requirement: At least one of companyId or apiKey must be provided. If both are null, the request returns 400 Bad Request. If both are provided, companyId is used.
Parameter Value Reference
| Field | Example | Format / Constraint |
|---|---|---|
| ksefReferenceNumber | 9876543210-20260227-...-.. | KSeF reference number in (NIP)-[YYYYMMDD]-(HEX12)-(SUFFIX) format |
| companyId | xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx | RFC 4122 compliant UUID v4 format |
| apiKey | AbCd1234XyZw5678Qr... | Alphanumeric API key registered in the system |
Responses
200 - Successful Response
A successful request returns the raw XML content of the invoice as Content-Type: application/xml or text/plain. This XML is the UBL-formatted e-invoice document retrieved from the KSeF system.
The response body is raw XML, not JSON. An XML parser must be used when processing the response.
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:ID>INV-2026-00042</cbc:ID>
<cbc:IssueDate>2026-02-27</cbc:IssueDate>
<...>
</Invoice>
400 - Bad Request
Both apiKey and companyId fields are null or not sent. At least one of companyId or apiKey must be provided.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:30:45.123456",
"path": "/invoice/PL/get-invoice",
"data": null,
"validationErrors": null
}
400 - Bad Request
The provided apiKey value does not match any company registered in the system. Ensure that a correct and active apiKey value is being used.
{
"errorMessage": "Api Key Didn't Match",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "b2c3d4e5-f6a7-8901-bcde-...",
"timestamp": "2026-02-27T10:31:12.456789",
"path": "/invoice/PL/get-invoice",
"data": null,
"validationErrors": null
}
400 - Bad Request
Authentication with the KSeF system using the company's or user's certificate failed. Verify that the certificate associated with the company is active and valid.
{
"errorMessage": "Authentication error: <KSEF_ERROR_DETAIL>",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "c3d4e5f6-a708-9012-cdef-...",
"timestamp": "2026-02-27T10:32:00.789012",
"path": "/invoice/PL/get-invoice",
"data": null,
"validationErrors": null
}
400 - Bad Request
No invoice was found in the KSeF system for the given referenceNumber, or the KSeF service returned an unexpected error. Verify that the referenceNumber is correct and complete, and that the invoice exists in KSeF.
{
"errorMessage": "Get invoice error: <KSEF_ERROR_DETAIL>",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "d4e5f6a7-b8c9-0123-defa-...",
"timestamp": "2026-02-27T10:33:15.012345",
"path": "/invoice/PL/get-invoice",
"data": null,
"validationErrors": null
}
401 - Unauthorized
The JWT token in the R-Auth header is missing, malformed, or has expired. Retry the request with a valid, non-expired JWT.
{
"errorMessage": "Unauthorized",
"errorType": "UNAUTHORIZED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "e5f6a7b8-c9d0-1234-efab-...",
"timestamp": "2026-02-27T10:34:00.234567",
"path": "/invoice/PL/get-invoice",
"data": null,
"validationErrors": null
}
500 - Internal Server Error
The companyId field contains a value that does not conform to UUID v4 format. Ensure that the companyId value is a valid UUID in xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx format.
{
"errorMessage": "Internal Server Error",
"errorType": "RUNTIME_EXCEPTION",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "f6a7b8c9-d0e1-2345-fabc-...",
"timestamp": "2026-02-27T10:35:22.345678",
"path": "/invoice/PL/get-invoice",
"data": null,
"validationErrors": null
}
500 - Internal Server Error
No active certificate is registered in the system for the company or the requesting user. Register an active KSeF certificate for the company.
{
"errorMessage": "Authentication error: No active certificate found for company or its users: <COMPANY_ID>",
"errorType": "API_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "a7b8c9d0-e1f2-3456-abcd-...",
"timestamp": "2026-02-27T10:36:45.456789",
"path": "/invoice/PL/get-invoice",
"data": null,
"validationErrors": null
}
13. Trigger Historical Fetch POST
Purpose of Use: This endpoint bulk-retrieves historical incoming invoices from KSeF (Krajowy System e-Faktur — Poland's National e-Invoice System) on behalf of an authorized company, filtered by a specified date range.
While the platform usually handles current invoices via an automated 5-minute synchronization loop, this endpoint allows manual triggering of a "backfill" for invoices from a specific historical window.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/historical-fetch |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/historical-fetch' \
--header 'Accept: */*' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"apiKey": "<API_KEY>",
"companyId": "<COMPANY_UUID>",
"fromDate": "2025-01-01T00:00:00+03:00",
"toDate": "2026-02-01T23:59:59+03:00"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Yes | The service or client API key registered on the platform. Unique per company. |
| companyId | string (UUID v4) | Yes | The platform-unique identifier of the company whose invoice history is being queried. |
| fromDate | string (ISO 8601) | Yes | Start date and time of the query range. Must include timezone offset. |
| toDate | string (ISO 8601) | Yes | End date and time of the query range. Must include timezone offset. |
Parameter Value Reference
| Field | Format | Constraint | Example |
|---|---|---|---|
| apiKey | string | Min 32, Max 64 characters; alphanumeric | F9NBGSFDtQOcddN10gKC... |
| companyId | UUID v4 | RFC 4122-compliant UUID format | xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx |
| fromDate | ISO 8601 | Format: yyyy-MM-dd'T'HH:mm:ss±HH:mm; must be before toDate | 2025-01-01T00:00:00+03:00 |
| toDate | ISO 8601 | Format: yyyy-MM-dd'T'HH:mm:ss±HH:mm; must be after fromDate; future dates not allowed | 2026-02-01T23:59:59+03:00 |
| R-Auth (JWT userType) | enum | CLIENT | ADMIN | SERVICE | CLIENT |
| R-Auth (JWT exp) | Unix timestamp | Token must not be expired | 1772273654 |
Responses
200 - Successful Response
{
"success": true,
"country": "PL",
"companyId": "<COMPANY_UUID>",
"fromDate": "2025-01-01T00:00:00+03:00",
"toDate": "2026-02-01T23:59:59+03:00",
"totalFetched": 148,
"totalPages": 15,
"invoices": [
{
"ksefReferenceNumber": "PL20250101000000000000...",
"invoiceNumber": "FV/2025/001",
"issueDate": "2025-01-05",
"invoicingDate": "2025-01-05T10:22:00+01:00",
"acquisitionDate": "2025-01-05T10:23:00+01:00",
"supplierName": "Firma ABC Sp. z o.o.",
"customerName": "Firma XYZ S.A.",
"netAmount": 10000.00,
"grossAmount": 12300.00,
"taxAmount": 2300.00,
"currency": "PLN",
"status": "KSEF_ACCEPTED",
"hasAttachment": false,
"invoiceHash": "sha256:abcd1234...",
"upoDownloadUrl": "https://ksef.mf.gov.pl/upo/..."
}
],
"processingStatus": "COMPLETED",
"message": "Historical fetch completed successfully."
}
Response Fields
| Field | Type | Description |
|---|---|---|
| success | boolean | Indicates whether the operation completed successfully |
| country | string | Country code for the operation (fixed: PL) |
| companyId | string (UUID) | The ID of the queried company |
| fromDate | string (ISO 8601) | Start of the queried period |
| toDate | string (ISO 8601) | End of the queried period |
| totalFetched | integer | Total number of invoices retrieved from KSeF within the period |
| totalPages | integer | Total number of pages in the paginated result set |
| invoices | array<Invoice> | List of fetched invoices (see below) |
| processingStatus | string (enum) | COMPLETED | PARTIAL | FAILED |
| message | string | Human-readable result message |
invoices Object Fields
| Field | Type | Description |
|---|---|---|
| ksefReferenceNumber | string | Unique invoice reference number in the KSeF system |
| invoiceNumber | string | Document number of the invoice (as issued by the supplier) |
| issueDate | string (YYYY-MM-dd) | Date the invoice was issued |
| invoicingDate | string (ISO 8601) | Date and time the invoice was submitted to KSeF (with offset) |
| acquisitionDate | string (ISO 8601) | Date and time the invoice was accepted by KSeF (with offset) |
| supplierName | string | Supplier company name |
| customerName | string | Buyer company name |
| netAmount | number (double) | Net amount excluding tax |
| grossAmount | number (double) | Gross amount including VAT |
| taxAmount | number (double) | VAT amount |
| currency | string (ISO 4217) | Currency code (e.g. PLN) |
| status | string (enum) | KSeF processing status: KSEF_ACCEPTED | KSEF_PENDING | KSEF_REJECTED | KSEF_DUPLICATE | SAVED_AS_KSEF |
| hasAttachment | boolean | Whether the invoice has an attached document |
| invoiceHash | string | Hash value for invoice integrity verification |
| upoDownloadUrl | string (URL) | Official UPO (Urzędowe Potwierdzenie Odbioru) download URL |
400 - Bad Request
Returned when any of apiKey, companyId, fromDate, or toDate is absent. Each missing field appears as a separate entry in the errors array.
{
"success": false,
"httpStatus": 400,
"error": "VALIDATION_ERROR",
"message": "Required field is missing",
"errors": [
{
"field": "fromDate",
"code": "NOT_NULL",
"message": "fromDate is required and must not be null."
}
]
}
400 - Bad Request - Invalid Date Format
Returned when fromDate or toDate does not conform to yyyy-MM-dd'T'HH:mm:ssXXX. Slash-separated or timezone-less formats are rejected.
{
"success": false,
"httpStatus": 400,
"error": "INVALID_DATE_FORMAT",
"message": "Date fields must be in ISO 8601 format with timezone offset (e.g. 2025-01-01T00:00:00+03:00)",
"errors": [
{
"field": "toDate",
"code": "INVALID_FORMAT",
"message": "Cannot parse \"2026/02/01\". Expected ISO 8601 format with timezone."
}
]
}
400 - Bad Request - Invalid Date Range
Returned when the end date is chronologically before the start date.
{
"success": false,
"httpStatus": 400,
"error": "INVALID_DATE_RANGE",
"message": "toDate must be after fromDate.",
"details": [
{
"fromDate": "2026-02-01T00:00:00+03:00",
"toDate": "2025-01-01T00:00:00+03:00"
}
]
}
400 - Bad Request - Future Date Not Allowed
Since this endpoint is designed for historical data retrieval only, future dates are rejected.
{
"success": false,
"httpStatus": 400,
"error": "FUTURE_DATE_NOT_ALLOWED",
"message": "toDate cannot be in the future. Only historical invoices can be fetched.",
"details": [
{
"toDate": "2027-01-01T00:00:00+03:00"
}
],
"serverTime": "2026-02-27T10:00:00+01:00"
}
401 - Unauthorized
Scenario 1: Missing R-Auth Token
Returned when no R-Auth header is included in the request.
{
"success": false,
"httpStatus": 401,
"error": "MISSING_AUTH_TOKEN",
"message": "Authorization token is required. Please provide a valid r-auth header."
}
Scenario 2: Expired R-Auth Token
Returned when the JWT exp claim indicates a past timestamp. A new token must be obtained before retrying.
{
"success": false,
"httpStatus": 401,
"error": "TOKEN_EXPIRED",
"message": "The provided authentication token has expired.",
"details": {
"expiredAt": "2026-01-01T12:00:00Z",
"serverTime": "2026-02-27T10:00:00Z"
}
}
Scenario 3: Invalid Token Signature
Returned when the JWT signature cannot be verified. Typically caused by token tampering or use of a wrong environment key.
{
"success": false,
"httpStatus": 401,
"error": "INVALID_TOKEN_SIGNATURE",
"message": "The authentication token signature is invalid or has been tampered with."
}
403 - Forbidden
Scenario 1: Invalid API Key
Returned when the apiKey is not registered in the system or has been revoked.
{
"success": false,
"httpStatus": 403,
"error": "INVALID_API_KEY",
"message": "The provided API key is invalid or has been revoked.",
"details": {
"country": "PL"
}
}
Scenario 2: companyId and apiKey Mismatch
Returned when the apiKey belongs to a different company than the one specified by companyId.
{
"success": false,
"httpStatus": 403,
"error": "COMPANY_API_KEY_MISMATCH",
"message": "The provided companyId does not match the company associated with this API key.",
"details": {
"companyId": "<COMPANY_UUID>"
}
}
Scenario 3: Country Not Authorized
Returned when the account does not have access rights to the Poland invoice module.
{
"success": false,
"httpStatus": 403,
"error": "COUNTRY_NOT_AUTHORIZED",
"message": "This account is not authorized to access PL (Poland) invoice operations.",
"details": {
"requestedCountry": "PL",
"authorizedCountries": ["RO", "DE"]
}
}
404 - Not Found
Returned when no company matching the given companyId exists in the system.
{
"success": false,
"httpStatus": 404,
"error": "COMPANY_NOT_FOUND",
"message": "No company found with the provided companyId.",
"details": {
"companyId": "<COMPANY_UUID>",
"country": "PL"
}
}
422 - Unprocessable Entity
Scenario 1: Date Range Exceeds Maximum
A single request may span a maximum of 365 days. For larger ranges, split the request into multiple calls.
{
"success": false,
"httpStatus": 422,
"error": "DATE_RANGE_EXCEEDED",
"message": "The requested date range exceeds the maximum allowed period.",
"details": {
"requestedDays": 396,
"maxAllowedDays": 365
}
}
Scenario 2: Company KSeF Certificate Not Found
Connecting to KSeF requires a valid X.509 certificate for the company. Returned when no certificate is enrolled.
{
"success": false,
"httpStatus": 422,
"error": "CERTIFICATE_NOT_FOUND",
"message": "No valid KSeF certificate found for the specified company. Please enroll a certificate before fetching invoices.",
"details": {
"companyId": "<COMPANY_UUID>",
"country": "PL"
}
}
429 - Too Many Requests
KSeF enforces a maximum of 50 invoice GET requests per minute. Returned when this threshold is exceeded. Wait for retryAfterSeconds before retrying.
{
"success": false,
"httpStatus": 429,
"error": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. KSeF allows a maximum of 50 invoice fetch operations per minute.",
"details": {
"limit": 50,
"windowSeconds": 60,
"retryAfterSeconds": 23
}
}
500 - Internal Server Error
An unexpected error occurred while processing the historical fetch request.
{
"success": false,
"httpStatus": 500,
"error": "INTERNAL_SERVER_ERROR",
"message": "An unexpected error occurred while processing the historical fetch request.",
"details": {
"correlationId": "a3f9c1d2-...",
"country": "PL",
"operation": "historical-fetch"
}
}
502 - Bad Gateway
Returned when the platform cannot connect to the KSeF system or receives an unexpected upstream response. May occur during KSeF planned or unplanned maintenance windows.
{
"success": false,
"httpStatus": 502,
"error": "KSEF_GATEWAY_ERROR",
"message": "Unable to reach the KSeF (Krajowy System e-Faktur) system. The upstream service returned an unexpected response.",
"details": {
"upstreamStatus": 503,
"country": "PL",
"retryable": true
}
}
14. Get Historical Fetch Status GET
Purpose of Use: This endpoint queries the current status of a historical invoice fetch task initiated against the Polish KSeF system.
Historical invoice fetch is an asynchronous operation that returns a UUID-format taskId upon initiation. Use this taskId to poll the status endpoint to track task completion, processed invoices, and any errors.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/historical-fetch/status/{taskId} |
| Method | GET |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/historical-fetch/status/d012fad4-a1d2-4343-b33d-10984c958d1b' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>'
Request Parameters
Path Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| country | string | Yes | ISO 3166-1 alpha-2 country code. Fixed value PL (Poland) for this endpoint. |
| taskId | string (UUID) | Yes | Task identifier returned by the /historical-fetch endpoint. Must be in RFC 4122 UUID format. |
Parameter Value Reference
| Value | Country | Description |
|---|---|---|
| PL | Poland | KSeF (Krajowy System e-Faktur) Integration |
This endpoint only operates with country code PL. For other countries, use the corresponding country module.
Responses
200 - Successful Response
{
"taskId": "d012fad4-a1d2-4343-b33d-...",
"country": "PL",
"status": "IN_PROGRESS",
"totalCount": 1500,
"processedCount": 742,
"failedCount": 3,
"startedAt": "2025-02-26T08:00:00Z",
"completedAt": null,
"errorMessage": null
}
Response Fields
| Field | Type | Nullable | Description |
|---|---|---|---|
| taskId | string (UUID) | No | Unique identifier of the task |
| country | string | No | ISO 3166-1 alpha-2 country code (PL) |
| status | string (enum) | No | Current status. Values: PENDING, IN_PROGRESS, COMPLETED, FAILED, CANCELLED |
| totalCount | integer | Yes | Total invoices found in KSeF. null if total not yet determined |
| processedCount | integer | No | Number of invoices successfully processed |
| failedCount | integer | No | Number of invoices that encountered errors |
| startedAt | string (ISO 8601) | No | Task start time. Format: yyyy-MM-dd'T'HH:mm:ss'Z' |
| completedAt | string (ISO 8601) | Yes | Task completion time. null if still running |
| errorMessage | string | Yes | Error description when status: FAILED. null otherwise |
status Field Values
| Value | Description |
|---|---|
| PENDING | Task has been queued but not yet started |
| IN_PROGRESS | Task is actively being processed |
| COMPLETED | All invoices have been successfully fetched |
| FAILED | Task terminated with an error |
| CANCELLED | Task was cancelled |
400 - Bad Request
Returned when the taskId path parameter does not conform to RFC 4122 UUID format. Missing, empty, or incorrectly formatted values (e.g., integers, shortened strings) trigger this error.
{
"status": 400,
"error": "Bad Request",
"code": "INVALID_TASK_ID_FORMAT",
"message": "taskid must be a valid UUID (RFC 4122). Received: 'abc123'.",
"timestamp": "2025-02-27T10:15:30Z",
"path": "/invoice/PL/historical-fetch/status/abc123"
}
401 - Unauthorized
Returned when the R-Auth header is absent, the JWT token is malformed (signature error, wrong algorithm), or the userType claim is not CLIENT.
{
"status": 401,
"error": "Unauthorized",
"code": "INVALID_AUTH_TOKEN",
"message": "r-auth token is missing, malformed, or has an invalid signature.",
"timestamp": "2025-02-27T10:15:30Z",
"path": "/invoice/PL/historical-fetch/status/d012fad4-e1d2-4343-b336-..."
}
401 - Unauthorized - Token Expired
Returned when the JWT token's exp claim is in the past. A new token must be obtained and the request retried.
{
"status": 401,
"error": "Unauthorized",
"code": "TOKEN_EXPIRED",
"message": "The provided r-auth token has expired. Please obtain a new token and retry.",
"timestamp": "2025-02-27T10:15:30Z",
"path": "/invoice/PL/historical-fetch/status/d012fad4-e1d2-4343-b336-..."
}
403 - Forbidden
Returned when the token is valid but the caller does not have permission to query this specific taskId. Occurs when the task belongs to a different company or user.
{
"status": 403,
"error": "Forbidden",
"code": "ACCESS_DENIED",
"message": "You do not have permission to access task 'd012fad4-e1d2-4343-b336-...'",
"timestamp": "2025-02-27T10:15:30Z",
"path": "/invoice/PL/historical-fetch/status/d012fad4-e1d2-4343-b336-..."
}
404 - Not Found
Returned when no task record matching the specified taskId exists. Causes include incorrect UUID, task never initiated, or record cleaned up.
{
"status": 404,
"error": "Not Found",
"code": "TASK_NOT_FOUND",
"message": "No historical-fetch task found with id 'd012fad4-e1d2-4343-b336-...' for country 'PL'.",
"timestamp": "2025-02-27T10:15:30Z",
"path": "/invoice/PL/historical-fetch/status/d012fad4-e1d2-4343-b336-..."
}
410 - Gone
The task has completed or failed, and its record has been purged after the retention period (e.g., 7 days). Results are no longer accessible.
{
"status": 410,
"error": "Gone",
"code": "TASK_RECORD_EXPIRED",
"message": "The historical-fetch task record has expired and is no longer available. Task results are retained for 7 days after completion.",
"timestamp": "2025-02-27T10:15:30Z",
"path": "/invoice/PL/historical-fetch/status/d012fad4-e1d2-4343-b336-..."
}
500 - Internal Server Error
An unexpected server-side error occurred while reading the task status. Can be investigated via logs using the correlationId.
{
"status": 500,
"error": "Internal Server Error",
"code": "TASK_STATUS_READ_FAILED",
"message": "An unexpected error occurred while reading the task status. Please contact support with the correlationId.",
"correlationId": "com-8f2a1c3d-0044-4a2b-9c5e-...",
"timestamp": "2025-02-27T10:15:30Z",
"path": "/invoice/PL/historical-fetch/status/d012fad4-a1d2-4343-b33d-..."
}
503 - Service Unavailable
The Polish KSeF external service is temporarily unavailable. If a Retry-After header is present, retry after the indicated duration.
{
"status": 503,
"error": "Service Unavailable",
"code": "KSEF_SERVICE_UNAVAILABLE",
"message": "The KSeF external service is temporarily unavailable. Please retry after the indicated period.",
"retryAfterSeconds": 60,
"timestamp": "2025-02-27T10:15:30Z",
"path": "/invoice/PL/historical-fetch/status/d012fad4-a1d2-4343-b33d-..."
}
15. Invoice Status POST
Purpose of Use: This endpoint queries the processing status of a specific invoice within Poland's KSeF (Krajowy System e-Faktur) system.
By supplying the sessionReferenceNumber and invoiceReferenceNumber of a previously submitted invoice, a client can retrieve the current processing state within KSeF and optionally download the UPO (Urzędowe Potwierdzenie Odbioru — Official Receipt Confirmation).
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/invoice-status |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/invoice-status' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"apiKey": "<API_KEY>",
"companyId": "<COMPANY_UUID>",
"invoiceReferenceNumber": "20260227-EE-1A58DB0000-...-..",
"sessionReferenceNumber": "20260227-50-1A58D5F000-...-.."
}'
Request Body
{
"apiKey": "BW4dwsYidnwFOv4i2rguw7EerngQDMp",
"companyId": "341ea08e-930a-4619-9029-...",
"invoiceReferenceNumber": "20260227-EE-1A58DB0000-...-..",
"sessionReferenceNumber": "20260227-50-1A58D5F000-...-.."
}
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | API key used to identify the company. Required when companyId is not provided. |
| companyId | string (UUID) | Conditional | Universally unique identifier for the company. Required when apiKey is not provided. |
| invoiceReferenceNumber | string | Yes | Reference number of the queried invoice within the KSeF session. |
| sessionReferenceNumber | string | Yes | Reference number of the KSeF session to which the invoice was submitted. |
At least one of apiKey or companyId must be provided. If both are omitted, 400 Bad Request is returned. When both are provided, companyId takes precedence.
Parameter Value Reference
| Field | Format | Example | Notes |
|---|---|---|---|
| apiKey | Alphanumeric string | BW4dwsYidnwFOv4i2rguw7EerngQDMp | Obtained from the Melasoft management panel |
| companyId | UUID v4 | 341ea08e-930a-4619-9029-... | Standard UUID format with hyphens |
| invoiceReferenceNumber | yyyyMMdd-EE-(hash)-(hash)-(suffix) | 20260227-EE-1A58DB0000-2059968E54-F7 | KSeF invoice reference format |
| sessionReferenceNumber | yyyyMMdd-SO-(hash)-(hash)-(suffix) | 20260227-50-1A58D5F000-C518216928-0A | KSeF session reference format |
Responses
200 - Successful Response
{
"ordinalNumber": 1,
"invoiceReferenceNumber": "20260227-EE-1A58DB0000-...-..",
"ksefReferenceNumber": "1234567890-20260227-..-...",
"referenceNumber": "20260227-50-1A58D5F000-...-..",
"invoiceHash": "a3f5b9c1d2e4f6a7b8c9d0e1f2a...",
"invoiceFileName": "invoice_2026_001.xml",
"invoicingDate": "2026-02-27T10:30:00+01:00",
"acquisitionDate": "2026-02-27T10:31:05+01:00",
"permanentStorageDate": "2026-02-27T10:31:10+01:00",
"upoDownloadUrl": "https://ksef.mf.gov.pl/upo/download/...",
"processingCode": 200,
"processingDescription": "Faktura przetworzona poprawnie"
}
Response Fields
| Field | Type | Description |
|---|---|---|
| ordinalNumber | integer | The invoice's ordinal position within the KSeF session |
| invoiceReferenceNumber | string | Invoice reference number within the session (mirrors the request value) |
| ksefReferenceNumber | string | The unique invoice number permanently assigned by KSeF |
| referenceNumber | string | General reference number for the KSeF session |
| invoiceHash | string | Hash value used to verify the integrity of the invoice content |
| invoiceFileName | string | Original filename of the invoice file uploaded to the system |
| invoicingDate | string (ISO 8601 OffsetDateTime) | Date and time the invoice was issued |
| acquisitionDate | string (ISO 8601 OffsetDateTime) | Date and time the invoice was received by the KSeF system |
| permanentStorageDate | string (ISO 8601 OffsetDateTime) | Date and time the invoice was permanently stored in KSeF |
| upoDownloadUrl | string (URL) | Download link for the UPO (Official Receipt Confirmation) file |
| processingCode | integer | Processing status code returned by KSeF |
| processingDescription | string | Human-readable description of the processingCode value |
400 - Bad Request
Thrown at the controller level when both apiKey and companyId are null. The request body was not sent or both fields were omitted.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": null,
"status": 400,
"errorId": "corr-abc-123",
"timestamp": "2026-02-27T10:30:00",
"path": "/invoice/PL/invoice-status"
}
400 - Bad Request - Invalid UUID Format
Thrown when companyId contains a value that is not in UUID format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx), triggering an IllegalArgumentException.
{
"errorMessage": "Invalid UUID string: not-a-uuid",
"errorType": "API_ERROR",
"status": 400,
"errorId": "corr-abc-124",
"timestamp": "2026-02-27T10:30:01",
"path": "/invoice/PL/invoice-status"
}
401 - Unauthorized
Returned when the R-Auth header is not sent, the token signature is invalid, or the token's exp (expiration) time has passed.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"status": 401,
"errorId": "corr-abc-125",
"timestamp": "2026-02-27T10:30:02",
"path": "/invoice/PL/invoice-status"
}
404 - Not Found
Thrown as a NotFoundException when no company matching the provided apiKey is found in the database.
{
"errorMessage": "Company not found!",
"errorType": "Company not found!",
"status": 404,
"errorId": "corr-abc-126",
"timestamp": "2026-02-27T10:30:03",
"path": "/invoice/PL/invoice-status"
}
404 - Not Found - Invoice Not Found in KSeF
Returned when no invoice matching the provided invoiceReferenceNumber or sessionReferenceNumber is found in the KSeF system.
{
"errorMessage": "Invoice not found!",
"errorType": "Invoice not found!",
"status": 404,
"errorId": "corr-abc-127",
"timestamp": "2026-02-27T10:30:04",
"path": "/invoice/PL/invoice-status"
}
422 - Unprocessable Entity
Thrown when an unprocessable state is detected at the business logic layer. May occur when the invoice's current KSeF status is not valid for the query.
{
"errorMessage": "Invoice status not allowed!",
"errorType": "Invoice status not allowed!",
"status": 422,
"errorId": "corr-abc-128",
"timestamp": "2026-02-27T10:30:05",
"path": "/invoice/PL/invoice-status"
}
500 - Internal Server Error
Returned when a connection to KSeF cannot be established, certificate-based authentication fails, or the KSeF response cannot be parsed. The errorMessage field contains the raw error message from KSeF.
{
"errorMessage": "Invoice status error: Connection refused to KSeF endpoint",
"errorType": "API_ERROR",
"status": 500,
"errorId": "corr-abc-129",
"timestamp": "2026-02-27T10:30:06",
"path": "/invoice/PL/invoice-status"
}
500 - Internal Server Error - Unexpected Server Error
Returned when an unclassified RuntimeException or Exception is caught.
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"status": 500,
"errorId": "corr-abc-130",
"timestamp": "2026-02-27T10:30:07",
"path": "/invoice/PL/invoice-status"
}
16. Invoice Sync POST
17. Get Invoice Upo By Ksef POST
Purpose of Use: This endpoint downloads the UPO (Urzędowe Poświadczenie Odbioru — Official Receipt Confirmation) document in PDF format. The UPO confirms that an invoice has been successfully submitted to and registered in Poland's KSeF (Krajowy System e-Faktur) system.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/invoice-upo-by-ksef |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/invoice-upo-by-ksef' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data-raw '{
"apiKey": "<YOUR_API_KEY>",
"companyId": "<YOUR_COMPANY_ID>",
"invoiceReferenceNumber": "FA-000001",
"ksefReferenceNumber": "1234567890-20260101-...-..",
"sessionReferenceNumber": "20260101-50-AAAAAAAAAA-...-.."
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | API key used to identify the company. Required when companyId is not provided. |
| companyId | string (UUID) | Conditional | The unique identifier of the company in UUID format. Required when apiKey is not provided. |
| invoiceReferenceNumber | string | Optional | The internal invoice reference number. Not directly used by this endpoint's logic. |
| ksefReferenceNumber | string | Yes | The unique reference number assigned to the invoice by the KSeF system. |
| sessionReferenceNumber | string | Yes | The reference number of the KSeF session in which the invoice was submitted. |
At least one of apiKey or companyId must be provided. Both may be sent simultaneously; in that case, companyId takes priority.
Parameter Value References
| Field | Format | Example Value | Description |
|---|---|---|---|
| apiKey | string (32 character alphanumeric) | BW4dwsYvidnwFOv4i2rgnuw7EerngQbMp | API key assigned to the company by the system |
| companyId | UUID (RFC 4122) | 341ea0c8-930a-46f9-9029-a13ee3d482c6 | UUID in RFC 4122 format |
| invoiceReferenceNumber | Free text | FA-059542, INV-2026-001 | Internal invoice number |
| ksefReferenceNumber | taxId-date-... | 8460002329-20260227-3CFD8D000000-EB | Generated by KSeF |
| invoiceIdentifier | (hash)-(suffix) | Globally unique invoice identifier | |
| sessionReferenceNumber | {date}-SO-{sessionId}-{checksum} | 20260227-SO-1A5BDF5000-C51B21692B-0A | Returned after a KSeF session is opened |
Responses
200 - Successful Response
On success, the response body is not a JSON object. It is a binary PDF file.
| Header | Value |
|---|---|
| Content-Type | application/pdf |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Content-Disposition | attachment; filename=upo_{ksefReferenceNumber}.pdf |
| Response Body | binary (byte[]) |
400 - Bad Request
These errors are thrown during request validation, before any business logic is executed.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"status": 400,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: Both apiKey and companyId are null or absent in the request body.
Resolution: Provide at least one of apiKey or companyId.
400 - Bad Request - Missing KSeF reference fields
{
"errorMessage": "sessionReferenceNumber and ksefReferenceNumber fields must be filled.",
"status": 400,
"errorId": "b2c3d4e5-f6a7-8901-bcde-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: sessionReferenceNumber or ksefReferenceNumber is null or missing.
Resolution: Provide both fields. These values are returned in the response when an invoice is submitted to KSeF.
400 - Bad Request - Invalid UUID format
{
"errorMessage": "Invalid UUID string: not-a-valid-uuid",
"status": 400,
"errorId": "c3d4e5f6-a7b8-9012-cdef-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: The companyId field does not conform to RFC 4122 UUID format.
Resolution: Provide companyId in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
401 - Unauthorized
These errors are thrown during JWT token validation of the R-Auth header.
{
"errorMessage": "JWT expired",
"status": 401,
"errorId": "d4e5f6a7-b8c9-0123-defa-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: The JWT token in the R-Auth header has passed its exp claim expiration time.
Resolution: Obtain a new JWT token and retry the request.
401 - Unauthorized - Invalid token
{
"errorMessage": "invalid jwt",
"status": 401,
"errorId": "e5f6a7b8-c9d0-1234-efab-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: The R-Auth header is missing, empty, or contains a token with an invalid signature.
Resolution: Retry the request with a valid JWT token.
401 - Unauthorized - Unexpected token issuer
{
"errorMessage": "unexpected issuer: <received_issuer>",
"status": 401,
"errorId": "f6a7b8c9-d0e1-2345-fabc-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: The iss (issuer) claim in the JWT token does not match the expected system value.
Resolution: Ensure the token is obtained from the correct identity provider.
404 - Not Found
{
"errorMessage": "User not found",
"errorType": "USER_NOT_FOUND",
"status": 404,
"errorId": "a7b8c9d0-e1f2-3456-abcd-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: Although the JWT token is valid, the user encoded in the token cannot be found in the database. The account may have been deleted or deactivated.
Resolution: Verify the account status.
500 - Internal Server Error
{
"errorMessage": "Authentication error: No active certificate found for user or company: <companyId>.",
"status": 500,
"errorId": "bb8c9d0e1-f2a3-4567-bcde-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: No active digital certificate was found for the user or company required to authenticate with KSeF. KSeF authentication is certificate based and the system first looks for a user level certificate, then falls back to the company level certificate.
Resolution: Verify that an active KSeF digital certificate has been uploaded to the user or company account.
500 - Internal Server Error - KSeF API failure
{
"errorMessage": "Get invoice UPO by KSeF error: <ksef_api_error_details>",
"status": 500,
"errorId": "c9d0e1f2-a3b4-5678-cdef-...",
"timestamp": "2026-02-27T10:15:30.123",
"path": "/invoice/PL/invoice-upo-by-ksef"
}
Cause: An error occurred while communicating with the Polish Ministry of Finance KSeF API. The ksefReferenceNumber or sessionReferenceNumber may be invalid, the referenced invoice may not exist within that session, or KSeF services may be temporarily unavailable.
Resolution: Verify that both ksefReferenceNumber and sessionReferenceNumber are correct and correspond to the same invoice session. If the issue persists, check KSeF service status.
18. Get Invoice Upo By Reference POST
This endpoint returns the UPO (Urzędowe Potwierdzenie Odbioru — Official Receipt Confirmation) document in PDF format for an invoice that has been successfully submitted to Poland's national e-invoicing system, KSeF (Krajowy System e-Faktur).
The UPO document is a legally binding official confirmation issued by KSeF, certifying that the invoice has been received and processed by the system. Under Polish tax regulations, this document serves as the official proof that the e-invoice submission process has been completed and the invoice has been recorded in the national system.
The endpoint identifies the invoice using the invoice reference number (invoiceReferenceNumber) and the session reference number (sessionReferenceNumber), without requiring the KSeF reference number. This makes it suitable for scenarios where the KSeF reference number has not yet been obtained, or where only the invoice and session reference numbers are available.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/invoice-upo-by-reference |
| Method | POST |
| Authorization | Required (JWT via R-Auth header) |
Example Request
curl -X POST 'https://api-stage.docnova.ai/invoice/PL/invoice-upo-by-reference' \
-H "accept: */*" \
-H "R-Auth: <YOUR_JWT_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"apiKey": "<YOUR_API_KEY>",
"companyId": "<YOUR_COMPANY_ID>",
"invoiceReferenceNumber": "<INVOICE_REFERENCE_NUMBER>",
"ksefReferenceNumber": "<KSEF_REFERENCE_NUMBER>",
"sessionReferenceNumber": "<SESSION_REFERENCE_NUMBER>"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | API key used to identify the company. Required if companyId is not provided. |
| companyId | string (UUID) | Conditional | Unique internal system identifier for the company (UUID format). Required if apiKey is not provided. |
| invoiceReferenceNumber | string | Yes | Internal reference number of the invoice. Generated during submission to KSeF and stored in the system. |
| ksefReferenceNumber | string | No | KSeF-assigned invoice reference number. Not used by this endpoint, belongs to the /invoice-upo-by-ksef endpoint. |
| sessionReferenceNumber | string | Yes | Reference number of the KSeF session during which the invoice was submitted. |
Note: Conditional requirement — At least one of apiKey or companyId must be provided.
Parameter Values Reference
| Field | Format | Example |
|---|---|---|
| apiKey | 32-character alphanumeric string | ************* (obfuscated) |
| companyId | UUID (8-4-4-4-12) | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
| invoiceReferenceNumber | (YYYYMMDD)-(TYPE)-(HEX8)-(HEX10)-(HEX2) | 20260115-EE-1A31C46000-28898017D9-3F |
| ksefReferenceNumber | (NIP)-(YYYYMMDD)-(SEQ14)-(XX) | 8460002329-20260115-010040996334-79 |
| sessionReferenceNumber | (YYYYMMDD)-(TYPE)-(HEX8)-(HEX10)-(XX) | 20260115-SO-1A31BCD000-C238BC1199-65 |
Responses
200 - Successful Response
When HTTP 200 OK is returned, the response body is a binary PDF file.
400 - Bad Request
{
"errorMessage": "Detailed description of the error",
"errorType": "ERROR_CODE",
"status": 400,
"errorTitle": "BAD_REQUEST",
"timestamp": "2026-03-04T12:00:00",
"path": "/invoice/PL/invoice-upo-by-reference",
"errorId": "correlation-id-value",
"details": {},
"validationErrors": []
}
400 - Bad Request — Missing Required Parameter (apiKey / companyId)
Trigger Condition: Both the apiKey and companyId fields are omitted from the request.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": "API_ERROR",
"status": 400,
"errorTitle": "BAD_REQUEST",
"timestamp": "2026-03-04T12:00:00",
"path": "/invoice/PL/invoice-upo-by-reference"
}
400 - Bad Request — Missing Required Parameter (sessionReferenceNumber / invoiceReferenceNumber)
Trigger Condition: The sessionReferenceNumber or invoiceReferenceNumber field is not provided.
{
"errorMessage": "sessionReferenceNumber and invoiceReferenceNumber fields must be filled.",
"errorType": "API_ERROR",
"status": 400,
"errorTitle": "BAD_REQUEST",
"timestamp": "2026-03-04T12:00:00",
"path": "/invoice/PL/invoice-upo-by-reference"
}
400 - Bad Request — Invalid API Key
Trigger Condition: The provided apiKey does not match any company registered in the system.
{
"errorMessage": "Api Key Didn't Match",
"errorType": "API_ERROR",
"status": 400,
"errorTitle": "BAD_REQUEST",
"timestamp": "2026-03-04T12:00:00",
"path": "/invoice/PL/invoice-upo-by-reference"
}
400 - Bad Request — KSeF UPO Retrieval Error
Trigger Condition: The connection to KSeF services fails, certificate authentication against KSeF fails, or no UPO document is found on the KSeF side for the specified reference numbers.
{
"errorMessage": "Get invoice UPO by reference error: <KSeF error message>",
"errorType": "API_ERROR",
"status": 400,
"errorTitle": "BAD_REQUEST",
"timestamp": "2026-03-04T12:00:00",
"path": "/invoice/PL/invoice-upo-by-reference"
}
401 - Unauthorized
Trigger Condition: The R-Auth header is absent, or contains an expired or invalid JWT token.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"status": 401,
"errorTitle": "UNAUTHORIZED",
"timestamp": "2026-03-04T12:00:00",
"path": "/invoice/PL/invoice-upo-by-reference"
}
If the JWT token has expired, the errorMessage field will be "JWT expired".
404 - Not Found
Trigger Condition: The provided companyId does not correspond to any company registered in the system.
{
"errorMessage": "Company not found",
"errorType": "NOT_FOUND",
"status": 404,
"errorTitle": "NOT_FOUND",
"timestamp": "2026-03-04T12:00:00",
"path": "/invoice/PL/invoice-upo-by-reference"
}
500 - Internal Server Error
Trigger Condition: A KSeF certificate loading failure, AES decryption error, or an unexpected system exception occurs.
{
"errorMessage": "An unexpected error occurred",
"errorType": "SERVER_ERROR",
"status": 500,
"errorTitle": "INTERNAL_SERVER_ERROR",
"timestamp": "2026-03-04T12:00:00",
"path": "/invoice/PL/invoice-upo-by-reference"
}
19. Get Qr Link POST
Purpose of Use: This endpoint is designed to generate an invoice verification link (QR Link) for invoices that have been registered within Poland's official electronic invoicing system, KSeF. The generated URL allows users to verify two key aspects of an invoice: its authenticity and its registration status with KSeF. This verification is performed through Poland's official Ministry of Finance portal.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/qr-link |
| Method | POST |
| Authorization | R-Auth: JWT Token |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/qr-link' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"apiKey": "<API_KEY>",
"companyId": "<COMPANY_UUID>",
"ksefReferenceNumber": "<KSEF_REFERENCE_NUMBER>"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | API key used to identify the company. Required when companyId is not provided. |
| companyId | string (UUID) | Conditional | Unique identifier of the company (UUID v4 format). Required when apiKey is not provided. |
| ksefReferenceNumber | string | Yes | The reference number assigned to the invoice within the KSeF system. |
At least one of apiKey or companyId must be provided.
Parameter Value Reference
| Field | Format | Example Value |
|---|---|---|
| apiKey | Alphanumeric, typically 32 characters | BW4dwsrYidnwFOv4i2rguw7EerngQbMp |
| companyId | UUID v4 — xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | 341ea08e-930a-4619-9029-a13ee3d482c6 |
| ksefReferenceNumber | (NIP)-(YYYYMMDD)-(HexID)-(Checksum) | 8460002329-20260227-5B0F8D000000-4C |
Responses
200 - Successfull Response
The response body is plain text (text/plain) and contains the KSeF invoice verification URL.
Example URL format:
https://ksef.mf.gov.pl/web/verify?sef={ksefReferenceNumber}&nip={NIP}&date={issueDate}&hash={SHA256_BASE64}
Response Field Description
| Field | Type | Description |
|---|---|---|
| response body | string (URL) | The invoice verification URL pointing to the KSeF verification portal. Used to prove the authenticity of the invoice on the Polish Ministry of Finance's official verification page. |
400 - Bad Request
Returned when both apiKey and companyId are omitted from the request. The system requires at least one to identify the company.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": null,
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/qr-link"
}
400 - Bad Request — Invalid API Key
Returned when the provided apiKey does not match any company in the database. When only apiKey is provided (without companyId), the system looks up the company by that key. If no match is found, this error is returned.
{
"errorMessage": "Api Key Didnt Match",
"errorType": null,
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/qr-link"
}
401 - Unauthorized
The JWT token in the R-Auth header is invalid, malformed, or expired. Obtain a new token and retry the request.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/qr-link"
}
500 - Internal Server Error
The service fails to authenticate against the KSeF system using the company's certificate. The certificate cannot be found, has expired, or is rejected by KSeF.
{
"errorMessage": "QR link generation error: Authentication failed - certificate not found or invalid.",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/qr-link"
}
500 - Internal Server Error — Invalid KSeF Reference Number / Invoice Not Found
No invoice matching the given ksefReferenceNumber can be found in the KSeF system (e.g., wrong number, deleted invoice, or record not yet processed).
{
"errorMessage": "QR link generation error: Invoice not found for reference: <ksefReferenceNumber>",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/qr-link"
}
500 - Internal Server Error — Invoice XML Parsing Error
The invoice XML successfully downloaded from KSeF cannot be parsed due to an unexpected format. The service attempts to parse the XML to extract the seller's NIP and invoice issue date.
{
"errorMessage": "QR link generation error: Failed to parse invoice XML",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/qr-link"
}
500 - Internal Server Error — QR Verification URL Generation Failure
The Ministry of Finance verification link service fails to construct the URL. This generally indicates a KSeF SDK integration issue.
{
"errorMessage": "QR link generation error: Failed to generate online invoice QR code: <detail>",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-02-27T10:00:00",
"path": "/invoice/PL/qr-link"
}
20. Sign and Send Invoice POST
Purpose of Use: This endpoint digitally signs and submits an invoice to KSeF (Krajowy System e-Faktur), Poland's national e-invoicing platform mandated by Polish tax law. The invoice XML must conform to the KSeF FA(3) schema (version 1-OE, xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/") and be transmitted as a Base64-encoded string.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/send-invoice |
| Method | POST |
| Authorization | R-Auth: JWT Token |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/send-invoice' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"invoiceXml": "<BASE64_ENCODED_KSEF_FA3_XML>",
"apiKey": "<YOUR_API_KEY>",
"companyId": "<YOUR_COMPANY_UUID>"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| invoiceXml | string | Yes | Base64-encoded KSeF FA(3) schema-compliant invoice XML (xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/"). Cannot be null. |
| apiKey | string | Conditional | API key identifying the company. At least one of apiKey or companyId must be provided. |
| companyId | string (UUID) | Conditional | Company UUID in the system. At least one of apiKey or companyId must be provided. Example: 341ea08e-930a-4619-9029-a13ee3d482c6 |
Note: If both apiKey and companyId are provided, companyId takes precedence. If both are missing, the request is rejected with 400 Bad Request.
InvoiceXmlContent — KSeF FA(3) Schema Fields
The table below describes the key elements of the XML that must be Base64-encoded and submitted in the invoiceXml field.
General Invoice Fields
| XML Field | Type / Format | Required | Accepted Values / Description |
|---|---|---|---|
| KodFormularza | string | Yes | Fixed: FA. Attributes: kodSystemowy="FA(3)", wersjaSchemy="1-OE" |
| WariantFormularza | integer | Yes | 3 (fixed value for FA(3) schema) |
| DataWytworzeniaFa | dateTime (ISO8601) | Yes | Date and time the invoice was generated. Example: 2025-12-17T14:31:37Z |
| Podmiot1 / NIP | string (10 digits) | Yes | Seller's Polish tax identification number (NIP) |
| Podmiot1 / Nazwa | string | Yes | Seller's registered company name |
| Podmiot1 / KodKraju | string (2 chars) | Yes | Seller's country code. Example: PL |
| Podmiot2 / NIP | string (10 digits) | Yes | Buyer's Polish tax identification number (NIP) |
| Podmiot2 / Nazwa | string | Yes | Buyer's registered company name |
| Podmiot2 / NrKlienta | string | No | Customer reference number assigned to the buyer |
| KodWaluty | string (3 chars) | Yes | ISO 4217 currency code. Example: PLN, EUR, USD |
| P_1 (Fa field) | date (YYYY-MM-DD) | Yes | Invoice issue date |
| P_2 (Fa field) | string | Yes | Invoice number. Example: EA-059852 |
| P_6 (Fa field) | date (YYYY-MM-DD) | No | Goods/services delivery date |
| P_13_1 | decimal | Yes | Net amount subject to 23% VAT rate (excl. VAT) |
| P_14_1 | decimal | Yes | VAT amount at 23% rate |
| P_15 | decimal | Yes | Total gross invoice amount (incl. VAT) |
| RodzajFaktury | string | Yes | Invoice type: VAT, KOR, ZAL, ROZ, UPR, KOR_ZAL, KOR_ROZ |
Invoice Line Item and Footer Fields
| XML Field | Type / Format | Required | Accepted Values / Description |
|---|---|---|---|
| FaWiersz / P_7 | string | Yes | Name or description of the goods or services |
| FaWiersz / P_8A | string | Yes | Unit code. Example: EA (each), KGM (kilogram), MTR (metre) |
| FaWiersz / P_8B | decimal | Yes | Quantity |
| FaWiersz / P_9A | decimal | Yes | Unit net price |
| FaWiersz / P_11 | decimal | Yes | Line net amount |
| FaWiersz / P_12 | integer or string | Yes | VAT rate (%). Example: 23, 8, 5, 0, zw (exempt) |
| TerminPlatnosci / Termin | date (YYYY-MM-DD) | No | Payment due date |
| Zamowienia / NrZamowienia | string | No | Related purchase order number |
| Stopka / KRS | string | No | National Court Register number |
| Stopka / REGON | string | No | Statistical identification number (REGON) |
Responses
200 - Successfull Response
{
"referenceNumber": "1234567890-20251217-...",
"invoiceNumber": "EA-059852",
"processingCode": 200,
"sessionReferenceNumber": "SESSION-REF-XYZ-001"
}
400 - Bad Request
Returned when both apiKey and companyId are missing.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2025-12-17T14:31:37",
"path": "/invoice/PL/send-invoice"
}
400 - Bad Request — Duplicate Invoice
Returned when an invoice with the same number, NIP, and year has already been submitted to KSeF.
{
"errorMessage": "Invoice sending error: Duplicate invoice detected. An invoice with number 'EA-0598544442', NIP '8460002329' and year 2025 has already been submitted to KSeF.",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "51469932-9516-436b-a760-...",
"status": 400,
"timestamp": "2026-02-27T05:09:24.777",
"path": "/invoice/PL/send-invoice"
}
400 - Bad Request — Validation Error (invoiceXml empty)
{
"errorMessage": "Human-readable error description",
"errorType": "ERROR_CODE",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "correlation-id-uuid",
"timestamp": "2025-12-17T14:31:37",
"path": "/invoice/PL/send-invoice",
"validationErrors": [
{
"field": "invoiceXml",
"code": "NOT_NULL",
"message": "invoiceXml field must not be empty"
}
]
}
401 - Unauthorized
Returned when the JWT token is invalid, malformed, or expired.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2025-12-17T14:31:37",
"path": "/invoice/PL/send-invoice"
}
404 - Not Found
Returned when no company is found for the given companyId or apiKey.
{
"errorMessage": "Company not found!",
"errorType": "COMPANY_NOT_FOUND",
"errorTitle": "NOT_FOUND",
"status": 404,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2025-12-17T14:31:37",
"path": "/invoice/PL/send-invoice"
}
422 - Unprocessable Entity
Returned when another invoice submission is already in progress for the same company.
{
"errorMessage": "Processing is already in progress!",
"errorType": "CONCURRENT_PROCESSING",
"errorTitle": "UNPROCESSABLE_ENTITY",
"status": 422,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2025-12-17T14:31:37",
"path": "/invoice/PL/send-invoice"
}
500 - Internal Server Error
Returned when an unexpected server-side error occurs.
{
"errorMessage": "An internal error occurred",
"errorType": "INTERNAL_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"timestamp": "2025-12-17T14:31:37",
"path": "/invoice/PL/send-invoice"
}
21. Sign and Send Invoice With Attachment POST
22. Get Session Failed Invoices POST
This endpoint is used to query invoices that failed to process, were rejected, or encountered errors within a batch invoice submission session on Poland's KSeF (Krajowy System e-Faktur — National e-Invoice System).
Under Polish e-invoice regulations, invoices are submitted to KSeF on a session basis (batch session). A single session may contain dozens or hundreds of invoices, each of which is individually validated and processed by KSeF. Invoices that fail (due to schema violations, invalid tax ID, formatting errors, authorization issues, etc.) are marked with a failed status within the session.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/session-failed-invoices |
| Method | POST |
| Authentication | R-Auth: JWT Token |
Example Request
curl -X POST 'https://api-stage.docnova.ai/invoice/PL/session-failed-invoices' \
-H "accept: */*" \
-H "R-Auth: <JWT_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"apiKey": "<API_KEY>",
"companyId": "<COMPANY_UUID>",
"pageOffset": 0,
"pageSize": 20,
"sessionReferenceNumber": "<SESSION_REFERENCE_NUMBER>"
}'
Request Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| sessionReferenceNumber | string | Yes | The KSeF session reference number to query for failed invoices. Generated by the system when the session is opened. |
| companyId | string (UUID) | Conditional | The internal unique identifier for the company in the system. Required when apiKey is not provided. |
| apiKey | string | Conditional | The API key belonging to the company. Required when companyId is not provided. The system automatically resolves companyId from this value. |
| pageSize | integer | Optional | The number of invoices to return per page. Default value is 10. |
| pageOffset | integer | Optional | The number of records to skip (offset-based pagination). This parameter is accepted in the current implementation but is hardcoded to 0; it is planned to be activated in a future release. |
Parameter Value Reference
| Field Name | Example Value | Format / Constraint | Note |
|---|---|---|---|
| sessionReferenceNumber | 20260227-SO-1A58D5F000-C518216928-0A | KSeF session reference in YYYYMMDD-XX-XXXXXXXX-XXXXXXXXXX-XX format | Format generated by the KSeF system |
| companyId | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | RFC 4122 UUID v4 format | Should not be used together with apiKey |
| apiKey | ABCDEFGHxxxxxxxxxxxxxxxxxxxx | 32-character alphanumeric string | Should not be used together with companyId |
| pageSize | 20 | Positive integer between 1 and 100 | Default: 10 |
| pageOffset | 0 | 0 or a positive integer | Currently only 0 is effective |
Responses
200 - Successful Response
{
"continuationToken": "eyjwYWdlT2Zmc2V0ljoyMH0=",
"invoices": [
{
"ordinalNumber": 3,
"referenceNumber": "INV-2026-00345",
"invoiceNumber": "FV/2026/03/003",
"ksefNumber": null,
"invoiceFileName": "FV_2026_03_003.xml",
"invoiceHash": "a3f1c2d4e5b6...",
"invoicingDate": "2026-03-04T08:30:00.000Z",
"acquisitionDate": "2026-03-04T08:30:05.000Z",
"permanentStorageDate": null,
"invoicingMode": "Offline",
"upoDownloadUrl": null,
"upoDownloadUrlExpirationDate": null,
"status": {}
}
]
}
Top-Level Fields
| Field Name | Type | Description |
|---|---|---|
| continuationToken | string | Continuation token used to fetch the next page. Returns null when no further records are available. |
| invoices | array<Invoice> | List of failed invoice objects |
Invoice Object
| Field Name | Type | Description |
|---|---|---|
| ordinalNumber | integer | Sequential position within the session |
| referenceNumber | string | Internal reference number assigned to the invoice by the sender system |
| invoiceNumber | string | Business-facing invoice number (e.g. FV/2026/03/001) |
| ksefNumber | string | Unique number assigned to the invoice by KSeF. May be null for failed invoices. |
| invoiceFileName | string | Name of the invoice file as stored in the KSeF system |
| invoiceHash | string | Hash value used to verify the integrity of the invoice content |
| invoicingDate | string (ISO 8601) | Date and time the invoice was submitted to KSeF |
| acquisitionDate | string (ISO 8601) | Date and time KSeF received the invoice |
| permanentStorageDate | string (ISO 8601) | Date and time the invoice was permanently archived in KSeF |
| invoicingMode | string (enum) | Submission mode of the invoice. Possible values: Online, Offline |
| upoDownloadUrl | string | Download link for the UPO (Urzędowe Potwierdzenie Odbioru - Official Receipt Confirmation) document |
| upoDownloadUrlExpirationDate | string | Expiration date of the upoDownloadUrl link |
| status | object<Status> | KSeF processing status object for the invoice |
400 - Bad Request
{
"code": 400,
"description": "Invoice XML does not conform to schema",
"details": [
"NIP field contains an invalid format",
"Mandatory field 'DatWystFaktur' is missing"
],
"extensions": {
"additionalProp1": "schemaVersion-2025-06-25",
"additionalProp2": "validatorId-KSeF-VAL-01"
}
}
400 - Bad Request — Missing Required Field
Trigger Condition: Thrown when both apiKey and companyId are absent from the request, or when sessionReferenceNumber is missing.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-03-04T10:15:30",
"path": "/invoice/PL/session-failed-invoices"
}
400 - Bad Request — Invalid UUID Format
Trigger Condition: The companyId field contains a value that does not conform to UUID format, causing the UUID.fromString() call to throw an IllegalArgumentException.
{
"errorMessage": "Invalid UUID string: abc-not-a-uuid",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-03-04T10:15:31",
"path": "/invoice/PL/session-failed-invoices"
}
400 - Bad Request — KSeF API Error
Trigger Condition: Raised when an ApiException occurs during a KSeF SDK call, which the service then wraps and propagates as an ApiError.
{
"errorMessage": "Get session failed invoices error: KSeF returned HTTP 400 - Invalid session reference",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-03-04T10:16:00",
"path": "/invoice/PL/session-failed-invoices"
}
401 - Unauthorized
Trigger Condition: The JWT token in the R-Auth header is missing, invalid, or expired, and the Spring Security filter rejects the request, handled via AuthorizationServiceException.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-03-04T10:15:45",
"path": "/invoice/PL/session-failed-invoices"
}
401 - Unauthorized — KSeF Certificate Authentication Failure
Trigger Condition: Thrown when the company's KSeF certificate cannot be found or when authentication with KSeF using the certificate fails. Handled via AuthorizationServiceException.
{
"errorMessage": "Certificate authentication failed for the given company",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-03-04T10:16:05",
"path": "/invoice/PL/session-failed-invoices"
}
404 - Not Found
Trigger Condition: When apiKey is provided, the system attempts to resolve the corresponding companyId from the database. A NotFoundException is thrown if no match is found.
{
"errorMessage": "Company not found for given API key",
"errorType": "COMPANY_NOT_FOUND",
"errorTitle": "NOT_FOUND",
"status": 404,
"timestamp": "2026-03-04T10:16:10",
"path": "/invoice/PL/session-failed-invoices"
}
422 - Unprocessable Entity
Trigger Condition: Thrown when data is technically valid but a business-level inconsistency is detected. Handled via GeneralException.
{
"errorMessage": "Session is still in progress, failed invoices are not yet available",
"errorType": "GENERAL_ERROR",
"errorTitle": "UNPROCESSABLE_ENTITY",
"status": 422,
"timestamp": "2026-03-04T10:16:20",
"path": "/invoice/PL/session-failed-invoices"
}
500 - Internal Server Error
Trigger Condition: Thrown when the KSeF service is unreachable, the network connection is lost, or an unhandled exception occurs at the SDK level. Caught as a RuntimeException or Exception.
{
"errorMessage": "Get session failed invoices error: Connection timeout to KSeF service",
"errorType": "API_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-03-04T10:16:30",
"path": "/invoice/PL/session-failed-invoices"
}
23. Get Session Invoices POST
Purpose of Use: This endpoint retrieves, in a paginated manner, the list of invoices that were processed within a previously initiated and completed KSeF (Krajowy System e-Faktur — Poland's National e-Invoice System) submission session.
In KSeF bulk invoice submission, the flow is two-phased: first a session is opened, then invoices are submitted to it. Once the session is closed, this endpoint is called to retrieve the list of invoices that were successfully accepted by KSeF within that session.
The response includes the official KSeF-assigned reference numbers, hash values, processing statuses, and UPO download links for all invoices processed within the session.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/session-invoices |
| Method | POST |
| Authentication | JWT Token (R-Auth header) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/session-invoices' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"apiKey": "<API_KEY>",
"companyId": "<COMPANY_UUID>",
"pageOffset": 0,
"pageSize": 100,
"sessionReferenceNumber": "<SESSION_REFERENCE_NUMBER>"
}'
Request Parameters
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| apiKey | string | Conditional* | — | API key identifying the company. Required when companyId is not provided. |
| companyId | string | Conditional* | — | Unique company identifier in UUID format. Required when apiKey is not provided. If both are supplied, companyId takes precedence. |
| sessionReferenceNumber | string | Yes | — | The KSeF session reference number to query. Generated by KSeF when the session was initiated. |
| pageSize | integer | No | 10 | Maximum number of invoices to return in a single response. |
| pageOffset | integer | No | 0 | Starting offset for pagination. |
*Conditional Requirement: At least one of apiKey or companyId must be provided. Both cannot be omitted simultaneously.
Parameter Value Reference
| Field | Example Value | Valid Format / Range | Notes |
|---|---|---|---|
| apiKey | F9NBGSFDtQOcddN1OgKC... | Alphanumeric string | Obtained from the DocNova management panel. |
| companyId | 341ea08e-930a-4619-9029-a13ee3d482c6 | UUID v4 | Invalid format returns 400. |
| sessionReferenceNumber | 20260301-SO-165011A000-D6815F9275-5C | KSeF session reference format | Must be the value returned by KSeF. |
| pageSize | 100 | Positive integer (1–100 recommended) | Defaults to 10 if not specified. |
| pageOffset | 0 | Non-negative integer (>= 0) | Use 0 for the first page. |
Responses
200 - Successful Response
{
"invoices": [
{
"ordinalNumber": 1,
"invoiceNumber": "FV/2026/03/001",
"ksefNumber": "1234567890-20260301-...-..",
"referenceNumber": "REF-20260301-001",
"invoiceHash": "SHA256:abc123def456==",
"invoiceFileName": "FV_2026_03_001.xml",
"invoicingDate": "2026-03-01T16:50:11+01:00",
"acquisitionDate": "2026-03-01T16:50:15+01:00",
"permanentStorageDate": "2026-03-01T16:50:20+01:00",
"status": {
"code": 200,
"description": "Invoice accepted by KSeF",
"details": [],
"extensions": {}
},
"upoDownloadUrl": "https://ksef.mf.gov.pl/upo/download/abc123",
"upoDownloadUrlExpirationDate": "2026-03-08T16:50:20+01:00",
"invoicingMode": "ONLINE"
}
],
"continuationToken": null
}
Response Fields
SessionInvoicesResponse
| Field | Type | Description |
|---|---|---|
| invoices | Array<SessionInvoiceStatus> | List of invoice records processed within the session. |
| continuationToken | string | null | Cursor-based pagination token. Pass in subsequent requests for the next page. Returns null on the last page. |
essionInvoiceStatus Object
| Field | Type | Description |
|---|---|---|
| ordinalNumber | integer | Sequential order number of the invoice within the session. |
| invoiceNumber | string | Internal reference number of the invoice. |
| ksefNumber | string | Official invoice number assigned by KSeF. |
| referenceNumber | string | Submission reference number used when sending the invoice. |
| invoiceHash | string | Hash value computed for integrity verification. |
| invoiceFileName | string | Filename of the invoice document submitted to KSeF. |
| invoicingDate | string (ISO 8601) | Date and time the invoice was issued. |
| acquisitionDate | string (ISO 8601) | Date and time KSeF accepted the invoice. |
| permanentStorageDate | string (ISO 8601) | Date and time the invoice was permanently stored in KSeF. |
| status | StatusInfo | Processing status of the invoice within KSeF. |
| upoDownloadUrl | string | Download link for the UPO (Official Receipt Confirmation) document. |
| upoDownloadUrlExpirationDate | string | Expiration date of the UPO download link. |
| invoicingMode | string | Invoice submission mode. Values: ONLINE, OFFLINE |
StatusInfo Object
| Field | Type | Description |
|---|---|---|
| code | integer | KSeF processing status code. |
| description | string | Human-readable description of the status code. |
| details | Array<string> | Additional detail messages for the status. |
| extensions | map<string, string> | Additional status information in key-value format. |
400 - Bad Request
Neither apiKey nor companyId was provided in the request body. At least one of these fields is mandatory to identify the company.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": "IllegalArgumentException",
"errorTitle": "BAD_REQUEST",
"data": null,
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"details": {},
"validationErrors": [],
"timestamp": "2026-03-01T16:50:11.000Z",
"path": "/invoice/PL/session-invoices"
}
400 - Bad Request — sessionReferenceNumber Is Missing
sessionReferenceNumber is a required field. The exact reference number generated by KSeF when the session was initiated must be provided.
{
"errorMessage": "sessionReferenceNumber field must be filled.",
"errorType": "IllegalArgumentException",
"errorTitle": "BAD_REQUEST",
"data": null,
"errorId": "b2c3d4e5-f6a7-8901-bcde-...",
"status": 400,
"details": {},
"validationErrors": [],
"timestamp": "2026-03-01T16:50:11.000Z",
"path": "/invoice/PL/session-invoices"
}
400 - Bad Request — Invalid companyId Format
The companyId field must contain a valid UUID v4 value (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). Triggered by missing hyphens, incorrect length, or invalid characters.
{
"errorMessage": "Invalid UUID string: invalid-value",
"errorType": "IllegalArgumentException",
"errorTitle": "BAD_REQUEST",
"data": null,
"errorId": "c3d4e5f6-a7b8-9012-cdef-...",
"status": 400,
"details": {},
"validationErrors": [],
"timestamp": "2026-03-01T16:50:11.000Z",
"path": "/invoice/PL/session-invoices"
}
400 - Bad Request — apiKey Not Found in System
The provided apiKey value does not exist in the system or is currently inactive. Verify that a valid and active API key from the DocNova management panel is being used.
{
"errorMessage": "Get session invoices error: Api Key not found",
"errorType": "ApiError",
"errorTitle": "BAD_REQUEST",
"data": null,
"errorId": "d4e5f6a7-b8c9-0123-def0-...",
"status": 400,
"details": {},
"validationErrors": [],
"timestamp": "2026-03-01T16:50:11.000Z",
"path": "/invoice/PL/session-invoices"
}
400 - Bad Request — KSeF API General Error
The call to the KSeF external API failed. The errorMessage field contains the original error message returned by KSeF. Verify the validity of sessionReferenceNumber and ensure the KSeF service is reachable.
{
"errorMessage": "Get session invoices error: <KSeF error detail>",
"errorType": "ApiError",
"errorTitle": "BAD_REQUEST",
"data": null,
"errorId": "e5f6a7b8-c9d0-1234-ef01-...",
"status": 400,
"details": {},
"validationErrors": [],
"timestamp": "2026-03-01T16:50:11.000Z",
"path": "/invoice/PL/session-invoices"
}
401 - Unauthorized
No active KSeF certificate was found for the specified company during the KSeF authentication phase. Ensure that the company's KSeF certificate has been uploaded to the DocNova system and that its validity period has not expired.
{
"errorMessage": "No active certificate found for the company.",
"errorType": "UserCertificateNotFoundException",
"errorTitle": "UNAUTHORIZED",
"data": null,
"errorId": "f6a7b8c9-d0e1-2345-f012-...",
"status": 401,
"details": {},
"validationErrors": [],
"timestamp": "2026-03-01T16:50:11.000Z",
"path": "/invoice/PL/session-invoices"
}
401 - Unauthorized — Invalid or Missing JWT
The R-Auth header is missing, contains an invalidly signed JWT, or the token has expired. Obtain a fresh token from the DocNova authentication service and retry the request.
{
"errorMessage": "Unauthorized access. Invalid or expired token.",
"errorType": "AuthorizationServiceException",
"errorTitle": "UNAUTHORIZED",
"data": null,
"errorId": "a7b8c9d0-e1f2-3456-0123-...",
"status": 401,
"details": {},
"validationErrors": [],
"timestamp": "2026-03-01T16:50:11.000Z",
"path": "/invoice/PL/session-invoices"
}
500 - Internal Server Error
When sessionReferenceNumber is null, the internal validation error falls through to the generic RuntimeException handler and is returned as 500. The sessionReferenceNumber field must always be populated before sending the request.
{
"errorMessage": "sessionReferenceNumber field must be filled.",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "b0128590-7d21-4ae8-9b63-...",
"status": 500,
"timestamp": "2026-03-01T06:53:04.236995",
"path": "/invoice/PL/session-invoices"
}
24. Session Status POST
Purpose of Use: This endpoint is used to query the current status of a previously opened session on KSeF (Krajowy System e-Faktur), Poland's national e-invoicing system. When an invoice submission is sent to KSeF, the system assigns a reference number and processes the operation asynchronously. This endpoint returns the following information for the session associated with that reference number: session status, validity period, UPO (Official Receipt Confirmation) download links, and invoice counts (total, successful, failed).
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/session-status |
| Method | POST |
| Authorization | R-Auth: JWT Token |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/session-status' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"apiKey": "<API_KEY>",
"companyId": "<COMPANY_UUID>",
"pageOffset": 0,
"pageSize": 1000,
"referenceNumber": "<SESSION_REFERENCE_NUMBER>"
}'
Request Parameters
Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Conditional | API key belonging to the company. Required when companyId is not provided. |
| companyId | string (UUID) | Conditional | Unique identifier of the company (UUID v4 format). Required when apiKey is not provided. |
| pageOffset | integer | No | Pagination start offset. Reserved in the current implementation — not forwarded to KSeF. |
| pageSize | integer | No | Number of records per page. Reserved in the current implementation — not forwarded to KSeF. |
| referenceNumber | string | Yes | Session reference number assigned by KSeF. |
Conditional Requirement: At least one of apiKey or companyId must be provided. Both cannot be left empty simultaneously. If both are provided, companyId takes precedence.
Parameter Value Reference
| Field | Example Value | Format / Constraint |
|---|---|---|
| apiKey | F9NBGSFDtQOoddN1OgKCJ2ENZHlwmEG | Alphanumeric, 32 characters |
| companyId | 341ea08e-930a-46f9-9029-a13ee3d482c6 | UUID v4 — xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
| pageOffset | 0 | Integer >= 0 |
| pageSize | 1000 | Integer >= 1 |
| referenceNumber | 20260301-SB-16F5657000-20513B2097-F3 | KSeF session reference format |
Responses
200 - Successful Response
{
"status": {
"code": 200,
"description": "Session processed successfully.",
"details": [],
"extensions": {}
},
"validUntil": "2026-03-01T23:59:59+01:00",
"upo": {
"pages": [
{
"referenceNumber": "20260301-58-16F5657000-...-..",
"downloadUrl": "https://ksef.mf.gov.pl/upo/download/...",
"downloadUrlExpirationDate": "2026-03-02T12:00:00+01:00"
}
]
},
"invoiceCount": 10,
"successfulInvoiceCount": 9,
"failedInvoiceCount": 1
}
Response Fields
| Field | Type | Description |
|---|---|---|
| status | object | Session status information object |
| status.code | integer | Status code returned from the KSeF system |
| status.description | string | Human-readable description of the status code |
| status.details | Array<string> | Additional detail messages related to the status |
| status.extensions | map<string, string> | KSeF-specific extension fields |
| validUntil | string (ISO 8601 OffsetDateTime) | Date and time when the session validity expires (with timezone offset) |
| upo | object | UPO (Official Receipt Confirmation) information |
| upo.pages[] | Array<object> | List of UPO pages |
| upo.pages[].referenceNumber | string | UPO reference number |
| upo.pages[].downloadUrl | string (URI) | URL from which the UPO document can be downloaded |
| upo.pages[].downloadUrlExpirationDate | string (ISO 8601) | Expiration date and time of the download link |
| invoiceCount | integer | Total number of invoices processed in the session |
| successfulInvoiceCount | integer | Number of successfully accepted invoices |
| failedInvoiceCount | integer | Number of rejected or errored invoices |
CommonSessionStatus Values
| Value | Description |
|---|---|
| 200 (SUCCEEDED) | Session completed successfully |
| INPROGRESS | Session is still being processed |
| FAILED | Session processing failed |
| CANCELLED | Session was cancelled |
400 - Bad Request
Returned when both apiKey and companyId are null in the request body. The system cannot determine which company the operation should be performed for.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": null,
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-correlation-id",
"timestamp": "2026-03-01T12:00:00",
"path": "/invoice/PL/session-status",
"data": null,
"details": null,
"validationErrors": null
}
400 - Bad Request — API Key Not Found
Returned when companyId is not provided and the provided apiKey value does not correspond to any registered company in the database.
{
"errorMessage": "Api Key Didnt Match",
"errorType": null,
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-correlation-id",
"timestamp": "2026-03-01T12:00:00",
"path": "/invoice/PL/session-status",
"data": null,
"details": null,
"validationErrors": null
}
400 - Bad Request — KSeF Session Query Error
Occurs when the KSeF system returns an error while querying the session status through the KSeF SDK. Possible triggers include an invalid referenceNumber, an expired session, or a KSeF service-side error. The original error details from the SDK are appended to the errorMessage.
{
"errorMessage": "Session status error: <KSeF SDK error message>",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-correlation-id",
"timestamp": "2026-03-01T12:00:00",
"path": "/invoice/PL/session-status",
"data": null,
"details": null,
"validationErrors": null
}
401 - Unauthorized
Returned when the JWT token in the R-Auth header is invalid, malformed, or has expired. Thrown when the system cannot verify the identity of the requesting user or application.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "a1b2c3d4-correlation-id",
"timestamp": "2026-03-01T12:00:00",
"path": "/invoice/PL/session-status",
"data": null,
"details": null,
"validationErrors": null
}
500 - Internal Server Error
Returned in cases such as infrastructure failure during certificate-based KSeF authentication, network disconnection, or unforeseen runtime errors. The errorId (correlation ID) value can be used to locate the corresponding record in server logs.
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "a1b2c3d4-correlation-id",
"timestamp": "2026-03-01T12:00:00",
"path": "/invoice/PL/session-status",
"data": null,
"details": null,
"validationErrors": null
}
25. Get Session Upo POST
26. Submit Saved Invoice POST
Purpose of Use: This endpoint is used to submit a previously saved (draft or pending) Polish e-invoice document to KSeF (Krajowy System e-Faktur), Poland's official electronic invoicing infrastructure operated by the Polish Tax Authority.
Under Polish regulations, e-invoices are first saved to the Docnova system. After validation, approval, or batch processing steps are completed, this endpoint delivers the invoice to KSeF in a single call, granting it legal validity.
Authentication and process steps: The endpoint authenticates the company using either apiKey or companyId, opens a KSeF session utilizing the company's certificate, submits the invoice XML to KSeF, and returns the resulting KSeF reference in the response.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/submit-saved-invoice |
| Method | POST |
| Authorization | R-Auth: JWT Token |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/submit-saved-invoice' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"invoiceId": "<INVOICE_UUID>",
"apiKey": "<COMPANY_API_KEY>",
"companyId": "<COMPANY_UUID>"
}'
Request Parameters
Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| invoiceId | string(UUID v4) | Yes | The unique identifier of the saved invoice in Docnova to be submitted to KSeF. |
| apiKey | string | Conditional | API key used to identify the company. Required if companyId is not provided. |
| companyId | string(UUID v4) | Conditional | Unique identifier of the company submitting the invoice. Required if apiKey is not provided. |
Note: At least one of apiKey or companyId must be provided. If both are given, apiKey takes precedence.
Parameter Value Reference
| Field | Valid Values | Format | Example |
|---|---|---|---|
| invoiceId | Any saved invoice UUID in the system | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | d5878ec8-12e8-49fe-8e1e-09743acfc62a |
| apiKey | API key assigned to the company | Alphanumeric string | F9NBGSFDtQOcddN1OgKCJ2ENZHlwmEG |
| companyId | Company UUID registered in the system | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | 341ea08e-930a-4619-9029-a13ee3d482c6 |
Response
200 - Successful Response
{
"ksefReferenceNumber": "1234567890-20240115-...",
"sessionReferenceNumber": "20240115-123456-PL-SESSION",
"processingCode": 200,
"processingDescription": "Invoice processed successfully",
"invoicingDate": "2024-01-15T10:30:00Z",
"invoiceHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e46496934ca495991b7..."
}
400 - Bad Request
Both apiKey and companyId are absent from the request body.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": "IllegalArgumentException",
"status": 400,
"timestamp": "2024-01-15T10:30:00",
"path": "/invoice/PL/submit-saved-invoice"
}
400 - Bad Request — Invalid API Key
The provided apiKey does not match any company registered in the system.
{
"errorMessage": "Api Key Didnt Match",
"errorType": "IllegalArgumentException",
"status": 400,
"timestamp": "2024-01-15T10:30:00",
"path": "/invoice/PL/submit-saved-invoice"
}
400 - Bad Request — KSeF Authentication Failure
The company's KSeF certificate is missing, the certificate password is incorrect, or the certificate could not be parsed.
{
"errorMessage": "Authentication error: Failed to decrypt private key. Please check the password.",
"errorType": "ApiError",
"status": 400,
"timestamp": "2024-01-15T10:30:00",
"path": "/invoice/PL/submit-saved-invoice"
}
400 - Bad Request — KSeF Submission Error
The invoice XML is invalid, failed KSeF schema validation, or was rejected by the KSeF system.
{
"errorMessage": "Invoice sending error: Invalid XML schema for KSeF submission.",
"errorType": "ApiError",
"status": 400,
"timestamp": "2024-01-15T10:30:00",
"path": "/invoice/PL/submit-saved-invoice"
}
400 - Bad Request — Invalid Invoice Status
The invoice cannot be submitted because its current status does not allow KSeF submission. Expected status: READY_FOR_KSEF.
{
"errorMessage": "Invoice cannot be submitted. Current status: KSEF_PENDING, expected: READY_FOR_KSEF",
"errorTitle": "BAD_REQUEST",
"errorId": "8b16189c-b1d6-4814-9790-...",
"status": 400,
"timestamp": "2026-03-01T06:47:03.277764",
"path": "/invoice/PL/submit-saved-invoice"
}
401 - Unauthorized
The R-Auth header is absent, the token has expired, or the token signature is invalid.
{
"errorMessage": "Unauthorized",
"errorType": "AuthorizationServiceException",
"status": 401,
"timestamp": "2024-01-15T10:30:00",
"path": "/invoice/PL/submit-saved-invoice"
}
404 - Not Found
No invoice with the given invoiceId exists in the system, or the invoice does not belong to the specified company.
{
"errorMessage": "Invoice not found: d5878ec8-f2e8-49fe-8e1e-...",
"errorType": "NotFoundException",
"status": 404,
"timestamp": "2024-01-15T10:30:00",
"path": "/invoice/PL/submit-saved-invoice"
}
500 - Internal Server Error
Loss of connectivity with the KSeF system, an unexpected service failure, or an unhandled server-side exception.
{
"errorMessage": "An unexpected error occurred",
"errorType": "RuntimeException",
"status": 500,
"timestamp": "2024-01-15T10:30:00",
"path": "/invoice/PL/submit-saved-invoice"
}
27. Peppol - Get MLR GET
Purpose of Use This endpoint is used to query Message Level Response (MLR) records for invoices sent or received through the Peppol network.
MLR is a message level response mechanism in the Peppol infrastructure that indicates whether a document was successfully delivered, accepted, or rejected by the receiving party.
Endpoint Information
| Property | Value |
|---|---|
| URL | /peppol/search-mlr |
| Method | GET |
| Authentication | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/peppol/search-mlr?companyId={companyId}&counterpartParticipantId={counterpartParticipantId}&documentId={documentId}&fromDate={fromDate}&invoiceId={invoiceId}&toDate={toDate}' \
--header 'Accept: */*' \
--header 'R-Auth: {jwt_token}'
Request Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| companyId | string (UUID) | Yes | Unique identifier of the company to query. The user in the token must be associated with this company. |
| counterpartParticipantId | string | No | PEPPOL participant ID of the counterpart. Must be URL-encoded in PEPPOL standard format. |
| documentId | string (UUID) | No | Identifier of the PEPPOL document to query. |
| invoiceId | string (UUID) | No | Identifier of the invoice to query. |
| fromDate | string (ISO 8601 - YYYY-MM-DD) | No | Filter start date (inclusive). Returns MLR records from this date onward. |
| toDate | string (ISO 8601 - YYYY-MM-DD) | No | Filter end date (inclusive). Returns MLR records up to and including this date. |
Parameter Value Reference
| Parameter | Valid Format | Example Value | Notes |
|---|---|---|---|
| companyId | UUID v4 | Daf615ef-3789-4475-b109-3695796e0afd | Hyphen-separated 8-4-4-4-12 UUID format |
| counterpartParticipantId | PEPPOL Participant ID (URL-encoded) | iso6523-actorid-upis%3A%3A0208%3A0811368376 | Decoded Form: iso6523-actorid-upis::0208:0811368376 |
| documentId | UUID v4 | cb6cde62-7355-478c-8e7b-5330d2b8817 | |
| invoiceId | UUID v4 | 5a6b5466-e63b-4802-ad11-672dd4903b1a | |
| fromDate | YYYY-MM-DD | 2024-01-01 | ISO 8601 date format |
| toDate | YYYY-MM-DD | 2024-12-31 | ISO 8601 date format. Query includes up to 23:59:59 on this date |
| R-Auth | JWT (HS512) | eyJhbGciOiJlUzUxMiJ9... | Passed as request header |
Responses
200 - Successful Response
Type: List<MLRRecord>
{
{
"id": "3fa85164-5717-4562-b3fc-...",
"companyId": "0af615ef-3789-4475-b109-...",
"documentId": "cb6cde62-7355-478c-8e7b-...",
"invoiceId": "5a6b5466-a63b-4802-ad11-...",
"counterpartParticipantId": "iso6523-actorid-upis::0208:...",
"responseType": "ACCEPTANCE",
"receivedTime": "2024-06-01T14:30:00",
"responseLines": []
}
"responseType": "REJECTION",
"receivedTime": "2024-06-01T14:35:00",
"responseLines": [
{
"id": "9c1b2d3e-4f5a-6b70-8d9e-...",
"errorField": "cbc:TaxAmount",
"responseCode": "REJECTION",
"description": "Tax amount mismatch with invoice line totals.",
"statusReasonCode": "BUSINESS_RULE_VIOLATION_FATAL"
}
]
}
Response Fields
Root Object (MLRRecord)
| Field Name | Type | Description |
|---|---|---|
| id | string (UUID) | Unique identifier of the MLR record |
| companyId | string (UUID) | Identifier of the associated company |
| documentId | string (UUID) | Identifier of the associated PEPPOL document |
| invoiceId | string (UUID) | Identifier of the associated invoice |
| counterpartParticipantId | string | PEPPOL participant ID of the counterpart |
| responseType | enum (ResponseType) | Overall response type of the MLR. See enum table below. |
| receivedTime | string (ISO 8601 DateTime) | Date and time the MLR was received by the system |
| responseLines | array (MLRLine) | Line-level details of the MLR. Contains error details for rejected documents. |
Response Type
| Value | Description |
|---|---|
| ACCEPTANCE | Document accepted. Both business rules and technical validation passed. |
| ACKNOWLEDGING | Document received and queued for processing; final decision not yet communicated. |
| REJECTION | Document rejected. Error details are provided in the responseLines array. |
StatusReasonCode
| Value | Description |
|---|---|
| BUSINESS_RULE_VIOLATION_FATAL | Fatal business rule violation. Document is definitively rejected. |
| BUSINESS_RULE_VIOLATION_WARNING | Business rule warning. Document may be accepted, but attention is required. |
| SYNTAX_VIOLATION | XML syntax error. Document does not conform to the expected schema format. |
400 - Bad Request
This error is returned when the companyId parameter is not in a valid UUID format (e.g., a non-parseable string is provided). If companyId cannot be parsed into a valid UUID format, an IllegalArgumentException is thrown, and a 400 status is returned.
{
"errorMessage": "Invalid UUID string: abc123",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-correlation-id",
"status": "400",
"timestamp": "2024-06-01T14:35:00",
"path": "/peppol/search-mlr",
"data": null,
"details": null,
"validationErrors": null
}
401 - Unauthorized
This error occurs when the JWT token is either invalid, missing, or the user associated with the token is not linked to the specified companyId. If no association is found between the user in the token and the given companyId, an AuthorizationServiceException is thrown with the AUTHORIZATION_FAILED error type.
{
"errorMessage": "Authorization failed for this company.",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"errorId": "b2c3d4e5-correlation-id",
"status": "401",
"timestamp": "2024-06-01T14:36:00",
"path": "/peppol/search-mlr",
"data": null,
"details": null,
"validationErrors": null
}
498 - Token Expired
This error indicates that the JWT token's validity period has expired. It is a non-RFC-standard HTTP status code used specifically in this project. Even if the token signature is valid, this response is returned when the token has expired. Re-authentication is required to obtain a new token.
{
"errorMessage": "Your session has expired. Please login again.",
"errorType": "TOKEN_EXPIRED",
"errorTitle": "UNAUTHORIZED",
"errorId": null,
"status": "498",
"timestamp": "2024-06-01T14:37:00",
"path": "/peppol/search-mlr",
"data": null,
"details": null,
"validationErrors": null
}
500 - Internal Server Error
When returned: For unhandled exceptions such as database connection failures or unexpected system errors.
{
"errorMessage": "An unexpected error occurred.",
"errorType": "INTERNAL_SERVER_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "c3d4e5f6-correlation-id",
"status": "500",
"timestamp": "2024-06-01T14:38:00",
"path": "/peppol/search-mlr",
"data": null,
"details": null,
"validationErrors": null
}
28. Peppol - Send MLR POST
This endpoint is used to send a Message Level Response (MLR) for an invoice transmitted or received over the PEPPOL network.
In the PEPPOL standard, after an invoice is processed, the receiving party sends an MLR message back to the sender to indicate whether the invoice was accepted, acknowledged, or rejected. This endpoint handles the entire flow in a single operation: creating the MLR record, persisting it to the database, and forwarding it to the counterparty via the PEPPOL access point.
Endpoint Information
| Property | Value |
|---|---|
| URL | /peppol/send-mlr |
| Method | POST |
| Authentication | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/peppol/send-mlr' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {YOUR_JWT_TOKEN}' \
--data '{
"invoiceId": "<INVOICE_UUID>",
"responseCode": "REJECTION",
"errorLines": [
{
"errorField": "TaxAmount",
"responseCode": "REJECTION",
"description": "Tax amount calculation error",
"statusReasonCode": "BUSINESS_RULE_VIOLATION_FATAL"
}
]
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| invoiceId | string (UUID) | Yes | Unique identifier of the invoice for which the MLR is being sent |
| responseCode | MessageLevelResponseType | Yes | Overall response code for the invoice |
| errorLines | array<ErrorLine> | No | List of error details identified in the invoice |
Responses
200 - Successful Response
HTTP/1.1 200 OK
Content-Type: text/plain
OK
400 - Bad Request
Occurs when the prepared MLR packet is rejected by the external PEPPOL access point service. After the MLR packet is assembled and sent to the access point via HTTP POST, this error is returned if the access point rejects it (e.g., due to an invalid endpoint format or unreachable recipient identifier). The message field provides the specific rejection detail.
{
"timestamp": "2026-03-04T10:15:30.123Z",
"status": 400,
"error": "API_ERROR",
"message": "Failed to send MLR: Invalid participant identifier format",
"path": "/peppol/send-mlr"
}
401 - Unauthorized
Occurs when the R-Auth header is missing, invalid, or the JWT token has expired. If JWT token validation fails, an AuthorizationServiceException is thrown. The user must ensure the token is valid and has not expired.
{
"timestamp": "2026-03-04T10:15:30.123Z",
"status": 401,
"error": "NOT_AUTHORITY",
"message": "Unauthorized access",
"path": "/peppol/send-mlr"
}
404 - Not Found
Occurs when no invoice record matching the provided invoiceId exists in the database. Before creating the MLR, the service queries the invoice record using the invoiceId. If no record is found, a NotFoundException is thrown, resulting in a 404 response. The user should ensure the provided UUID is valid and corresponds to an existing invoice.
{
"timestamp": "2026-03-04T10:15:30.123Z",
"status": 404,
"error": "NOT_FOUND_INVOICE",
"message": "Invoice not found with id: 5a6b5466-a63b-4802-ad11-...",
"path": "/peppol/send-mlr"
}
422 - Unprocessable Entity
Occurs when the request is syntactically valid but violates a business logic rule. Even if the invoice exists, if it does not meet specific state conditions (e.g., attempting to send a second MLR for an already finalized invoice), a GeneralException is thrown, resulting in a 422 response.
{
"timestamp": "2026-03-04T10:15:30.123Z",
"status": 422,
"error": "GENERAL_ERROR",
"message": "Invoice is not in a valid state to receive MLR",
"path": "/peppol/send-mlr"
}
500 - Internal Server Error
When returned: An unexpected error occurs while forwarding the MLR to the access point (network error, timeout, etc.).
{
"timestamp": "2026-03-04T10:15:30.123Z",
"status": 500,
"error": "API_ERROR",
"message": "Failed to send MLR: Connection timeout to access point",
"path": "/peppol/send-mlr"
}
Details: If the HTTP request to the access point fails, the exception is wrapped as an ApiError. The MLR may have been written to the database but was not delivered to the counterparty. It is safe to retry the operation.
500 - Internal Server Error — Database Write Failure
When returned: An error occurs while persisting the MLR record to the database.
{
"timestamp": "2026-03-04T10:15:30.123Z",
"status": 500,
"error": "RUNTIME_ERROR",
"message": "Failed to save MLR response",
"path": "/peppol/send-mlr"
}
Details: When a DataAccessException is caught during the database write, it is wrapped as a RuntimeException. In this case the MLR has neither been saved to the database nor delivered to the access point.
29. Get Certificate QR POST
Purpose of Use: This endpoint generates a digitally signed certificate verification QR code compliant with the Polish KSeF standard. The invoice hash and taxpayer identity in the request are signed using the company's active certificate. The response provides two outputs: a digitally signed verification URL and a base64-encoded PNG QR code image labeled "CERTYFIKAT". The system automatically selects the certificate based on companyId and the authenticated user. Certificate priority order: OFFLINE → COMPANY → INDIVIDUAL. The generated QR code is intended for physical invoice printouts to verify authenticity via the signed URL.
Endpoint Information
| Property | Value |
|---|---|
| URL | /qrcode/PL/certificate |
| Method | POST |
| Authentication | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/qrcode/PL/certificate?companyId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'r-auth: <jwt_token>' \
--data '{
"contextIdentifierType": "Nip",
"contextIdentifierValue": "1234567890",
"invoiceHash": "W5jW+IcwmCN75xbM84oKKrreniY8tj4u9ya/j110038-"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| contextIdentifierType | string (enum) | Yes | The type of context identifier. See enum table below. |
| contextIdentifierValue | string | Yes | The value corresponding to contextIdentifierType (e.g. NIP number). Cannot be blank. |
| invoiceHash | string (Base64) | Yes | SHA-256 hash of the invoice to be verified, Base64-encoded. Cannot be blank. |
Query Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | string (UUID v4) | Yes | Unique identifier of the company whose certificate will be used. |
contextIdentifierType Values
| Enum Value | JSON Representation | Description |
|---|---|---|
| NIP | "Nip" | Polish Tax Identification Number (NIP). Most common use case. |
| INTERNAL_ID | "InternalId" | Internal system identifier. |
| NIP_VAT_UE | "NipVatUe" | EU VAT number (used for cross-border transactions). |
Responses
200 - Succesful Response
{
"url": "https://verify.example.com/cert?sig=eyJhbG...&hash=W5jW..",
"qrCode": "VBORw0KGgoAAAANSUhEUgAA.."
}
400 - Bad Request
Scenario: A value outside the defined enum is sent in the contextIdentifierType field. contextIdentifierType only accepts "Nip", "InternalId", or "NipVatUe".
{
"status": 400,
"error": "Bad Request",
"message": "Unexpected value 'InvalidType'"
}
400 - Bad Request — Missing or blank required field
Scenario: One of invoiceHash, contextIdentifierType, or contextIdentifierValue is missing or blank.
{
"status": 400,
"error": "Bad Request",
"errors": [
{
"field": "invoiceHash",
"message": "must not be blank"
}
]
}
400 - Bad Request — No active certificate found
Scenario: No active, valid certificate exists for the given companyId (search order: OFFLINE → COMPANY → INDIVIDUAL).
{
"status": 400,
"error": "Bad Request",
"message": "No active certificate found for company: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
400 - Bad Request — Certificate has no NIP number
Scenario: The certificate record found in the database does not have a nipNumber field set.
{
"status": 400,
"error": "Bad Request",
"message": "Certificate does not have a NIP number"
}
400 - Bad Request — Cannot determine certificate serial number
Scenario: The serial number cannot be read from the certificate (corrupted or incomplete certificate record).
{
"status": 400,
"error": "Bad Request",
"message": "Could not determine certificate serial number"
}
400 - Bad Request — Certificate has no private key
Scenario: The encrypted private key data associated with the certificate record is missing.
{
"status": 400,
"error": "Bad Request",
"message": "Certificate does not have a private key"
}
400 - Bad Request — QR code generation failure
Scenario: An unexpected error occurs during the signing or QR image generation process.
{
"status": 400,
"error": "Bad Request",
"message": "Failed to generate certificate QR code: <detail>"
}
401 - Unauthorized
Scenario: The r-auth header is missing, malformed, or the JWT has expired.
{
"status": 401,
"error": "Unauthorized",
"message": "JWT token is expired or invalid"
}
403 - Forbidden
Scenario: The token is valid but the authenticated user does not have permission to operate on the given companyId.
{
"status": 403,
"error": "Forbidden",
"message": "Access denied"
}
30. Get Invoice QR Offline POST
Purpose of Use: This endpoint generates a QR code for a Polish KSeF invoice that has not yet been submitted to KSeF. It operates in "offline mode." In this mode, a verification URL is constructed using: the SHA-256 hash of the invoice XML content, the invoice date, and the Polish Tax Identification Number (NIP). A QR code is generated in PNG format from this URL. An "OFFLINE" label is applied to the image to indicate that the invoice has not yet received a KSeF number. Verification can be performed using only the hash value.
Difference from online mode: The online endpoint is /qrcode/PL/invoice/online. The online endpoint is for invoices successfully submitted to KSeF. In online mode, the QR code label is the KSeF number. In offline mode, no KSeF number exists, and the label is fixed as "OFFLINE."
Endpoint Information
| Property | Value |
|---|---|
| URL | /qrcode/PL/invoice/offline |
| Method | POST |
| Authentication | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/qrcode/PL/invoice/offline' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'r-auth: {JWT_TOKEN}' \
--data '{
"invoiceHash": "{INVOICE_HASH_BASE64}",
"issueDate": "2026-02-27",
"nip": "{NIP}"
}'
Request Parameters
Path Parameter
| Parameter | Type | Required | Description |
|---|---|---|---|
| country | String | Yes | Country code. Fixed value for this endpoint: PL (Poland) |
Body Parameters
| Field | Type | Required | Format | Description |
|---|---|---|---|---|
| nip | String | Yes | 10-digit numeric string | Polish Tax Identification Number (Numer Identyfikacji Podatkowej). Must contain only digits – no dashes, letters, or spaces |
| issueDate | String | Yes | yyyy-MM-dd | Invoice issue date (ISO 8601). Null or incorrectly formatted values produce an error |
| invoiceHash | String | Yes | Base64 (SHA-256) | SHA-256 digest of the invoice XML content, Base64-encoded. Must be a valid Base64 string |
| ksefNumber | String | No | [NIP]-[YYYYMMDD]-[HEX]-[SUFFIX] | Optional in offline mode; ignored even if provided |
Parameter Value Reference
| Parameter | Accepted Values | Example Value | Constraints |
|---|---|---|---|
| nip | 10-digit numeric string | 1234567890 | Must not be blank; digits only |
| issueDate | ISO 8601 date format | 2026-02-27 | null not accepted; format must be yyyy-MM-dd |
| invoiceHash | Base64-encoded SHA-256 digest | W5jW+IcwmCN75xbM84oKK... | Must not be blank; must be valid Base64 |
| ksefNumber | [NIP]-[YYYYMMDD]-[HEX]-[SUFFIX] | 1234567890-20260227-BCFD80000000-E8 | Optional in offline mode; ignored if provided |
| r-auth | HS512-signed JWT token | eyJhbGciOiJUzUxMil9... | Expired or invalid tokens are rejected |
| country (path) | PL | PL | This endpoint is exclusively for Poland (PL) |
Responses
200 - Successful Response
{
"url": "https://ksef.mf.gov.pl/web/verify?nip=[NIP]&date=2026-02-27&hash=[INVOICE_HASH_BASE64]",
"qrCode": "VBORw0KGgoAAAANSUhEUgAAA..."
}
Note: The qrCode field is Base64-encoded PNG content and can be used directly in an HTML <img> tag with the format data:image/png;base64, [qrCode].
400 - Bad Request
Case 1 — nip missing or blank: The nip field is required but is missing or empty.
{
"errorMessage": "NIP is required",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-03-04T10:15:00",
"path": "/qrcode/PL/invoice/offline"
}
Case 2 — issueDate is null: The issueDate field is required but is null.
{
"errorMessage": "Issue date is required",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-03-04T10:15:00",
"path": "/qrcode/PL/invoice/offline"
}
Case 3 — invoiceHash missing or blank: The invoiceHash field is required but is missing or empty.
{
"errorMessage": "Invoice hash is required",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-03-04T10:15:00",
"path": "/qrcode/PL/invoice/offline"
}
Case 4 — issueDate invalid format (e.g. "27-02-2026" or "2026/02/27"): The issueDate field is provided in an invalid format, leading to a JSON parse error because it cannot be deserialized to java.time.LocalDate from a String.
{
"errorMessage": "JSON parse error: Cannot deserialize value of type 'java.time.LocalDate' from String",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-03-04T10:15:00",
"path": "/qrcode/PL/invoice/offline"
}
Validation for these 400 Bad Request cases is performed in the controller layer via validateInvoiceQrRequest(). The errorType is always API_ERROR for these cases.
401 - Unauthorized
Occurs when the r-auth header is missing, carries an invalidly signed JWT, or contains an expired token.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 401,
"timestamp": "2026-03-04T10:15:00",
"path": "/qrcode/PL/invoice/offline"
}
422 - Unprocessable Entity
Parameters provided in a request are technically valid but violate a business rule.
{
"errorMessage": "Business rule violation: ---",
"errorType": "GENERAL_ERROR",
"errorTitle": "UNPROCESSABLE_ENTITY",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 422,
"timestamp": "2026-03-04T10:15:00",
"path": "/qrcode/PL/invoice/offline"
}
500 - Internal Server Error
The KSeF SDK fails to generate a verification URL or an unexpected error occurs during QR image generation.
{
"errorMessage": "Failed to generate offline invoice QR code: <technical error detail>",
"errorType": "API_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 500,
"timestamp": "2026-03-04T10:15:00",
"path": "/qrcode/PL/invoice/offline"
}
31. Get Invoice QR Online POST
Purpose of Use: This endpoint generates a verification QR code for invoices that have been successfully submitted to KSeF (Krajowy System e-Faktur — Poland's National e-Invoice System) and have been assigned a KSeF reference number. KSeF is the mandatory electronic invoicing infrastructure managed by Poland's Ministry of Finance, and as of 2026, e-invoices are a legal requirement for all B2B and B2G transactions in Poland.
"Online mode" refers to the scenario where the invoice has been successfully submitted to KSeF and has a unique KSeF reference number. The endpoint performs three key actions: (1) It builds an official KSeF verification URL by combining the taxpayer NIP, issue date, SHA-256 invoice hash, and KSeF reference number. (2) It produces a QR code image (Base64 PNG) embedding that URL, with the KSeF reference number printed as a label on the image. (3) The returned QR code can be embedded in the invoice PDF, printed copy, or digital distribution channel, allowing the invoice recipient or a tax auditor to scan it with a mobile device and verify the original invoice on the KSeF portal.
Endpoint Information
| Property | Value |
|---|---|
| URL | /qrcode/PL/invoice/online |
| Method | POST |
| Authentication | R-Auth header (JWT token) |
Example Request
curl --location 'https://api-stage.docnova.ai/qrcode/PL/invoice/online' \
--header 'Content-Type: application/json' \
--header 'r-auth: <YOUR_JWT_TOKEN>' \
--data '{
"nip": "[[nip]]",
"issueDate": "[[issueDate]]",
"invoiceHash": "[[invoiceHash]]",
"ksefNumber": "[[ksefNumber]]"
}'
Request Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| nip | string | Yes | Polish taxpayer identification number (NIP – Numer Identyfikacji Podatkowej). 10-digit numeric value belonging to the invoice issuer. |
| issueDate | string | Yes | Invoice issue date. ISO 8601 date value in yyyy-MM-dd format. |
| invoiceHash | string | Yes | SHA-256 hash of the invoice XML content, Base64-encoded. Used in signing the KSeF verification link. |
| ksefNumber | string | Yes | Unique reference number assigned by the KSeF system upon successful invoice submission. Mandatory in online mode. |
Parameter Values and Constraints
| Field Name | Format | Valid Value Example | Constraints |
|---|---|---|---|
| nip | [0-9]10 | 0000000000 | 10 digits, numeric only; no hyphens or spaces |
| issueDate | yyyy-MM-dd | 2026-02-27 | ISO 8601 date format; must be a valid calendar date |
| invoiceHash | Base64 (SHA-256) | W5jW+IcwmCN7... | SHA-256 hash, standard Base64 encoding; 44 characters |
| ksefNumber | (NIP)-[YYYYMMDD]-(HEX_ID)-(SUFFIX) | 0000000000-20260227-BCFD80000000-E8 | Format assigned by KSeF system; 4 sections separated by hyphens |
| r-auth | JWT (HS512) | eyjhbGcOjUzUxMj9... | HS512-signed; not expired; passed in the r-auth header |
Responses
200 - Successful Response
{
"url": "https://qr-demo.ksef.mf.gov.pl/qr?nip=0000000000&date=2026-02-27&hash=W5/W%2BlcwmCN75xbM84oKKrreniY8tj4u%oya%2Fj110038%30&ksefNo=0000000000-20260227-...-EB",
"qrCode": "VBORw0KGgoAAAANSUhEUgAAASWAAAESCAYAAABS/Y5..."
}
400 - Bad Request
{
"errorMessage": "NIP is required",
"errorType": "API_ERROR",
"status": 400,
"errorId": "a1b2c364-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:15:00",
"path": "/qrcode/PL/invoice/online"
}
400 - Bad Request — Missing Issue Date
{
"errorMessage": "Issue date is required",
"errorType": "API_ERROR",
"status": 400,
"errorId": "a1b2c364-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:15:01",
"path": "/qrcode/PL/invoice/online"
}
400 - Bad Request — Missing Invoice Hash
{
"errorMessage": "invoice hash is required",
"errorType": "API_ERROR",
"status": 400,
"errorId": "a1b2c364-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:15:02",
"path": "/qrcode/PL/invoice/online"
}
400 - Bad Request — Missing KSeF Number
{
"errorMessage": "KSeF number is required for online mode",
"errorType": "API_ERROR",
"status": 400,
"errorId": "a1b2c364-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:15:03",
"path": "/qrcode/PL/invoice/online"
}
401 - Unauthorized
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"status": 401,
"errorId": "a1b2c364-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:15:04",
"path": "/qrcode/PL/invoice/online"
}
500 - Internal Server Error
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"status": 500,
"errorId": "a1b2c364-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:15:05",
"path": "/qrcode/PL/invoice/online"
}
500 - Internal Server Error — KSeF SDK Error
{
"errorMessage": "internal server error",
"errorType": "SERVER_ERROR",
"status": 500,
"errorId": "a1b2c364-e5f6-7890-abcd-...",
"timestamp": "2026-02-27T10:15:06",
"path": "/qrcode/PL/invoice/online"
}
35. Get all offline invoices GET
Purpose of Use: This endpoint retrieves all offline invoices registered in the Polish KSeF system for a given company. Invoices in all statuses — pending, submitted, and failed — are returned in a single query.
Results are ordered by creation time in descending order. Each record includes QR Code I (invoice verification), QR Code II (certificate verification), current status, and the KSeF reference number (if already submitted).
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/offline/all |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | Bearer Token (R-Auth Header) Required |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/PL/offline/all?companyId={{company_uuid}}' \
-H 'accept: */*' \
-H 'R-Auth: {{jwt_token}}'
Request Parameters
Query Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| companyId | string (UUID) | Yes | Unique identifier of the company whose offline invoices are to be listed (query parameter) |
Responses
200 - Successful Response
Returns all offline invoices registered for the company in the KSeF system, ordered by creation time descending. The ksefNumber field is null for invoices that have not yet been submitted.
Response body (Array<OfflineInvoiceResult>):
[
{
"queueId": "{{entity_uuid}}",
"invoiceId": "{{invoice_uuid}}",
"invoiceHash": "{{encoded_secret}}",
"qrCodeI": "https://api-stage.docnova.ai/verify/invoice?hash={{encoded_secret}}",
"qrCodeII": "https://api-stage.docnova.ai/verify/cert?nip=1234567890&serial=KSEF-CERT-001&sig={{encoded_secret}}",
"status": "PENDING",
"issueDate": "2026-03-01",
"createdTime": "2026-03-01T10:00:00",
"ksefNumber": null
},
{
"queueId": "{{entity_uuid}}",
"invoiceId": "{{invoice_uuid}}",
"invoiceHash": "{{encoded_secret}}",
"qrCodeI": "https://api-stage.docnova.ai/verify/invoice?hash={{encoded_secret}}",
"qrCodeII": "https://api-stage.docnova.ai/verify/cert?nip=1234567890&serial=KSEF-CERT-001&sig={{encoded_secret}}",
"status": "SUBMITTED",
"issueDate": "2026-02-15",
"createdTime": "2026-02-15T08:30:00",
"ksefNumber": "PL-KSEF-2026-0001234"
}
]
Response Fields
| Field | Type | Description |
|---|---|---|
| [].queueId | string (UUID) | Unique identifier of the offline queue entry |
| [].invoiceId | string (UUID) | Internal unique identifier of the invoice |
| [].invoiceHash | string | SHA-256 hash of the invoice content, Base64-encoded |
| [].qrCodeI | string | QR Code I — invoice verification URL |
| [].qrCodeII | string | QR Code II — certificate and signature verification URL |
| [].status | string (enum) | Current queue status: PENDING, SUBMITTED, or FAILED |
| [].issueDate | string (ISO 8601) | Invoice issue date in YYYY-MM-DD format |
| [].createdTime | string (ISO 8601) | Timestamp when the queue entry was created |
| [].ksefNumber | string | KSeF reference number assigned after successful submission; null for unsubmitted invoices |
Parameter Value Reference
| Value | Description |
|---|---|
| PENDING | Waiting to be submitted to KSeF when connectivity is available |
| SUBMITTED | Successfully submitted to KSeF and received a reference number |
| FAILED | Submission failed after all retry attempts were exhausted |
400 - Bad Request
Trigger: When the companyId query parameter is missing or not a valid UUID.
Response body:
{
"errorMessage": "Failed to process request",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-03-11T10:00:00",
"path": "/invoice/PL/offline/all"
}
Returns 400 Bad Request when the companyId query parameter is absent or cannot be parsed as a valid UUID.
401 - Unauthorized
Trigger: When an invalid or expired JWT token is used, or the user lacks the required authority for the company.
Response body:
{
"errorMessage": "Authorization failed!",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "{{correlation_id}}",
"timestamp": "2026-03-11T10:00:00",
"path": "/invoice/PL/offline/all"
}
Thrown as AuthorizationServiceException when the R-Auth header is missing, invalid, or expired, or when the user does not have ADMIN or POLAND_INVOICE authority for the given company.
500 - Internal Server Error
Trigger: When an unexpected server error occurs.
Response body:
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "{{correlation_id}}",
"timestamp": "2026-03-11T10:00:00",
"path": "/invoice/PL/offline/all"
}
Returns a 500 Internal Server Error when an unexpected server-side error occurs.
36. Get pending offline invoices GET
Purpose of Use: This endpoint retrieves the list of pending offline invoices in the queue for the specified company in the Polish KSeF system.
Returns invoices created in offline mode that have not yet been submitted to KSeF (with PENDING status). Each invoice includes QR codes, invoice summary, and queue status information. Access requires either ADMIN or POLAND_INVOICE authority.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/offline/pending |
| Method | GET |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | Required (R-Auth Header - JWT Token) |
Example Request
curl -X GET 'https://api-stage.docnova.ai/invoice/PL/offline/pending?companyId={{company_uuid}}' \
-H 'accept: */*' \
-H 'R-Auth: {{jwt_token}}'
Request Parameters
Query Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| companyId | string (UUID) | Yes | The unique identifier of the company whose pending offline invoices will be retrieved (query parameter) |
Responses
200 - Successful Response
Successful response. Returns a list of PENDING offline invoices for the company. The ksefNumber field is null for invoices not yet submitted to KSeF.
Response body (List<OfflineInvoiceResult>):
[
{
"queueId": "{{entity_uuid}}",
"invoiceId": "{{invoice_uuid}}",
"invoiceHash": "{{encoded_secret}}",
"qrCodeI": "https://api-stage.docnova.ai/verify/invoice?nip=1234567890&date=2026-01-15&hash={{encoded_secret}}",
"qrCodeII": "https://api-stage.docnova.ai/verify/cert?nip=1234567890&serial=CERT-001&hash={{encoded_secret}}&sig={{encoded_secret}}",
"status": "PENDING",
"issueDate": "2026-01-15",
"createdTime": "2026-01-15T10:30:00",
"ksefNumber": null
}
]
Response Fields
| Field | Type | Description |
|---|---|---|
| [].queueId | string (UUID) | Unique identifier of the offline invoice queue entry |
| [].invoiceId | string (UUID) | Internal invoice identifier in the system |
| [].invoiceHash | string | SHA-256 digest of the invoice XML content (Base64-encoded) |
| [].qrCodeI | string | QR Code I — Invoice verification URL (containing NIP, date, and hash) |
| [].qrCodeII | string | QR Code II — Certificate verification URL (certificate-signed URL) |
| [].status | string (enum) | Queue status of the invoice. Always PENDING for invoices returned by this endpoint |
| [].issueDate | string (ISO 8601) | Issue date of the invoice (YYYY-MM-DD) |
| [].createdTime | string (ISO 8601) | Timestamp when the queue entry was created |
| [].ksefNumber | string | KSeF reference number assigned by the KSeF system. Null until the invoice is successfully submitted |
#### Parameter Value Reference
| Value | Description |
|---|---|
| PENDING | Invoice is waiting to be submitted to KSeF when connectivity is available |
| SUBMITTED | Invoice has been successfully submitted to KSeF and received a reference number |
| FAILED | Invoice submission failed after all retry attempts were exhausted |
400 - Bad Request
Trigger: When the companyId query parameter is missing or provided in an invalid UUID format.
Response body:
{
"errorMessage": "Required UUID parameter 'companyId' is not present",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/PL/offline/pending"
}
Returns a 400 Bad Request error when the companyId parameter is missing or not in valid UUID format.
401 - Unauthorized
Trigger: When the user does not have ADMIN or POLAND_INVOICE authority for the specified company.
Response body:
{
"errorMessage": "Authorization failed",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/PL/offline/pending"
}
An AuthorizationServiceException is thrown and a 401 Unauthorized response is returned. Users without ADMIN or POLAND_INVOICE authority for the company will receive this error.
500 - Internal Server Error
Trigger: When an unexpected server error occurs.
Response body:
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/PL/offline/pending"
}
Returns a 500 Internal Server Error when an unexpected server-side error occurs.
37. Submit pending offline invoices POST
Purpose of Use: This endpoint submits all pending offline invoices that were previously created for the Polish KSeF system in bulk to KSeF when connectivity is restored.
It processes all invoices in PENDING status for the given company and returns separate lists of successfully submitted and failed invoices. The caller must hold ADMIN or POLAND_INVOICE authority for the specified company.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/PL/offline/submit |
| Method | POST |
| Content-Type | Not Required (no body) |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | Bearer Token (R-Auth Header) Required |
Example Request
curl -X POST 'https://api-stage.docnova.ai/invoice/PL/offline/submit?companyId={{company_uuid}}' \
-H 'R-Auth: {{jwt_token}}'
Request Parameters
Query Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| companyId | string (UUID) | Yes | Unique identifier of the company whose pending offline invoices will be submitted (sent as a query parameter) |
Responses
200 - Successful Response
Batch submission completed. Successfully submitted and failed invoices are reported in separate lists. If there are no pending invoices, all counters return as 0 and the lists are empty.
Response body (SubmissionResult):
{
"totalProcessed": 3,
"successCount": 2,
"failureCount": 1,
"submittedInvoices": [
{
"queueId": "{{entity_uuid}}",
"invoiceId": "{{invoice_uuid}}",
"ksefNumber": "PL2026/01/00001"
}
],
"failedInvoices": [
{
"queueId": "{{entity_uuid}}",
"invoiceId": "{{invoice_uuid}}",
"errorMessage": "KSeF connection timeout",
"retryCount": 2
}
]
}
Response Fields
Root Fields
| Field | Type | Description |
|---|---|---|
| totalProcessed | number | Total number of invoices processed in this batch |
| successCount | number | Number of invoices successfully submitted to KSeF |
| failureCount | number | Number of invoices that failed to submit |
Submitted Invoices (submittedInvoices[])
| Field | Type | Description |
|---|---|---|
| submittedInvoices[].queueId | string | Unique identifier of the offline queue record |
| submittedInvoices[].invoiceId | string | Unique identifier of the submitted invoice |
| submittedInvoices[].ksefNumber | string | Invoice reference number assigned by KSeF upon successful submission |
Failed Invoices (failedInvoices[])
| Field | Type | Description |
|---|---|---|
| failedInvoices[].queueId | string | Unique identifier of the offline queue record |
| failedInvoices[].invoiceId | string | Unique identifier of the failed invoice |
| failedInvoices[].errorMessage | string | Error message describing why the submission failed |
| failedInvoices[].retryCount | number | Number of submission attempts made for this invoice (maximum 3) |
400 - Bad Request
Trigger: When a KSeF session cannot be opened or KSeF returns an error during invoice transmission.
Response body:
{
"errorMessage": "Failed to submit invoices: KSeF authentication failed",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/PL/offline/submit"
}
An ApiError is thrown. Returns 400 Bad Request when KSeF authentication with the company certificate fails or the online session cannot be established.
401 - Unauthorized
Trigger: When the authenticated user does not have ADMIN or POLAND_INVOICE authority for the specified company.
Response body:
{
"errorMessage": "You are not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/PL/offline/submit"
}
An AuthorizationServiceException is thrown. Returns 401 Unauthorized when the JWT token is invalid or the user lacks the required authority for the requested company.
500 - Internal Server Error
Trigger: When an unexpected server error occurs.
Response body:
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/PL/offline/submit"
}
Returns a 500 Internal Server Error when an unexpected server-side error occurs.