Belgium E-Invoice Peppol
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
efactuurhub is a cloud-based e-invoice management portal developed by Melasoft, fully compliant with Belgium's digital transformation requirements and Peppol network standards. This API documentation is designed to ensure that your ERP systems integrate seamlessly with Belgian e-invoicing regulations.
Our portal abstracts complex XML structures and Peppol communication protocols (AS4), providing developers with an easy-to-use, secure, and scalable interface. By utilizing the efactuurhub API, you can submit invoices asynchronously, track real-time statuses, manage incoming invoices, and automatically process technical responses (MLR) from the recipient back into your ERP system.
Our compliance-oriented architecture guarantees the legal validity of every document, ensures data integrity, and establishes an end-to-end traceable audit trail.
2. Authentication POST
Purpose of Use: The POST /auth/login endpoint is used to authenticate to the Docnova API platform using an API Key. This endpoint allows users to log in to the system with a pre-defined API key. API key authentication is commonly used in machine-to-machine (M2M) integrations, automation scenarios, and external system integrations. Upon successful login, the user receives a JWT access token, refresh token, user details, and a list of authorized companies. This token is then used in subsequent API calls via the Authorization: Bearer JWT header.
Endpoint Information
| Property | Value |
|---|---|
| URL | /auth/login |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authorization | Not required (public endpoint) |
Example Request
curl --location 'https://api-stage.docnova.ai/auth/login' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--data '{
"apiKey": "YOUR_API_KEY"
}'
Request Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| apiKey | String | Required | Unique API key used for system authentication. It is a 32 character alphanumeric value generated through the Docnova panel. |
API Key Types
| Type | Description |
|---|---|
| USER | API key assigned to a specific user. Returns that user's information upon login. |
| COMPANY | API key assigned to a company. Returns the first active admin user's information of that company upon login. |
Responses
200 - Login Successful
When logging in with an API Key, an AccountInfo object is returned:
{
"id": "99913890-b7fd-4126-b3fd-...",
"superAdmin": false,
"companies": [
{
"id": "b8d79b88-44b1-4347-a3f9-...",
"name": "Example Company",
"taxNumber": "0401065997",
"website": null,
"address": "Sample Address 157 9000 City",
"city": "City",
"state": null,
"country": "BE",
"portalType": "BE",
"postalCode": "9000",
"phoneNumber": "+32 9 000 00 00",
"credit": 852,
"iconUrl": "stage/.../company_logo.jpg",
"email": "info@example.com",
"userCount": 16,
"vatNumber": "BE0401065997",
"faxNumber": null,
"mailLanguage": "EN",
"subscriptionType": "ENCRYPTED_VALUE",
"cif": null,
"sftp": false,
"isSubCompany": false,
"participants": [
{
"id": "4fcb57ae-09d8-4068-ba3e-...",
"fullParticipantId": "iso6523-actorid-upis::0208:...",
"scheme": "iso6523-actorid-upis::",
"icd": "0208",
"identifier": "0401065997",
"existInOurService": true,
"status": "APPROVED",
"deleteRequestExists": false
}
],
"featureAllowed": false,
"subCompanies": [],
"stripeObj": {
"stripeCustomerId": "cus_XXXXXXXXX",
"type": "FREE",
"renewalDate": "2026-02-26T13:00:00.141125",
"melaAiTokenCount": 47,
"googleAiTokenCount": null,
"docnovaCount": 0,
"renewal": true
},
"authorities": "ENCRYPTED_VALUE",
"compAuthTypes": "ENCRYPTED_VALUE",
"currencyCode": "EUR",
"remainingDocumentPercentage": 10.87,
"remainingPromotionDays": null,
"trialUsed": false,
"defaultParticipantId": {
"id": "4fcb57ae-09d8-4068-ba3e-...",
"fullParticipantId": "iso6523-actorid-upis::0208:0401065997",
"scheme": "iso6523-actorid-upis::",
"icd": "0208",
"identifier": "0401065997",
"existInOurService": true,
"status": "APPROVED",
"deleteRequestExists": false
}
}
],
"jwt": "eyJhbGciOiJIUzUxMiJ9...",
"expirationDate": "2026-02-18T08:16:23.516+00:00",
"user": {
"id": null,
"email": "user@example.com",
"firstName": null,
"lastName": null,
"phoneNumber": null,
"creationTime": null,
"photoUrl": null,
"mailLang": "EN",
"isSuperAdmin": null,
"lastLoginTime": null,
"authorities": null,
"adminAuthorities": "ENCRYPTED_VALUE",
"featureAllowed": false
},
"mfaEnabled": false,
"secretImageUri": null,
"lastCompanyId": "b8d79b88-44b1-4347-a3f9-...",
"requiresRecaptchaV2": null,
"message": null,
"active": true,
"isAppLogin": false,
"mfaType": null,
"refreshToken": "REFRESH_TOKEN_VALUE",
"refreshTokenExpiration": "2026-03-19T08:16:23.518+00:00"
}
Response Fields
| Field Name | Type | Description |
|---|---|---|
| id | String (UUID) | Unique identifier of the user |
| superAdmin | Boolean | Whether the user is a super admin |
| companies | List<AuthorizedCompany> | List of companies the user has access to |
| jwt | String | JWT access token. Used as Authorization: Bearer <jwt> in subsequent API calls |
| expirationDate | DateTime (ISO 8601) | JWT token expiration time |
| user | User | User detail information (id, email, first name, last name) |
| mfaEnabled | Boolean | Whether Multi Factor Authentication (MFA) is enabled |
| secretImageUri | String | null | Google Authenticator QR code URI if MFA is active |
| lastCompanyId | String (UUID) | ID of the last company accessed by the user |
| requiresRecaptchaV2 | Boolean | null | Whether reCAPTCHA v2 verification is required |
| message | String | null | Additional information message |
| active | Boolean | Active status of the user account |
| isAppLogin | Boolean | Whether login was performed via OAuth2 |
| mfaType | String | null | MFA type: GOOGLE or WHATSAPP |
| refreshToken | String | Refresh token. Used to obtain a new JWT when the current one expires |
| refreshTokenExpiration | DateTime (ISO 8601) | Refresh token expiration time |
User Object
| Field Name | Type | Description |
|---|---|---|
| id | String (UUID) | User ID |
| String | User email address | |
| firstName | String | User first name |
| lastName | String | User last name |
| phoneNumber | String | null | Phone number |
| creationTime | DateTime | Account creation time |
| photoUrl | String | null | Profile photo URL |
| mailLang | String | Email language preference |
| lastLoginTime | DateTime | Last login time |
400 - API Key Not Found
When the API key is not registered in the database:
{
"errorMessage": "API key not found!",
"errorType": "API key not found!",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-id-xxxx",
"timestamp": "2026-02-12T14:30:00",
"path": "/auth/login"
}
Description: The provided apiKey value does not match any registered API key in the system. Verify that the API key is entered correctly. Check your API key from the Docnova panel.
400 - API Key Out of Use
When the API key has been deactivated or deleted:
{
"errorMessage": "Provided api key is out of use! Please login with your credentials and try again.",
"errorType": "Provided api key is out of use! Please login with your credentials and try again.",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-id-xxxx",
"timestamp": "2026-02-12T14:30:00",
"path": "/auth/login"
}
Description: The API key exists in the system but is marked as active=false or deleted=true. This occurs when the key has been deactivated or deleted by an administrator. Create a new API key or reactivate the existing one.
400 - API Key Expired
When the API key's validity period has ended:
{
"errorMessage": "Provided api key has expired! Please login with your credentials and try again.",
"errorType": "Provided api key has expired! Please login with your credentials and try again.",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-id-xxxx",
"timestamp": "2026-02-12T14:30:00",
"path": "/auth/login"
}
Description: The API key's expireDate field points to a past date. API keys have a maximum validity of 1 year. You need to renew the expired key or create a new one.
400 - Invalid / Empty Request Body
When invalid JSON or an empty body is sent:
{
"errorMessage": "Required request body is missing",
"errorType": "HttpMessageNotReadableException",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-id-xxxx",
"timestamp": "2026-02-12T14:30:00",
"path": "/auth/login"
}
Description: The request body is not in valid JSON format or was sent empty. Ensure that the Content-Type: application/json header is set correctly and that the body contains valid JSON.
401 - Invalid Login Attempt
When the API key is valid but the returned response is of an unexpected type:
{
"errorMessage": "Invalid login attempt!",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "corr-id-xxxx",
"timestamp": "2026-02-12T14:30:00",
"path": "/auth/login"
}
Description: The API key was validated but the login process could not be completed. This can occur when a COMPANY type API key's associated company does not have any active admin users. Ensure that the relevant company has at least one active admin user.
3. Send Document Async POST
Purpose of Use: This endpoint is used for asynchronous processing of a Base64-encoded e-invoice or waybill document. The document is not processed immediately upon submission; it is placed into a Kafka queue and processed in the background by an independent consumer.
When the endpoint is called, the server immediately returns a trackingId. This trackingId can be used to query the current status of the document via the GET /document-status/{trackingId} endpoint.
Endpoint Information
| Info | Value |
|---|---|
| HTTP Method | POST |
| URL | /invoice/send-document-async |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authentication | JWT Token (Header: R-Auth) |
| Response Format | application/json |
Example Request
curl --location "https://api-stage.docnova.ai/invoice/send-document-async" \
--header "Content-Type: application/json" \
--header "Accept: */*" \
--header "R-Auth: <JWT_TOKEN>" \
--data "{
\"apiKey\": \"<API_KEY>\",
\"base64Document\": \"<BASE64_ENCODED_XML>\",
\"invoiceType\": \"PEPPOL_BIS\"
}"
Request Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| apiKey | String | Conditional | API key. Required if compId is not provided. Used to identify the company. |
| compId | String (UUID) | Conditional | Company identifier. Required if apiKey is not provided. |
| base64Document | String | Conditional | Base64 encoded XML document. Required if base64Pdf is not provided. |
| base64Pdf | String | Conditional | Base64 encoded PDF document. Required if base64Document is not provided. |
| invoiceType | DataType (Enum) | Conditional | Invoice type. Required if waybillType is not provided. |
| waybillType | WaybillDataType (Enum) | Conditional | Waybill type. Required if invoiceType is not provided. |
| invoiceSource | InvoiceSource (Enum) | No | Source of the invoice. Default: ERP |
| receiverEmails | List<String> | No | List of receiver email addresses |
| mailTemplateId | String | No | Email template identifier |
| businessType | BusinessModelType (Enum) | No | Business model type |
Parameter Values
invoiceType
| Value | Description |
|---|---|
| PEPPOL_BIS | Peppol BIS 3.0 standard |
| RO_EFACTURA | Romania e-Factura format |
| XRECHNUNG | Germany XRechnung standard |
| MY_INVOIS | Malaysia MyInvois format |
| MY_PINT | Malaysia PINT format |
| DK_OIOUBL | Denmark OIOUBL format |
| EG_INVOICE | Egypt invoice format |
| HR_INVOICE | Croatia invoice format |
| UAE_PINT | United Arab Emirates PINT format |
| ZUGFERD | ZUGFeRD structured invoice |
| FACTUR_X | France Factur-X format |
| XRECHNUNG_CII | XRechnung CII format |
| CII | UN/CEFACT CII format |
| CID | UN/CEFACT CID format |
| Unstructured PDF documents | |
| KZ_ESF_V2 | Kazakhstan ESF V2 format |
| KSEF | Poland KSeF format |
| KSEF_OFFLINE | Poland KSeF offline format |
waybillType
| Value | Description |
|---|---|
| RS_WAYBILL_DESPATCH | Serbia waybill (despatch) |
| RS_WAYBILL_RECEIPT | Serbia waybill (receipt) |
| RS_APPLICATION_RESPONSE | Serbia application response |
| RO_ETRANSPORT | Romania e-Transport |
invoiceSource
| Value | Description |
|---|---|
| ERP | ERP system (default) |
| PORTAL | Web portal |
| PORTAL_OCR | Portal via OCR |
| EMAIL_OCR | Email via OCR |
| PEPPOL | Peppol network |
| SFTP | SFTP integration |
| SERVICE | Service |
| HARVEST | Harvest integration |
| SHOPIFY | Shopify integration |
| AMAZON_SP | Amazon SP integration |
| EBAY | eBay integration |
| HUBSPOT | HubSpot integration |
| STRIPE | Stripe integration |
| LHDNM | LHDNM (Malaysia) |
| NEMHANDEL | Nemhandel (Denmark) |
| ANAF | ANAF (Romania) |
| LAZADA | Lazada integration |
| KSEF | KSeF (Poland) |
| RS_API | Serbia API |
| ETA | ETA (Egypt) |
| ERACUN | eRacun (Croatia) |
businessType
| Value | Description |
|---|---|
| B2B | Business to Business |
| B2C | Business to Consumer |
| B2G | Business to Government |
Responses
200 - Successful Response
{
"trackingId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": "PENDING",
"message": "Document processing request submitted successfully"
}
200 - OK - Processing Submission Failed (Internal Failure)
Scenario: Kafka message submission or database operation fails internally.
{
"trackingId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": "FAILED",
"message": "Failed to submit document processing request: <error detail>"
}
Description: The document was accepted but could not be submitted to the async processing queue. If a trackingId is returned, it cannot be used for subsequent status queries as processing never started. Retry the request.
Response Fields
| Field Name | Type | Description |
|---|---|---|
| trackingId | UUID | Unique identifier for tracking the document processing |
| status | DocumentProcessStatus (Enum) | Current processing status of the document |
| message | String | Descriptive message about the operation |
Status Values
| Value | Description |
|---|---|
| PENDING | Document accepted, awaiting processing |
| PROCESSING | Document is being processed |
| COMPLETED | Processing completed successfully |
| FAILED | Processing failed |
| SENDING_FAILED | Sending to external system failed |
| PERMANENT_FAILED | Permanent failure (max retry attempts reached) |
400 - Bad Request
Scenario: Neither apiKey nor compId is provided in the request.
{
"errorMessage": "Document process required fields: apiKey or companyId",
"errorType": "DOCUMENT_PROCESS_REQUIRED_FIELDS",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-abc-123",
"timestamp": "2026-02-12T10:30:00",
"path": "/invoice/send-document-async"
}
Description: At least one field (apiKey or compId) must be provided to identify the company. The API uses this field to determine which company the document belongs to.
400 - Bad Request - Missing Document Type
Scenario: Neither invoiceType nor waybillType is provided in the request.
{
"errorMessage": "Document process required fields: invoiceType or waybillType",
"errorType": "DOCUMENT_PROCESS_REQUIRED_FIELDS",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-abc-123",
"timestamp": "2026-02-12T10:30:00",
"path": "/invoice/send-document-async"
}
Description: At least one of invoiceType (for invoices) or waybillType (for waybills) must be provided to determine the document type. The system uses this field to select the appropriate processing strategy.
400 - Bad Request - Missing Document Content
Scenario: Neither base64Document nor base64Pdf is provided in the request.
{
"errorMessage": "Document process required fields: base64Document or base64Pdf",
"errorType": "DOCUMENT_PROCESS_REQUIRED_FIELDS",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-abc-123",
"timestamp": "2026-02-12T10:30:00",
"path": "/invoice/send-document-async"
}
Description: Document content must be provided as Base64-encoded data. Use base64Document for XML documents and base64Pdf for PDF documents.
400 - Bad Request - Invalid API Key
Scenario: The provided apiKey is not found in the system or apiKey and compId are missing.
{
"errorMessage": "At least one of apiKey or companyId fields must be filled.",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-abc-123",
"timestamp": "2026-02-12T10:30:00",
"path": "/invoice/send-document-async"
}
Description: The provided apiKey value is not registered in the database. Use a valid API key. Alternatively, the company identifier can be specified directly using the compId field.
401 - Unauthorized
Scenario: JWT token is invalid or expired.
{
"errorMessage": "Authentication is required. Please complete the authentication process.",
"errorType": "AUTHENTICATION_REQUIRED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "corr-abc-123",
"timestamp": "2026-02-12T10:30:00",
"path": "/invoice/send-document-async"
}
Description: The JWT token sent in the R-Auth header is invalid, expired, or was not provided. Retry with a valid JWT token.
401 - Unauthorized - Company Authorization Error
Scenario: The user in the JWT token is not associated with the specified company.
{
"errorMessage": "User is not authorized for this operation",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "corr-abc-123",
"timestamp": "2026-02-12T10:30:00",
"path": "/invoice/send-document-async"
}
Description: The authenticated user is not authorized for the company identified by apiKey or compId. Verify that the user is assigned to the relevant company.
498 - Token Expired
Returned when the JWT token has expired (custom HTTP status code).
{
"errorMessage": "Your session has expired. Please login again.",
"errorType": "TOKEN_EXPIRED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-02-12T14:30:00"
}
Description: The JWT token's exp (expiration) claim has passed. The user needs to refresh their session to obtain a new token.
500 - Internal Server Error
Scenario: An unexpected server error occurs.
{
"errorMessage": "An unexpected error occurred",
"errorType": "INTERNAL_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "corr-abc-123",
"timestamp": "2026-02-12T10:30:00",
"path": "/invoice/send-document-async"
}
Description: An unexpected error occurred on the server side. Use the errorId value to contact the support team for investigating the root cause.
4. Send Document Async JSON POST
Purpose of Use: This endpoint allows invoice data compliant with UBL 2.1 / PEPPOL BIS standards to be submitted asynchronously as a JSON object (ublDto). No Base64-encoded file upload is required; all invoice details are provided directly in a structured JSON format.
When the request is accepted, the document is placed in the processing queue and a trackingId is returned. The processing status can be queried at any time using this ID via the GET /invoice/document-status/{trackingId} endpoint.
Endpoint Information
| Info | Value |
|---|---|
| HTTP Method | POST |
| URL | /invoice/send-document-async-json |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authentication | Bearer Token (Header: R-Auth) |
| Response Format | application/json |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async-json' \
--header 'r-auth: YOUR_R_AUTH_BEARER_TOKEN' \
--header 'Content-Type: application/json' \
--data-raw '{
"apiKey": "YOUR_DOCNOVA_API_KEY",
"ublDto": {
"Type": "PEPPOL_BIS",
"IsPeppolParticipant": true,
"ProfileType": "EN16931",
"CustomizationID": {
"Value": "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0"
},
"ProfileID": {
"Value": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
},
"ID": {
"Value": "INV-DEMO-2026-001"
},
"IssueDate": {
"Value": "2026-04-22"
},
"DueDate": {
"Value": "2026-04-22"
},
"InvoiceTypeCode": {
"Value": "380"
},
"Note": [
{
"Value": "NA"
}
],
"DocumentCurrencyCode": {
"Value": "EUR"
},
"BuyerReference": {
"Value": "na"
},
"OrderReference": {
"ID": {
"Value": ""
},
"SalesOrderID": {
"Value": "NA"
}
},
"AccountingSupplierParty": {
"Party": {
"EndpointID": {
"Value": "0123456789",
"schemeID": "0208"
},
"PartyIdentification": [
{
"ID": {
"schemeID": "0208",
"Value": "0123456789"
}
}
],
"PartyName": [
{
"Name": {
"Value": "Demo Supplier NV"
}
}
],
"PostalAddress": {
"StreetName": {
"Value": "Rue du Commerce 10, bus 2,1000 Bruxelles, BELGIUM"
},
"CityName": {
"Value": "Brussels"
},
"PostalZone": {
"Value": 2000
},
"AddressLine": [
{
"Line": {
"Value": "Rue du Commerce 10, bus 2,1000 Bruxelles, BELGIUM"
}
}
],
"Country": {
"IdentificationCode": {
"Value": "BE"
}
}
},
"PartyTaxScheme": [
{
"CompanyID": {
"schemeID": "VAT",
"Value": "BE0123456789"
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
],
"PartyLegalEntity": [
{
"RegistrationName": {
"Value": "Demo Supplier NV"
},
"CompanyID": {
"Value": "0123456789",
"schemeID": "0208"
}
}
],
"Contact": {
"Name": {
"Value": "Demo Contact"
},
"Telephone": {
"Value": "+32 2 555 01 23"
},
"ElectronicMail": {
"Value": "billing@demo-supplier.example"
}
}
}
},
"AccountingCustomerParty": {
"Party": {
"EndpointID": {
"Value": "0987654321",
"schemeID": "0208"
},
"PartyIdentification": [
{
"ID": {
"schemeID": "0208",
"Value": "0987654321"
}
}
],
"PartyName": [
{
"Name": {
"Value": "Demo Customer BVBA"
}
}
],
"PostalAddress": {
"StreetName": {
"Value": "Avenue des Tests 25,3000 Leuven, BELGIUM"
},
"CityName": {
"Value": ""
},
"PostalZone": {
"Value": "2000"
},
"AddressLine": [
{
"Line": {
"Value": "Avenue des Tests 25,3000 Leuven, BELGIUM"
}
}
],
"Country": {
"IdentificationCode": {
"Value": "BE"
}
}
},
"PartyTaxScheme": [
{
"CompanyID": {
"schemeID": "VAT",
"Value": "BE0987654321"
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
],
"PartyLegalEntity": [
{
"RegistrationName": {
"Value": "Demo Customer BVBA"
},
"CompanyID": {
"Value": "0987654321",
"schemeID": "0208"
}
}
],
"Contact": {
"Name": {
"Value": ""
},
"Telephone": {
"Value": ""
},
"ElectronicMail": {
"Value": ""
}
}
}
},
"Delivery": [
{
"ActualDeliveryDate": {
"Value": "2026-04-22"
},
"DeliveryLocation": {
"Address": {
"StreetName": {
"Value": "Avenue des Tests 25,3000 Leuven, BELGIUM"
},
"CityName": {
"Value": ""
},
"PostalZone": {
"Value": "2000"
},
"AddressLine": [
{
"Line": {
"Value": "Avenue des Tests 25,3000 Leuven, BELGIUM"
}
}
],
"Country": {
"IdentificationCode": {
"Value": "BE"
}
}
}
},
"DeliveryParty": {
"PartyName": [
{
"Name": {
"Value": "Demo Customer BVBA"
}
}
]
}
}
],
"PaymentMeans": [
{
"PaymentMeansCode": {
"name": "SEPA credit transfer",
"Value": "58"
},
"PayeeFinancialAccount": {
"ID": {
"Value": "BE68 5390 0754 7034"
},
"Name": {
"Value": "Demo Supplier NV"
}
}
}
],
"PaymentTerms": [
{
"Note": [
{
"Value": "NA"
}
]
}
],
"TaxTotal": [
{
"TaxAmount": {
"currencyID": "EUR",
"Value": 0.00
},
"TaxSubtotal": [
{
"TaxableAmount": {
"currencyID": "EUR",
"Value": 3910.00
},
"TaxAmount": {
"currencyID": "EUR",
"Value": 0.00
},
"TaxCategory": {
"ID": {
"Value": "Z"
},
"Percent": {
"Value": 0.00
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
}
]
}
],
"LegalMonetaryTotal": {
"LineExtensionAmount": {
"currencyID": "EUR",
"Value": 3910.00
},
"TaxExclusiveAmount": {
"currencyID": "EUR",
"Value": 3910.00
},
"TaxInclusiveAmount": {
"currencyID": "EUR",
"Value": 3910.00
},
"AllowanceTotalAmount": {
"currencyID": "EUR",
"Value": 0
},
"ChargeTotalAmount": {
"currencyID": "EUR",
"Value": 0
},
"PrepaidAmount": {
"currencyID": "EUR",
"Value": 0
},
"PayableAmount": {
"currencyID": "EUR",
"Value": 3910.00
}
},
"InvoiceLine": [
{
"ID": {
"Value": "1"
},
"InvoicedQuantity": {
"unitCode": "E53",
"Value": 1.000
},
"LineExtensionAmount": {
"currencyID": "EUR",
"Value": 3650.00
},
"DocumentReference": [
{
"ID": {
"schemeID": "",
"Value": "1"
},
"DocumentTypeCode": {
"Value": "130"
}
}
],
"Item": {
"Name": {
"Value": "Ocean Freight"
},
"SellersItemIdentification": {
"ID": {
"Value": "01"
}
},
"ClassifiedTaxCategory": [
{
"ID": {
"Value": "Z"
},
"Percent": {
"Value": 0.00
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
]
},
"Price": {
"PriceAmount": {
"currencyID": "EUR",
"Value": 3650.00
},
"BaseQuantity": {
"Value": 1
}
}
},
{
"ID": {
"Value": "2"
},
"InvoicedQuantity": {
"unitCode": "E53",
"Value": 1.000
},
"LineExtensionAmount": {
"currencyID": "EUR",
"Value": 260.00
},
"DocumentReference": [
{
"ID": {
"schemeID": "",
"Value": "2"
},
"DocumentTypeCode": {
"Value": "130"
}
}
],
"Item": {
"Name": {
"Value": "Others"
},
"SellersItemIdentification": {
"ID": {
"Value": "01"
}
},
"ClassifiedTaxCategory": [
{
"ID": {
"Value": "Z"
},
"Percent": {
"Value": 0.00
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
]
},
"Price": {
"PriceAmount": {
"currencyID": "EUR",
"Value": 260.00
},
"BaseQuantity": {
"Value": 1
}
}
}
]
}
}
'
Request Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| apiKey | String | Conditional | API key used to identify the company. Required if ublDto.CompanyId is not provided. |
| ublDto | Object (UBLDto) | Required | UBL 2.1 compliant invoice data structure containing all invoice details. |
| ublDto.Type | String (enum) | No | Document format type (e.g. PEPPOL_BIS, XRECHNUNG, ZUGFERD). See Parameter Values Reference. |
| ublDto.IsPeppolParticipant | Boolean | No | If true, the document is routed via Peppol when the recipient is on the network. |
| ublDto.CompanyId | String (UUID) | Conditional | UUID of the sending company. Required if apiKey is not provided. |
| ublDto.ProfileType | String (enum) | No | ZUGFeRD / Factur-X profile type. Default: EN16931. |
| ublDto.CustomizationID.Value | String | No | Customization ID (URN) for PEPPOL / EN16931 compliance. |
| ublDto.ID.Value | String | No | Invoice number / unique document identifier. |
| ublDto.IssueDate.Value | String (ISO 8601) | No | Invoice issue date (YYYY-MM-DD). |
| ublDto.DueDate.Value | String (ISO 8601) | No | Due date (YYYY-MM-DD). |
| ublDto.InvoiceTypeCode.Value | String | No | UN/CEFACT code (e.g. 380 = commercial invoice, 381 = credit note). |
| ublDto.Note[].Value | String | No | Free-text note on the invoice. |
| ublDto.DocumentCurrencyCode.Value | String | No | Currency (ISO 4217), e.g. EUR. |
| ublDto.BuyerReference.Value | String | No | Buyer reference / Leitweg-ID. |
| ublDto.OrderReference.ID.Value | String | No | Purchase order number. |
| ublDto.OrderReference.SalesOrderID.Value | String | No | Sales order number. |
| ublDto.AccountingSupplierParty | Object | No | Supplier party (EndpointID, PartyName, address, tax, legal entity, contact). |
| ublDto.AccountingSupplierParty.Party.EndpointID.Value | String | No | Supplier Peppol endpoint ID value. |
| ublDto.AccountingSupplierParty.Party.EndpointID.schemeID | String | No | Scheme code (e.g. 9930, 0088). |
| ublDto.AccountingCustomerParty | Object | No | Customer party (same structure as supplier). |
| ublDto.Delivery[].ActualDeliveryDate.Value | String | No | Actual delivery date. |
| ublDto.Delivery[].DeliveryLocation.Address | Object | No | Delivery address (street, city, postal zone, country). |
| ublDto.PaymentMeans[].PaymentMeansCode.Value | String | No | Payment means code (e.g. 58 = SEPA credit transfer). |
| ublDto.PaymentMeans[].PayeeFinancialAccount.ID.Value | String | No | Payee IBAN. |
| ublDto.PaymentMeans[].PayeeFinancialAccount.Name.Value | String | No | Account holder name. |
| ublDto.PaymentTerms[].Note[].Value | String | No | Payment terms text. |
| ublDto.TaxTotal[].TaxAmount.Value | Number | No | Total tax amount. |
| ublDto.TaxTotal[].TaxAmount.currencyID | String | No | Currency for tax amount. |
| ublDto.TaxTotal[].TaxSubtotal[].TaxableAmount.Value | Number | No | Taxable base. |
| ublDto.TaxTotal[].TaxSubtotal[].TaxCategory.ID.Value | String | No | Tax category (e.g. S, Z, E, AE). |
| ublDto.TaxTotal[].TaxSubtotal[].TaxCategory.Percent.Value | Number | No | VAT rate (%). |
| ublDto.LegalMonetaryTotal.LineExtensionAmount.Value | Number | No | Sum of line net amounts. |
| ublDto.LegalMonetaryTotal.TaxExclusiveAmount.Value | Number | No | Total excl. VAT. |
| ublDto.LegalMonetaryTotal.TaxInclusiveAmount.Value | Number | No | Total incl. VAT. |
| ublDto.LegalMonetaryTotal.PayableAmount.Value | Number | No | Amount payable. |
| ublDto.InvoiceLine[].ID.Value | String | No | Line number. |
| ublDto.InvoiceLine[].InvoicedQuantity.Value | Number | No | Quantity. |
| ublDto.InvoiceLine[].InvoicedQuantity.unitCode | String | No | Unit (UN/ECE Rec. 20, e.g. MTQ, C62, KGM). |
| ublDto.InvoiceLine[].LineExtensionAmount.Value | Number | No | Line net amount. |
| ublDto.InvoiceLine[].Item.Name.Value | String | No | Item name. |
| ublDto.InvoiceLine[].Item.SellersItemIdentification.ID.Value | String | No | Seller item code. |
| ublDto.InvoiceLine[].Price.PriceAmount.Value | Number | No | Unit price. |
| ublDto.InvoiceLine[].Price.BaseQuantity.Value | Number | No | Base quantity for price (usually 1). |
| receiverEmails | Array<String> | No | Email recipients after processing. |
| mailTemplateId | String | No | Optional mail template id. |
| businessType | String (enum) | No | B2B, B2C, or B2G. |
Request notes
- At least one of apiKey or ublDto.CompanyId must be provided. Both cannot be omitted.
- When ublDto.CompanyId is omitted, the company is resolved from apiKey.
- For AccountingSupplierParty / AccountingCustomerParty, EndpointID.schemeID uses Peppol participant identifier schemes (e.g. 9930, 0088, 0184).
- InvoiceLine[].InvoicedQuantity.unitCode uses UN/ECE Recommendation 20 codes (e.g. MTQ, C62, KGM, LTR).
Parameter Values Reference
ublDto.Type (document format)
| Value | Description |
|---|---|
| PEPPOL_BIS | PEPPOL BIS Billing 3.0 (UBL-based) |
| XRECHNUNG | Germany XRechnung (UBL) |
| ZUGFERD | ZUGFeRD (PDF/A-3 + embedded XML) |
| FACTUR_X | France Factur-X |
| XRECHNUNG_CII | Germany XRechnung CII |
| CII | UN/CEFACT CII |
| CID | Cross Industry Document |
| MY_INVOIS | Malaysia MyInvois |
| MY_PINT | Malaysia PINT |
| DK_OIOUBL | Denmark OIOUBL |
| RO_EFACTURA | Romania e-Factura |
| UAE_PINT | UAE PINT |
| HR_INVOICE | Croatia |
| EG_INVOICE | Egypt |
| KSEF | Poland KSeF |
ublDto.ProfileType
| Value | Description |
|---|---|
| EN16931 | EN 16931 profile (default) |
| EXTENDED | Extended profile |
| BASIC | Basic profile |
businessType
| Value | Description |
|---|---|
| B2B | Business to Business |
| B2C | Business to Consumer |
| B2G | Business to Government |
Response status (immediate async status)
| Value | Description |
|---|---|
| PENDING | Queued, not yet started |
| PROCESSING | Actively processed |
| COMPLETED | Completed successfully |
| FAILED | Processing failed |
| SENDING_FAILED | Generated but Peppol/email delivery failed |
| PERMANENT_FAILED | Permanent failure, no retry |
Responses
200 - Success
Request accepted; the document is queued for asynchronous processing.
{
"trackingId": "{{entity_uuid}}",
"status": "PENDING",
"message": "Document process started successfully"
}
Response Fields
| Field Name | Type | Description |
|---|---|---|
| trackingId | String (UUID) | Use with GET /invoice/document-status/{trackingId}. |
| status | String (enum) | Initial status (typically PENDING). |
| message | String | Informational message. |
400 - Bad Request
Scenario: Both apiKey and ublDto.CompanyId are missing.
{
"errorMessage": "apiKey or companyId field is required",
"errorType": "DOCUMENT_PROCESS_REQUIRED_FIELDS",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/send-document-async-json"
}
400 - Bad Request
Scenario: apiKey does not match any registered company.
{
"errorMessage": "Api Key Didnt Match",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/send-document-async-json"
}
401 - Unauthorized
Scenario: JWT in R-Auth is invalid or expired, or the user is not authorized for the company.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/send-document-async-json"
}
500 - Internal Server Error
Scenario: Unexpected server error.
{
"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/send-document-async-json"
}
5. Get Document Status GET
Purpose of Use: This endpoint is used to query the processing status of documents (invoices, waybills, etc.) that have been submitted asynchronously. After submitting a document via endpoints such as /invoice/send-document-async or /invoice/send-document-async-json, the user receives a trackingId (UUID) and uses this endpoint to monitor the document's current processing stage whether it is pending, being processed, completed, or has failed.
The typical workflow is as follows: The user submits a document and immediately receives a trackingId. The user then polls this endpoint at regular intervals to track the document through its conversion, validation, signing, and delivery stages. When the document reaches a terminal status (COMPLETED, FAILED, PERMANENT_FAILED, SENDING_FAILED), the process is finished. On success, documentId, invoiceNumber, and country-specific additionalData are populated in the response; on failure, errorType and errors fields provide detailed error information.
Endpoint Information
GET /invoice/document-status/"{trackingId}"Example Request
curl --location 'https://api-stage.docnova.ai/invoice/document-status/"{trackingId}"' \
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
Request Parameters
Path Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| trackingId | UUID | Yes | Tracking identifier returned from async document submission. Example: 550e8400-e29b-41d4-a716-446655440000 |
Header Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| R-Auth | String (JWT) | Yes | JWT token for authentication. Signed with HS512 algorithm. Payload includes: userId, companyId, authorities, correlationId |
type Parameter Accepted Values
| Value | Group | Description |
|---|---|---|
| PEPPOL_BIS | UBL/Peppol | Peppol BIS Billing 3.0 format |
| XRECHNUNG | UBL/Peppol | Germany XRechnung UBL format |
| RO_EFACTURA | UBL/Peppol | Romania e-Invoice format |
| DK_OIOUBL | Country-Specific | Denmark OIOUBL format |
| EG_INVOICE | Country-Specific | Egypt e-Invoice format |
| HR_INVOICE | Country-Specific | Croatia e-Invoice format |
| UAE_PINT | Country-Specific | UAE PINT format |
| MY_INVOIS | Country-Specific | Malaysia MyInvois format |
| MY_PINT | Country-Specific | Malaysia PINT format |
| ZUGFERD | ZUGFeRD/CII | ZUGFeRD 2.x format (XML embedded in PDF) |
| FACTUR_X | ZUGFeRD/CII | Factur-X format (XML embedded in PDF) |
| XRECHNUNG_CII | ZUGFeRD/CII | XRechnung CII format |
| CII | ZUGFeRD/CII | UN/CEFACT CII format |
| CID | ZUGFeRD/CII | CID format |
| ZUGFeRD/CII | Unstructured invoice, processed with ZUGFeRD template | |
| KZ_ESF_V2 | Poland/Kazakhstan | KZ ESF v2 invoice format |
| KSEF | Poland | Poland KSeF format |
| KSEF_OFFLINE | Poland | Poland KSeF offline format |
country Parameter Example Values
| Value | Country | Currency |
|---|---|---|
| DE | Germany | EUR |
| FR | France | EUR |
| BE | Belgium | EUR |
| NL | Netherlands | EUR |
| AT | Austria | EUR |
| IT | Italy | EUR |
| PL | Poland | PLN |
| RO | Romania | RON |
| TR | Turkey | TRY |
| EG | Egypt | EGP |
| AE | UAE | AED |
| MY | Malaysia | MYR |
| DK | Denmark | DKK |
| HR | Croatia | EUR |
| KZ | Kazakhstan | KZT |
All country codes following the ISO 3166-1 Alpha-2 standard are supported.
Responses
200 - Successful Response
{
"trackingId": "5e3c7f09-6f5f-4597-b38b-...",
"companyId": "b8d79b88-44b1-4347-a3f9-...",
"direction": null,
"documentType": "PEPPOL_BIS",
"waybillType": null,
"source": "ERP",
"target": null,
"status": "FAILED",
"filename": null,
"invoiceNumber": null,
"documentId": null,
"sendingResult": null,
"errorType": "INVOICE_ALREADY_EXISTS",
"createdAt": "2026-02-12T08:47:00",
"statusUpdatedAt": "2026-02-12T08:47:19",
"completedAt": "2026-02-12T08:47:19",
"errors": [
"Invoice already exists!"
],
"additionalData": null
}
Response Fields (200 OK)
| Field Name | Type | Nullable | Description |
|---|---|---|---|
| trackingId | UUID | No | Process tracking identifier |
| companyId | UUID | No | Company identifier the document belongs to |
| direction | DocumentType | No | Document direction (INCOMING/OUTGOING) |
| documentType | DataType | Yes | Document format (see DataType Values table) |
| waybillType | WaybillDataType | Yes | Waybill type, only populated for waybill operations |
| source | InvoiceSource | Yes | Source the document originated from (ERP, PORTAL, PEPPOL, etc.) |
| target | InvoiceSource | Yes | Destination the document is being sent to |
| status | DocumentProcessStatus | No | Current processing status (see Status Values table) |
| filename | String | Yes | Original file name |
| invoiceNumber | String | Yes | Invoice number (assigned upon completion) |
| documentId | UUID | Yes | System-generated document identifier (assigned upon completion) |
| sendingResult | String | Yes | Peppol/target system delivery result |
| errorType | ErrorType | Yes | Error classification (only on failure) |
| createdAt | ISO 8601 DateTime | No | Process creation timestamp |
| statusUpdatedAt | ISO 8601 DateTime | Yes | Last status update timestamp |
| completedAt | ISO 8601 DateTime | Yes | Process completion timestamp (success or failure) |
| errors | Object | Yes | Error details. Can be List<ValidationError>, List<String>, or String |
| additionalData | Object | Yes | Country-specific metadata (KSeF reference no, eFactura submissionId, etc.) |
Enum Value Tables
DocumentProcessStatus
| Value | Description |
|---|---|
| PENDING | Initial state, processing has not yet started |
| PROCESSING | Currently being processed (conversion, validation, signing) |
| COMPLETED | Successfully completed |
| FAILED | Processing failed (may be retried) |
| SENDING_FAILED | Delivery to target system failed |
| PERMANENT_FAILED | Permanent failure, will not be retried |
DocumentType
| Value | Description |
|---|---|
| INCOMING | Incoming document |
| OUTGOING | Outgoing document |
DataType
| Value | Description |
|---|---|
| PEPPOL_BIS | Peppol BIS 3.0 format |
| RO_EFACTURA | Romania eFactura format |
| XRECHNUNG | Germany XRechnung (UBL) format |
| XRECHNUNG_CII | Germany XRechnung (CII) format |
| MY_INVOIS | Malaysia MyInvois format |
| MY_PINT | Malaysia PINT format |
| DK_OIOUBL | Denmark OIOUBL format |
| EG_INVOICE | Egypt e-Invoice format |
| HR_INVOICE | Croatia e-Invoice format |
| UAE_PINT | UAE PINT format |
| ZUGFERD | ZUGFeRD format |
| FACTUR_X | Factur-X format |
| CII | Cross-Industry Invoice |
| CID | CID format |
| PDF document | |
| KZ_ESF_V2 | Kazakhstan ESF v2 format |
| KSEF | Poland KSeF format |
| KSEF_OFFLINE | Poland KSeF offline format |
InvoiceSource
| Value | Description |
|---|---|
| PORTAL | Web portal |
| PORTAL_OCR | Document read via OCR through portal |
| Document received via email | |
| EMAIL_OCR | Document read via OCR through email |
| ERP | ERP integration |
| PEPPOL | Peppol network |
| LHDNM | Malaysia LHDNM |
| NEMHANDEL | Denmark Nemhandel |
| SERVICE | Service layer |
| HARVEST | Harvest integration |
| SHOPIFY | Shopify integration |
| AMAZON_SP | Amazon SP integration |
| EBAY | eBay integration |
| HUBSPOT | HubSpot integration |
| ANAF | Romania ANAF |
| LAZADA | Lazada integration |
| SFTP | SFTP transfer |
| KSEF | Poland KSeF |
| RS_API | Serbia API |
| ETA | Egypt ETA |
| ERACUN | eRacun |
| STRIPE | Stripe integration |
WaybillDataType
| Value | Description |
|---|---|
| RS_WAYBILL_DESPATCH | Serbia despatch waybill |
| RS_WAYBILL_RECEIPT | Serbia receipt waybill |
| RS_APPLICATION_RESPONSE | Serbia application response |
| RO_ETRANSPORT | Romania eTransport |
401 - Unauthorized
Returned when the token is missing or invalid.
{
"error": "Full authentication is required to access this resource"
}
Description: The R-Auth header is missing, the token format is invalid, or the token signature cannot be verified. Retry with a valid JWT token.
498 - Token Expired
Returned when the JWT token has expired (custom HTTP status code).
{
"errorMessage": "Your session has expired. Please login again.",
"errorType": "TOKEN_EXPIRED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-02-12T14:30:00"
}
Description: The JWT token's exp (expiration) claim has passed. The user needs to refresh their session to obtain a new token.
404 - Not Found
Returned when no document process matches the provided trackingId.
(body: null)
Description: An invalid or non-existent trackingId was provided. Ensure you are using the correct UUID returned from the async submission. This error originates from ErrorType.INVOICE_PROCESS_NOT_FOUND ("Tracking ID not found").
400 - Bad Request
Returned by the Spring framework when the trackingId path parameter is not a valid UUID format.
{
"timestamp": "2026-02-12T14:30:00.000+00:00",
"status": 400,
"error": "Bad Request",
"message": "Failed to convert value of type 'java.lang.String' to required type 'java.util.UUID'",
"path": "/invoice/document-status/invalid-uuid"
}
Description: The trackingId parameter must be in standard UUID format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
500 Internal Server Error
Returned when an unexpected error occurs during processing.
(body: null)
Description: An unexpected server-side error occurred. If the issue persists, contact the support team.
6. Search Document Process POST
Purpose of Use: This endpoint is used to search and filter records in the Document Processing Queue with paginated results. When an invoice or document is submitted for processing in the system (from sources such as email, ERP integration, portal upload, etc.), its processing lifecycle is tracked in the DocumentProcess table. Each document passes through status transitions such as PENDING -> PROCESSING -> COMPLETED or FAILED / SENDING_FAILED / PERMANENT_FAILED.
The endpoint requires JWT-based authentication and the user must have at least one of ADMIN, INCOMING_INVOICE_DISPLAY, or OUTGOING_INVOICE_DISPLAY authorities on the specified company.
Endpoint Information
| Property | Value |
|---|---|
| HTTP Method | POST |
| URL | /invoice/document-process/search |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authentication | JWT Token (R-Auth header) |
| Authorization | ADMIN, INCOMING_INVOICE_DISPLAY, or OUTGOING_INVOICE_DISPLAY |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/document-process/search?page=0&size=20&sort=createdAt,desc' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"companyId": "<COMPANY_UUID>",
"createdAt": {
"from": "2026-01-01",
"to": "2026-09-09"
},
"direction": "INCOMING",
"filename": "invoice_001.xml",
"source": "EMAIL",
"status": "PERMANENT_FAILED"
}'
Query Parameters (Pagination)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| page | Integer | No | 0 | Page number (0-indexed) |
| size | Integer | No | 20 | Records per page (max: 100) |
| sort | String | No | createdAt,desc | Sort field and direction. Format: field,asc |
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | UUID | Yes | Unique identifier of the company to search. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
| direction | String (Enum) | No | Document direction filter |
| source | String (Enum) | No | Document ingestion source filter |
| filename | String | No | Exact match filter by document filename |
| status | String (Enum) | No | Document processing status filter |
| createdAt | Object | No | Date range filter |
| createdAt.from | LocalDate | No | Start date (inclusive). Format: YYYY-MM-DD |
| createdAt.to | LocalDate | No | End date (inclusive, until 23:59:59 of the day). Format: YYYY-MM-DD |
Enum Values
direction — Document Direction
| Value | Description |
|---|---|
| INCOMING | Incoming documents (invoices, waybills received from suppliers) |
| OUTGOING | Outgoing documents (invoices, waybills sent to customers) |
source — Document Source
| Value | Description |
|---|---|
| PORTAL | Manual upload via web portal |
| PORTAL_OCR | Uploaded via portal with OCR scanning |
| Automatically received via email | |
| EMAIL_OCR | Received via email and processed with OCR |
| ERP | Received via ERP system integration |
| PEPPOL | Received/sent via Peppol network |
| SFTP | Transferred via SFTP server |
| KSEF | Received via Poland KSeF system |
| ANAF | Received via Romania ANAF/eFactura system |
| RS_API | Received via Serbia eFaktura API |
| LHDNM | Received via Malaysia LHDNM/MyInvois system |
| NEMHANDEL | Received via Denmark NemHandel network |
| ETA | Received via Egypt ETA system |
| ERACUN | Received via Indonesia eRacun system |
| SERVICE | Generated by internal service |
| HARVEST | Received via Harvest integration |
status — Processing Status
| Value | Description |
|---|---|
| PENDING | Document queued, processing has not started yet |
| PROCESSING | Document is actively being processed (conversion, validation, submission) |
| COMPLETED | Document successfully processed and completed |
| FAILED | Processing failed, eligible for automatic retry |
| SENDING_FAILED | Document prepared but failed during transmission to target system |
| PERMANENT_FAILED | Permanent failure, no retry will be attempted (validation error, format mismatch, etc.) |
Responses
200 - Successful Response
{
"content": [
{
"trackingId": "a1b2c3d4-e5f6-7890-abcd-...",
"companyId": "b8d79b88-44b1-4347-a3f9-...",
"direction": "INCOMING",
"documentType": "PEPPOL_BIS",
"waybillType": null,
"source": "EMAIL",
"target": "PORTAL",
"status": "PERMANENT_FAILED",
"filename": "invoice_001.xml",
"invoiceNumber": "INV-2026-001",
"documentId": "d4e5f6a7-b8c9-0123-4567-...",
"sendingResult": null,
"errorType": "VALIDATION_FAILED",
"createdAt": "2026-01-15T10:30:00",
"statusUpdatedAt": "2026-01-15T10:31:15",
"completedAt": null,
"errors": [
{
"field": "buyerReference",
"message": "Buyer reference is required for INCOMING invoices"
}
],
"additionalData": null
}
],
"totalElements": 42,
"totalPages": 3,
"number": 0,
"size": 20,
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"first": true,
"last": false,
"empty": false
}
Response Fields — content[] Array
| Field | Type | Nullable | Description |
|---|---|---|---|
| trackingId | UUID | No | Unique tracking identifier of the document processing record |
| companyId | UUID | No | Unique identifier of the associated company |
| direction | String (Enum) | Yes | Document direction (INCOMING/OUTGOING) |
| documentType | String (Enum) | Yes | Document format/type (e.g., XRECHNUNG, ZUGFERD, KSEF, MY_INVOIS) |
| waybillType | String (Enum) | Yes | Waybill type. Values: RS_WAYBILL_DESPATCH, RS_WAYBILL_RECEIPT, RS_APPLICATION_RESPONSE, RO_ETRANSPORT |
| source | String (Enum) | Yes | Source from which the document originated |
| target | String (Enum) | Yes | Target system where the document will be delivered |
| status | String (Enum) | No | Current processing status |
| filename | String | Yes | Name of the processed file |
| invoiceNumber | String | Yes | Invoice number (parsed from document content) |
| documentId | UUID | Yes | ID of the created document if processing completed |
| sendingResult | String | Yes | Result message from submission to target system |
| errorType | String (Enum) | Yes | Error category (e.g., VALIDATION_FAILED, INVOICE_PROCESS_NOT_FOUND) |
| createdAt | DateTime | No | Timestamp when the processing record was created. Format: YYYY-MM-DDTHH:mm:ss |
| statusUpdatedAt | DateTime | No | Timestamp of the last status update |
| completedAt | DateTime | Yes | Timestamp when processing completed (only populated for COMPLETED status) |
| errors | Object | Yes | Error details. Can be ValidationErrors[], String[], or String |
| additionalData | Object | Yes | Country-specific metadata (e.g., KSeF reference number, ANAF submission ID) |
Response Fields — Pagination Metadata
| Field | Type | Description |
|---|---|---|
| totalElements | Long | Total number of records matching the filters |
| totalPages | Integer | Total number of pages |
| number | Integer | Current page number (0-indexed) |
| size | Integer | Number of records per page |
| sort.sorted | Boolean | Whether results are sorted |
| first | Boolean | Whether this is the first page |
| last | Boolean | Whether this is the last page |
| empty | Boolean | Whether the page content is empty |
The following error codes may be returned by this endpoint.
400 - Invalid Request
Returned when request body validation fails. The companyId field is marked as @NotNull and is required. Invalid enum values or format errors also trigger this code.
{
"errorMessage": "Validation failed",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-abc123",
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/document-process/search",
"validationErrors": [
{
"field": "companyId",
"message": "must not be null"
}
]
}
Trigger Conditions:
- companyId field is missing or null
- direction field contains an invalid enum value (e.g., "BOTH" instead of "INCOMING" or "OUTGOING")
- source field contains an invalid enum value
- status field contains an invalid enum value
- createdAt.from or createdAt.to has an invalid date format (must be YYYY-MM-DD)
- createdAt.from or createdAt.to contains a future date (@PastOrPresent constraint)
401 - Authentication Failure
Returned when the JWT token is missing, expired, or invalid.
{
"errorMessage": "AUTHORIZATION_FAILED",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "corr-def456",
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/document-process/search"
}
Trigger Conditions:
- R-Auth header is not provided
- JWT token has expired (exp claim has passed)
- JWT token signature is invalid (secret key mismatch)
- JWT token format is malformed or cannot be parsed
403 - Authorization Failure
The user has passed authentication but does not have the required authority on the specified company.
{
"errorMessage": "AUTHORIZATION_FAILED",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "corr-ghi789",
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/document-process/search"
}
Note: In the project architecture, AuthorizationServiceException is mapped to 401 UNAUTHORIZED. Even if the user has a valid token, this error is returned if the user does not have ADMIN, INCOMING_INVOICE_DISPLAY, or OUTGOING_INVOICE_DISPLAY authority on the specified company.
Trigger Conditions:
- User has no role on the company specified by companyId
- User's current role does not include any of ADMIN, INCOMING_INVOICE_DISPLAY, or OUTGOING_INVOICE_DISPLAY
500 - Internal Server Error
Returned when an unexpected server error occurs.
{
"errorMessage": "An unexpected error occurred",
"errorType": "INTERNAL_SERVER_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "corr-jkl012",
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/document-process/search"
}
Trigger Conditions:
- Database connection failure
- Redis connection issue
- Unexpected RuntimeException or IOException
7. Get PDF From UBL POST
Purpose of Use: This API endpoint converts e-invoice XML data in UBL (Universal Business Language) format into a human-readable PDF document. Client applications (ERP systems, accounting software, portal interfaces) use this service to generate visual previews, printable copies, or archival PDF outputs of invoices sent or received over the Peppol network.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/generate/pdf |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Authentication | R-Auth header (JWT token) |
| Success Response | 200 OK — Binary PDF data (byte[]) |
Example Request
curl --location 'https://api-stage.docnova.ai/invoice/generate/pdf' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: eyJhbGciOiJIUzUxMiJ9...' \
--data '{
"base64XML": "PD94bWwgdmVyc2...",
"country": "BE",
"type": "PEPPOL_BIS",
"vatNumber": "BE0401065997"
}'
Request Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| base64XML | String | Yes | Base64-encoded invoice XML data. Supports UBL 2.1, ZUGFeRD, CII, and country-specific XML formats. |
| type | DataType(Enum) | Yes | Specifies the format type of the invoice data. Determines which XSLT template will be used to process the XML. |
| country | Country(Enum) | No | Company country country code (ISO 3166-1 Alpha-2). When specified, company details (logo, language) are applied to the PDF. |
| vatNumber | String | No | Company VAT/Tax number. Used together with country to apply company settings (language, template) to the PDF. |
type Parameter Accepted Values
| Value | Group | Description |
|---|---|---|
| PEPPOL_BIS | UBL/Peppol | Peppol BIS Billing 3.0 format |
| XRECHNUNG | UBL/Peppol | Germany XRechnung UBL format |
| RO_EFACTURA | UBL/Peppol | Romania e-Invoice format |
| DK_OIOUBL | Country-Specific | Denmark OIOUBL format |
| EG_INVOICE | Country-Specific | Egypt e-Invoice format |
| HR_INVOICE | Country-Specific | Croatia e-Invoice format |
| UAE_PINT | Country-Specific | UAE PINT format |
| MY_INVOIS | Country-Specific | Malaysia MyInvois format |
| MY_PINT | Country-Specific | Malaysia PINT format |
| ZUGFERD | ZUGFeRD/CII | ZUGFeRD 2.x format (XML embedded in PDF) |
| FACTUR_X | ZUGFeRD/CII | Factur-X format (XML embedded in PDF) |
| XRECHNUNG_CII | ZUGFeRD/CII | XRechnung CII format |
| CII | ZUGFeRD/CII | UN/CEFACT CII format |
| CID | ZUGFeRD/CII | CID format |
| ZUGFeRD/CII | Unstructured invoice, processed with ZUGFeRD template | |
| KZ_ESF_V2 | Poland/Kazakhstan | KZ ESF v2 invoice format |
| KSEF | Poland | Poland KSeF format |
| KSEF_OFFLINE | Poland | Poland KSeF offline format |
country Parameter Example Values
| Value | Country | Currency |
|---|---|---|
| DE | Germany | EUR |
| FR | France | EUR |
| BE | Belgium | EUR |
| NL | Netherlands | EUR |
| AT | Austria | EUR |
| IT | Italy | EUR |
| PL | Poland | PLN |
| RO | Romania | RON |
| TR | Turkey | TRY |
| EG | Egypt | EGP |
| AE | UAE | AED |
| MY | Malaysia | MYR |
| DK | Denmark | DKK |
| HR | Croatia | EUR |
| KZ | Kazakhstan | KZT |
All country codes following the ISO 3166-1 Alpha-2 standard are supported.
Responses
200 - Successful Response
| Property | Value |
|---|---|
| HTTP Status | 200 OK |
| Content-Type | application/octet-stream |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| Body | Binary PDF data (byte[]) |
A successful response does not return JSON; the binary content of the PDF file is returned directly.
400 - Bad Request
Cause: Base64 decoding error, invalid XML structure, or XSLT transformation failure.
{
"errorMessage": "PDF convert error: Illegal base64 character",
"errorType": "PDF_CONVERT_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "a1b2c3d4-e5f6-7890",
"timestamp": "2026-02-12T14:30:00.000000",
"path": "/invoice/generate/pdf"
}
400 - Bad Request — IllegalStateException (PDF Conversion Failure)
Cause: An unexpected error occurred during HTML-to-PDF conversion (corrupted HTML output, missing fonts, etc.).
{
"errorMessage": "PDF convert error: PDF conversion failed due to an unexpected error",
"errorType": "PDF_CONVERT_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "b2c3d4e5-f6a7-8901",
"timestamp": "2026-02-12T14:31:00.000000",
"path": "/invoice/generate/pdf"
}
400 - Bad Request — Invalid type Value
Cause: An undefined enum value was sent for the type field.
{
"errorMessage": "JSON parse error: Cannot deserialize value of type `DataType` from String \"INVALID_TYPE\"",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "c3d4e5f6-a7b8-9012",
"timestamp": "2026-02-12T14:32:00.000000",
"path": "/invoice/generate/pdf"
}
400 - Bad Request — Invalid country Value
Cause: An undefined enum value was sent for the country field.
{
"errorMessage": "JSON parse error: Cannot deserialize value of type `Country` from String \"XX\"",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "d4e5f6a7-b8c9-0123",
"timestamp": "2026-02-12T14:33:00.000000",
"path": "/invoice/generate/pdf"
}
401 - Unauthorized
Cause: Missing, invalid, or expired JWT token in R-Auth header.
{
"errorMessage": "Unauthorized access",
"errorType": "UNAUTHORIZED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "e5f6a7b8-c9d0-1234",
"timestamp": "2026-02-12T14:34:00.000000",
"path": "/invoice/generate/pdf"
}
500 - Internal Server Error
Cause: Disk I/O errors, memory insufficiency, or other unexpected runtime errors during PDF generation.
{
"errorMessage": "An unexpected error occurred during PDF generation",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "f6a7b8c9-d0e1-2345",
"timestamp": "2026-02-12T14:35:00.000000",
"path": "/invoice/generate/pdf"
}
8. Invoice Search POST
Purpose of Use: The POST /invoice/search-documents endpoint is used to search for invoices and documents belonging to a specific company using various filter criteria. Users can search by date range, document direction (incoming/outgoing), invoice status, document format, and other attributes, receiving paginated results. The response includes a list of matching documents, total document count, and amount summaries (tax-exclusive and tax-inclusive totals). This endpoint performs document search operations across all supported country solutions (Germany, Austria, Belgium, Netherlands, Norway, Sweden, Poland, Denmark, Slovakia, Croatia, Malaysia, UAE, Romania). Key use cases include: listing incoming invoices within a specific date range, tracking the status of sent documents, searching documents by reference number, and obtaining amount summaries for financial reporting.
Endpoint Information
| Property | Value |
|---|---|
| URL | /invoice/search-documents |
| Method | POST |
| Authentication | R-Auth header (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": "{COMPANY_UUID}",
"documentType": "INCOMING",
"endDate": "2026-09-09",
"page": 1,
"size": 5,
"startDate": "2025-09-09"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| companyId | UUID | Yes | Unique identifier of the company to search within |
| documentType | DocumentType | No | Document direction filter (INCOMING or OUTGOING) |
| status | InvoiceStatus | No | Invoice status filter (see values table below) |
| type | DataType | No | Document format type filter (see values table below) |
| startDate | LocalDate | No | Start of the search date range (YYYY-MM-DD) |
| endDate | LocalDate | No | End of the search date range (YYYY-MM-DD) |
| tin | String | No | Filter by Tax Identification Number |
| uit | String | No | Filter by additional identifier |
| referenceDocument | String | No | Search by reference document number, supplier/customer name, or VAT number |
| page | Integer | No | Page number (default: 0, zero-indexed) |
| size | Integer | No | Number of records per page (default: 50) |
Parameter Value Tables
documentType Values
| Value | Description |
|---|---|
| INCOMING | Incoming invoices (received from suppliers) |
| OUTGOING | Outgoing invoices (sent to customers) |
status Values
| Category | Value | Description |
|---|---|---|
| General | CREATED | Invoice created |
| PENDING | Processing pending | |
| CANCELED | Cancelled | |
| DELETED | Deleted (soft delete) | |
| CREDIT_BLOCKED | Credit blocked | |
| Format Save | SAVED_AS_UBL | Saved as UBL format |
| SAVED_AS_ZUGFERD | Saved as ZUGFeRD format | |
| SAVED_AS_FACTUR_X | Saved as Factur-X format | |
| SAVED_AS_CII | Saved as CII format | |
| SAVED_AS_CID | Saved as CID format | |
| SAVED_AS_KSEF | Saved as KSeF format | |
| SAVED_AS_PDF | Saved as PDF format | |
| Transmission | SENT_TO_ACCESS_POINT | Sent to access point |
| SENT_VIA_EMAIL | Sent via email | |
| OCR | OCR_WAITING | OCR processing pending |
| OCR_PARSED | OCR parsed successfully | |
| OCR_FAILED | OCR failed | |
| OCR_PARSED_PENDING_PAYMENT | OCR parsed, payment pending | |
| OCR_WAITING_TOKEN | OCR waiting for token | |
| COMPLETED_BY_MELA_AI | Completed by Mela AI | |
| Peppol | SENT_TO_PEPPOL | Sent to Peppol network |
| SUCCESS | Successful | |
| INVALID_PARAMETERS | Invalid parameters | |
| TRANSPORT_ERROR | Transport error | |
| NO_SIGNAL_MESSAGE_RECEIVED | No signal message received | |
| AS4_ERROR_MESSAGE_RECEIVED | AS4 error message received | |
| INVALID_SIGNAL_MESSAGE_RECEIVED | Invalid signal message received | |
| INCOMING_RESPONSE_ACKNOWLEDGED | Incoming response acknowledged (MLR/MLS) | |
| INCOMING_RESPONSE_REJECTED | Incoming response rejected | |
| INCOMING_RESPONSE_ACCEPTED | Incoming response accepted | |
| OUTGOING_RESPONSE_ACKNOWLEDGED | Outgoing response acknowledged (MLR/MLS) | |
| OUTGOING_RESPONSE_REJECTED | Outgoing response rejected | |
| OUTGOING_RESPONSE_ACCEPTED | Outgoing response accepted | |
| ANAF (RO) | SENT_TO_ANAF | Sent to ANAF |
| PORTAL_OKAY | Portal approved | |
| PORTAL_ERROR | Portal error | |
| PORTAL_ERRORS | Portal errors (multiple) | |
| PORTAL_SYSTEM_ERROR | Portal system error | |
| PORTAL_IN_PROCESS | Portal processing | |
| LHDNM (MY) | LHDNM_SUBMITTED | Submitted to LHDNM |
| LHDNM_VALID | Validated by LHDNM | |
| LHDNM_INVALID | Invalidated by LHDNM | |
| LHDNM_CANCELLED | Cancelled by LHDNM | |
| LHDNM_REJECT_REQUESTED | LHDNM rejection requested | |
| LHDNM_REJECTED | Rejected by LHDNM | |
| LHDNM_ERROR | LHDNM error | |
| ETA (EG) | ETA_SUBMITTED | Submitted to ETA |
| KSeF (PL) | KSEF_PENDING | Pending in KSeF |
| KSEF_ACCEPTED | Accepted by KSeF | |
| KSEF_REJECTED | Rejected by KSeF | |
| KSEF_DUPLICATE | Duplicate in KSeF | |
| eRačun (HR) | ERACUN_ERROR | eRačun error |
| ERACUN_PENDING | eRačun pending | |
| ERACUN_WAITING_TO_SEND | eRačun waiting to send | |
| ERACUN_SENT | eRačun sent | |
| ERACUN_RECEIVED | eRačun received | |
| ERACUN_APPROVED | eRačun approved | |
| ERACUN_REJECTED | eRačun rejected | |
| ERACUN_FULLY_PAID | eRačun fully paid | |
| ERACUN_PARTIALLY_PAID | eRačun partially paid | |
| ERACUN_DELIVERY_FAILED | eRačun delivery failed | |
| Nemhandel (DK) | SENT_TO_NEMHANDEL | Sent to Nemhandel |
type Values
| Value | Group | Description |
|---|---|---|
| PEPPOL_BIS | XRECHNUNG | Peppol BIS standard |
| RO_EFACTURA | XRECHNUNG | Romania e-Invoice |
| XRECHNUNG | XRECHNUNG | Germany XRechnung standard |
| MY_INVOIS | MY_INVOIS | Malaysia MyInvois |
| MY_PINT | MY_PINT | Malaysia PINT |
| DK_OIOUBL | DK_OIOUBL | Denmark OIOUBL |
| EG_INVOICE | EG_INVOICE | Egypt e-Invoice |
| HR_INVOICE | HR_INVOICE | Croatia e-Invoice |
| UAE_PINT | UAE_PINT | UAE PINT |
| ZUGFERD | ZUGFERD | ZUGFeRD standard |
| FACTUR_X | ZUGFERD | Factur-X (France) |
| XRECHNUNG_CII | ZUGFERD | XRechnung CII format |
| CII | ZUGFERD | Cross Industry Invoice |
| CID | ZUGFERD | CID format |
| ZUGFERD | PDF document | |
| KZ_ESF_V2 | KZ_ESF_V2 | Kazakhstan ESF v2 |
| KSEF | KSEF | Poland KSeF |
| KSEF_OFFLINE | KSEF_OFFLINE | Poland KSeF offline |
Responses
200 - Successful Response
{
"totalCount": 50,
"netTotal": 8422.0,
"invoiceList": [
{
"id": "89596abc-1aa2-4d28-ade4-...",
"companyId": "b8d79b88-44b1-4347-a3f9-...",
"userId": null,
"customerName": "Germany Demo Company",
"supplierName": "Belgium Demo Company",
"supplierId": "BE234233327",
"supplierVat": "BE234233327",
"status": "OUTGOING_RESPONSE_ACCEPTED",
"invoiceNumber": "90002002",
"taxExclusiveAmount": 1000.0,
"taxInclusiveAmount": 1210.0,
"lineExtensionAmount": 1000.0,
"payableAmount": 1210.0,
"allowanceTotalAmount": null,
"currency": "EUR",
"createdTime": "2026-01-15T09:22:00.703586",
"localCreatedTime": "2026-01-15T10:22:00.703768",
"issueDate": "2026-01-14",
"deliveryDate": "2026-01-14",
"dueDate": "2026-01-14",
"supplierCountryCode": "BE",
"supplierEndpoint": "iso6523-actorid-upis::9925:...",
"customerId": "BE0401065997",
"customerVat": "BE0401065997",
"customerEndpoint": "iso6523-actorid-upis::9925:...",
"customerCountryCode": "BE",
"typeCode": "380",
"documentType": "INCOMING",
"errorMessage": null,
"lastUpdatedTime": "2026-01-15T09:22:00.703817",
"localLastUpdatedTime": "2026-01-15T10:22:00.703818",
"type": "PEPPOL_BIS",
"idIncarcare": null,
"idDescarcare": null,
"source": "PEPPOL",
"sendViaPeppol": false,
"statusTime": "2026-01-15T09:22:00.703812",
"localStatusTime": "2026-01-15T10:22:00.703815",
"fileName": null,
"ocrParser": null,
"paymentDetails": {
"paymentStatus": "LATE",
"paidAmount": 0.0,
"totalAmount": 1210.0,
"remainingAmount": 1210.0,
"paymentDate": null
},
"profileType": "EN16931",
"isActive": true,
"countrySpecificData": null
},
{
"id": "c3b82ec0-e91f-40eb-924e-...",
"companyId": "b8d79b88-44b1-4347-a3f9-...",
"userId": null,
"customerName": "Germany Demo Company",
"supplierName": "Belgium Demo Company",
"supplierId": "BE0401065997",
"supplierVat": "BE0401065997",
"status": "SAVED_AS_UBL",
"invoiceNumber": "90001998",
"taxExclusiveAmount": 1000.0,
"taxInclusiveAmount": 1210.0,
"lineExtensionAmount": 1000.0,
"payableAmount": 1210.0,
"allowanceTotalAmount": null,
"currency": "EUR",
"createdTime": "2026-01-13T12:02:00.875403",
"localCreatedTime": "2026-01-13T13:02:00.87577",
"issueDate": "2026-01-13",
"deliveryDate": "2026-01-09",
"dueDate": "2026-01-15",
"supplierCountryCode": "BE",
"supplierEndpoint": "iso6523-actorid-upis::9925:...",
"customerId": "BE0401065997",
"customerVat": "BE0401065997",
"customerEndpoint": "iso6523-actorid-upis::9925:...",
"customerCountryCode": "BE",
"typeCode": "380",
"documentType": "INCOMING",
"errorMessage": null,
"lastUpdatedTime": "2026-01-13T12:02:00.875844",
"localLastUpdatedTime": "2026-01-13T13:02:00.875851",
"type": "PEPPOL_BIS",
"idIncarcare": null,
"idDescarcare": null,
"source": "PEPPOL",
"sendViaPeppol": false,
"statusTime": "2026-01-13T12:02:00.875836",
"localStatusTime": "2026-01-13T13:02:00.875841",
"fileName": null,
"ocrParser": null,
"paymentDetails": {
"paymentStatus": "LATE",
"paidAmount": 0.0,
"totalAmount": 1210.0,
"remainingAmount": 1210.0,
"paymentDate": null
},
"profileType": "EN16931",
"isActive": true,
"countrySpecificData": null
}
],
"total": 9262.0
}
| Field | Type | Description |
|---|---|---|
| totalCount | Long | Total number of documents matching the filters |
| netTotal | Double | Sum of tax-exclusive amounts |
| Total | Double | Sum of tax-inclusive amounts |
| invoiceList | List<Invoice> | Paginated list of invoices |
Invoice Object within invoiceList
| Field | Type | Description |
|---|---|---|
| id | String | Unique invoice identifier (UUID) |
| companyId | String | Company identifier |
| userId | String | User identifier |
| customerName | String | Customer name |
| supplierName | String | Supplier name |
| supplierId | String | Supplier identifier |
| supplierVat | String | Supplier VAT number |
| status | InvoiceStatus | Invoice status |
| invoiceNumber | String | Invoice number |
| taxExclusiveAmount | Double | Tax-exclusive amount |
| taxInclusiveAmount | Double | Tax-inclusive amount |
| lineExtensionAmount | Double | Line extension total amount |
| payableAmount | Double | Payable amount |
| allowanceTotalAmount | Double | Total allowance amount |
| currency | String | Currency code (ISO 4217) |
| createdTime | DateTime | Creation timestamp (UTC) |
| localCreatedTime | DateTime | Local creation timestamp |
| issueDate | DateTime | Issue date |
| deliveryDate | DateTime | Delivery date |
| dueDate | DateTime | Due date |
| supplierCountryCode | String | Supplier country code |
| supplierEndpoint | String | Supplier endpoint address |
| customerId | String | Customer identifier |
| customerVat | String | Customer VAT number |
| customerEndpoint | String | Customer endpoint address |
| customerCountryCode | String | Customer country code |
| typeCode | String | Document type code |
| documentType | DocumentType | Document direction (INCOMING/OUTGOING) |
| errorMessage | String | Error message (if applicable) |
| lastUpdatedTime | DateTime | Last update timestamp (UTC) |
| localLastUpdatedTime | DateTime | Local last update timestamp |
| type | DataType | Document format type |
| source | InvoiceSource | Invoice source |
| sendViaPeppol | Boolean | Whether sent via Peppol |
| statusTime | DateTime | Status change timestamp |
| fileName | String | File name |
| ocrParser | OcrParser | OCR parser type |
| paymentDetails | InvoicePaymentDetails | Payment details |
| profileType | ProfileType | Profile type |
| isActive | Boolean | Active status |
| countrySpecificData | Object | Country-specific data |
400 - Bad Request
Trigger: When companyId is sent in an invalid UUID format, when documentType or status fields contain a value not defined in the enum, or when the date format is incorrect.
{
"errorMessage": "Invalid UUID string: invalid-uuid",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-xxxx-xxxx",
"status": 400,
"timestamp": "2026-02-13T10:30:00",
"path": "/invoice/search-documents"
}
401 - Unauthorized
Trigger: When the R-Auth header is missing, contains an expired JWT token, or an invalid token. Also returned when the user does not have authorization for the specified company.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"errorId": "corr-xxxx-xxxx",
"status": 401,
"timestamp": "2026-02-13T10:30:00",
"path": "/invoice/search-documents"
}
404 - Not Found
Trigger: When no company matching the specified companyId is found.
{
"errorMessage": "Company not found with id: b8d79b88-44b1-4347-a3f9-5438c2a4f936",
"errorType": "NOT_FOUND",
"errorTitle": "NOT_FOUND",
"errorId": "corr-xxxx-xxxx",
"status": 404,
"timestamp": "2026-02-13T10:30:00",
"path": "/invoice/search-documents"
}
422 - Unprocessable Entity
Trigger: When the request is syntactically correct but violates business rules. For example, when startDate is greater than endDate or an invalid date range is specified.
{
"errorMessage": "Start date cannot be after end date",
"errorType": "BUSINESS_ERROR",
"errorTitle": "UNPROCESSABLE_ENTITY",
"errorId": "corr-xxxx-xxxx",
"status": 422,
"timestamp": "2026-02-13T10:30:00",
"path": "/invoice/search-documents"
}
500 - Internal Server Error
Trigger: Triggered by server-side issues such as database connection errors, unexpected runtime exceptions, or I/O errors.
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "corr-xxxx-xxxx",
"status": 500,
"timestamp": "2026-02-13T10:30:00",
"path": "/invoice/search-documents"
}
9. 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.
With this API you can:
- List all MLR responses belonging to a specific company
- Query MLR status for a specific invoice (invoiceId) or document (documentId)
- Filter by the counterpart’s Peppol participant identifier (counterpartParticipantId)
- Perform time based searches by specifying a date range (fromDate, toDate)
- Returned responses include detail lines for each MLR record (error field, status reason, description)
This enables developers to programmatically track the final status of the invoice delivery process and take necessary actions in case of errors.
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 | Type | Required | Format | Description |
|---|---|---|---|---|
| companyId | String(UUID) | Yes | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Unique identifier of the company to query |
| documentId | String(UUID) | No | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Peppol document identifier (instance identifier) |
| counterpartParticipantId | String | No | {scheme}:{identifier} (e.g., 9930:de111222777) | Counterpart’s Peppol participant identifier |
| invoiceId | String | No | Free text | Invoice number or identifier |
| fromDate | String(ISO Date) | No | yyyy-MM-dd (e.g., 2025-09-09) | Search start date (inclusive) |
| toDate | String(ISO Date) | No | yyyy-MM-dd (e.g., 2026-09-09) | Search end date (inclusive) |
Request Headers
| Header | Type | Required | Description |
|---|---|---|---|
| R-Auth | String (JWT) | Yes | User authentication token. JWT signed with HS512 algorithm |
| Accept | String | No | Default /. Response is returned as application/json |
Parameter Values
counterpartParticipantId Format
| Scheme | Description | Example |
|---|---|---|
| 9930 | Germany VAT number | 9930:de111222777 |
| 0204 | Leitweg-ID | 0204:1234567890123 |
| 0088 | EAN location code | 0088:1234567890123 |
responseType Response Type Enum Values
| Value | Description |
|---|---|
| ACCEPTANCE | Document was accepted by the counterpart |
| ACKNOWLEDGING | Document was acknowledged (received) by the counterpart |
| REJECTION | Document was rejected by the counterpart |
statusReasonCode Status Reason Code Enum Values
| Value | Description |
|---|---|
| BUSINESS_RULE_VIOLATION_FATAL | Business rule violation. Critical error. Document was not processed |
| BUSINESS_RULE_VIOLATION_WARNING | Business rule violation. Warning. Document can still be processed |
| SYNTAX_VIOLATION | Syntax error. Document format is invalid |
Responses
200 - Successful Response
Type: List<SearchMLRResponse>
{
[
{
"id": "a1b2c3d4-e5f6-7890-abcd-...",
"companyId": "60ccd1a7-5348-47b2-9ef6-...",
"documentId": "8fa4606f-94f2-45e1-a8cb-...",
"responseType": "ACCEPTANCE",
"receivedTime": "2026-01-15T14:30:00",
"counterpartParticipantId": "9930:de111222777",
"invoiceId": "2026_007_peppol",
"responseLines": [
{
"id": "f1e2d3c4-b5a6-7890-abcd-...",
"errorField": null,
"responseCode": "ACCEPTANCE",
"description": "Document successfully processed",
"statusReasonCode": null
}
]
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
| id | UUID | Unique identifier of the MLR record |
| companyId | String | Identifier of the related company |
| documentId | String | Peppol document identifier |
| responseType | Enum (MessageLevelResponseType) | Overall response type: ACCEPTANCE, ACKNOWLEDGING, REJECTION |
| receivedTime | DateTime (ISO 8601) | Date and time the MLR response was received |
| counterpartParticipantId | String | Counterpart’s Peppol participant identifier |
| invoiceId | String | Related invoice number |
| responseLines | List<SearchMLRLineResponse> | MLR detail lines |
Response Detail Lines
| Field | Type | Description |
|---|---|---|
| id | UUID | Unique identifier of the detail line |
| errorField | String (nullable) | The field / XPath expression where the error occurred |
| responseCode | Enum (MessageLevelResponseType) | Line level response code: ACCEPTANCE, ACKNOWLEDGING, REJECTION |
| description | String (nullable) | Error or status description |
| statusReasonCode | Enum (MLRStatusReasonCode) (nullable) | Status reason code: BUSINESS_RULE_VIOLATION_FATAL, BUSINESS_RULE_VIOLATION_WARNING, SYNTAX_VIOLATION |
400 - Bad Request
Occurs when the required companyId parameter is missing or when the date format is invalid.
{
"errorMessage": "Required request parameter 'companyId' for method parameter type String is not present",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "corr-xxx-xxx",
"timestamp": "2026-01-15T14:30:00",
"path": "/peppol/search-mlr"
}
Description: The companyId parameter is mandatory and Spring framework automatically returns this error when it is missing. Additionally, if fromDate or toDate parameters do not conform to the yyyy-MM-dd ISO format, the same error code is returned.
401 - Unauthorized
Occurs when the JWT token is invalid, expired, or the R-Auth header is missing. Also returned when the user is not associated with the specified companyId.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "corr-xxx-xxx",
"timestamp": "2026-01-15T14:30:00",
"path": "/peppol/search-mlr"
}
Description: The authorizationService.checkIfCompanyUser(companyId, userId) method verifies that the user identity in the JWT token matches the specified companyId. If they do not match, an AuthorizationServiceException is thrown. This error is also returned when the token is expired or its signature is invalid.
500 - Internal Server Error
Returned in case of database access errors, unexpected runtime exceptions, or other server-side failures.
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"errorId": "corr-xxx-xxx",
"timestamp": "2026-01-15T14:30:00",
"path": "/peppol/search-mlr"
}
Description: Returned in case of database connection errors, JPA/Hibernate query failures, or unexpected internal server errors. The errorId (correlation id) field can be used to trace detailed error information from log records.
Error Response General Format
| Field | Type | Description |
|---|---|---|
| errorMessage | String | Human readable description of the error |
| errorType | String | Error classification code (e.g., NOT_AUTHORITY, RUNTIME_ERROR) |
| errorTitle | String (HttpStatus) | HTTP status code name (e.g., BAD_REQUEST, UNAUTHORIZED, INTERNAL_SERVER_ERROR) |
| status | Integer | HTTP status code numeric value (e.g., 400, 401, 500) |
| errorId | String (nullable) | Correlation ID used for log tracing |
| data | String (nullable) | Additional data (if available) |
| details | Map<String, Object> (nullable) | Detailed error information (if available) |
| validationErrors | List<ValidationError> (nullable) | Field level validation errors (if available) |
| timestamp | DateTime (ISO 8601) | Time when the error occurred |
| path | String | Endpoint path where the error occurred |
10. Peppol - Send MLR POST
Purpose of Use The POST /peppol/send-mlr endpoint is used to send a Message Level Response (MLR) within the Peppol infrastructure.
An MLR is the official response given by the receiving party to an e-invoice received through Peppol. This response communicates to the sender whether the invoice was successfully received and accepted, is being processed (acknowledged), or has been rejected. The receiver can inform the sender in detail by specifying errors in the invoice (IBAN error, syntax error, business rule violation, etc.).
After the MLR is sent, the related invoice status is automatically updated.
Endpoint Information
| Property | Value |
|---|---|
| URL | /peppol/send-mlr |
| Method | POST |
| Content-Type | application/json |
| Base URL | Stage Environment URLhttps://app-stage.docnova.ai/ Production Environment URLhttps://api.docnova.ai/ |
| 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: <JWT_TOKEN>' \
--data '{
"errorLines": [
{
"description": "The IBAN number provided in the payment instructions is invalid or missing",
"errorField": "PaymentMeans/PayeeFinancialAccount/ID",
"responseCode": "ACKNOWLEDGING",
"statusReasonCode": "BUSINESS_RULE_VIOLATION_WARNING"
}
],
"invoiceId": "<INVOICE_UUID>",
"responseCode": "ACCEPTANCE"
}'
Request Parameters
Root Level Parameters
| Field Name | Type | Required | Description |
|---|---|---|---|
| invoiceId | String (UUID) | Yes | Unique identifier of the invoice to send the MLR for (UUID format) |
| responseCode | Enum (MessageLevelResponseType) | Yes | Overall response code for the invoice |
| errorLines | Array<MLRErrorLine> | No | List of error details in the invoice. Can be left empty |
errorLines Array Element
| Field Name | Type | Required | Description |
|---|---|---|---|
| description | String | No | Human readable description of the error |
| errorField | String | No | UBL/XML field path where the error was detected (XPath-like) |
| responseCode | Enum (MessageLevelResponseType) | No | Response code specific to this error line |
| statusReasonCode | Enum (MLRStatusReasonCode) | No | Classification code of the error |
Allowed Parameter Values
MessageLevelResponseType (responseCode)
| Value | Description |
|---|---|
| ACCEPTANCE | Invoice accepted. It has been processed and approved |
| ACKNOWLEDGING | Invoice received. Receipt is confirmed but not yet fully processed |
| REJECTION | Invoice rejected. Not processed due to errors |
MLRStatusReasonCode (statusReasonCode)
| Value | Description |
|---|---|
| BUSINESS_RULE_VIOLATION_FATAL | Fatal business rule violation. A critical error that prevents the invoice from being processed |
| BUSINESS_RULE_VIOLATION_WARNING | Warning level business rule violation. The invoice can be processed but correction is recommended |
| SYNTAX_VIOLATION | Syntax error. Format or schema incompatibility in the XML/UBL structure |
Responses
200 - Successful Response
| Field | Type | Value | Description |
|---|---|---|---|
| HTTP Status | Integer | 200 | Operation successful |
| Body | String | "MLR sent successfully" | Response text returned from the Access Point service |
"MLR sent successfully"
404 - Not Found
Trigger Condition: When no invoice matching the provided invoiceId is found in the database.
{
"errorMessage": "<invoiceId> Invoice not found",
"errorType": "NOT_FOUND_INVOICE",
"errorTitle": "NOT_FOUND",
"errorId": "<correlation-id>",
"status": 404,
"timestamp": "2026-02-12T14:30:00",
"path": "/peppol/send-mlr"
}
Description: The invoiceId parameter contains an invalid or unregistered UUID in the database. Ensure the invoice ID is correct.
400 - Bad Request
Trigger Condition: When an error occurs while forwarding the MLR to the Access Point service (connection error, timeout, Access Point rejection).
{
"errorMessage": "Failed to send MLR: <detailed error message>",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "<correlation-id>",
"status": 400,
"timestamp": "2026-02-12T14:30:00",
"path": "/peppol/send-mlr"
}
Description: The MLR was saved to the database but could not be forwarded to the Access Point. The error message contains the detail returned from the Access Point. Check your network connectivity and Access Point service availability.
400 - Bad Request — Invalid responseCode
Trigger Condition: When the responseCode field contains an invalid enum value (i.e., a value other than ACCEPTANCE, ACKNOWLEDGING, REJECTION).
{
"errorMessage": "Unknown response code: <invalid_value>",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "<correlation-id>",
"status": 400,
"timestamp": "2026-02-12T14:30:00",
"path": "/peppol/send-mlr"
}
Description: The responseCode field only accepts ACCEPTANCE, ACKNOWLEDGING, or REJECTION values. Verify the value you are sending.
400 - Bad Request — Invalid UUID Format
Trigger Condition: When the invoiceId field is not in a valid UUID format.
{
"errorMessage": "Invalid UUID string: <invalid_value>",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "<correlation-id>",
"status": 400,
"timestamp": "2026-02-12T14:30:00",
"path": "/peppol/send-mlr"
}
Description: : The invoiceId value must be a valid UUID in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
401 - Unauthorized
Trigger Condition: When the R-Auth header is missing, invalid, or contains an expired JWT token.
{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"errorId": "<correlation-id>",
"status": 401,
"timestamp": "2026-02-12T14:30:00",
"path": "/peppol/send-mlr"
}
Description: The JWT token has expired or is malformed. Obtain a new token and retry.
500 - Internal Server Error
Trigger Condition: When a database error, network error, or unexpected exception occurs.
{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "<correlation-id>",
"status": 500,
"timestamp": "2026-02-12T14:30:00",
"path": "/peppol/send-mlr"
}
Description: An unexpected error occurred on the server side. Forward the errorId (correlation ID) value to the support team for detailed investigation.
Error Response Model (ExceptionResponse)
| Field Name | Type | Description |
|---|---|---|
| errorMessage | String | Detailed description of the error |
| errorType | String | Error classification code (e.g., NOT_FOUND_INVOICE, API_ERROR) |
| errorTitle | String (HttpStatus) | HTTP status name (e.g., NOT_FOUND, BAD_REQUEST) |
| errorId | String | Correlation identifier (for log tracing) |
| status | Integer | HTTP status code (e.g., 400, 404, 500) |
| data | String | Additional data (if available) |
| details | Map<String, Object> | Additional detail information (if available) |
| validationErrors | Array<ValidationError> | Validation error list (if available) |
| timestamp | String (ISO 8601) | Timestamp of when the error occurred |
| path | String | Endpoint path of the request |