Skip to main content
Version: 1.0.0

France E-Invoice & E-Reporting Factur-X


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

PropertyValue
Endpoint/auth/login
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationNone (Initial access)

Request Body (JSON)

The following fields are used to define login criteria:

FieldTypeDescription
apiKeyStringA 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”)
emailStringThe 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:

FieldTypeDescription
jwtThe secure session token that must be used as a 'R-Auth' API Key in all subsequent API calls.
expirationDateDateTimeIndicates 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

PropertyValue
KeyEnter R-Auth in the Key field.
Value{{apiKey}} or {{jwt}} (Copy the jwt string returned from the login endpoint.)
Header SettingNavigate to the "Headers" tab of the request to be sent.

Chorus Pro Test SIREN Guide

This guide explains how to create test SIREN numbers for the Docnova stage environment.


To view the PDF version of the guide, click the button below.

Open PDF Guide

EDI / iDoc - FR Invoices Standard Mappings

Click to enlarge

1. Introduction

This guide is structured to allow development teams to incorporate portal features into their business workflows with minimum effort and maximum compliance.

2. Authentication POST

Purpose of Use: This endpoint is utilized by ERP systems to obtain the session key (JWT Token) required to establish a secure connection and initiate data exchange with the docnova portal.

An enterprise ERP system must trigger this endpoint to receive a valid authentication token before performing actions such as transmitting invoices or querying compliance reports via the portal. The acquired token is then provided in the "Authorization" header for all subsequent API requests. This mechanism ensures that data traffic between the ERP and the portal is conducted via a secure, time-bound key rather than transmitting sensitive user credentials for every transaction.

Endpoint Information

PropertyValue
URL/auth/login
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationNot required (public endpoint)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/auth/login' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--data-raw '{
"apiKey": "{{your_api_key}}",
"email": "user@example.com"
}'

Request Parameters

FieldTypeRequiredDescription
emailStringOptionalUser's registered email address
apiKeyStringYesObtained from the portal, via the settings > ERP Management > API Management menu.

Responses


200 - Login Successful

Full Response (AccountInfo)

{
"id": "a1b2c3d4-e5f6-7890-abcd-...",
"superAdmin": false,
"companies": [
{
"id": "60ccd1a7-5348-47b2-9ef6-...",
"name": "Example Company Ltd.",
"taxNumber": "1234567890",
"vatNumber": "DE123456789",
"email": "info@examplecompany.com",
"website": "https://www.examplecompany.com",
"address": "Example Street No: 1",
"city": "Berlin",
"state": "Berlin",
"country": "DE",
"postalCode": "10115",
"phoneNumber": "+49 30 1234567",
"credit": 1000,
"userCount": 5,
"portalType": "RECHNUNG",
"mailLanguage": "DE",
"currencyCode": "EUR",
"sftp": false,
"isSubCompany": false,
"featureAllowed": true,
"participants": [
{
"id": "participant-uuid",
"peppolId": "0088:1234567890"
}
]
}
],
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expirationDate": "2026-01-30T10:30:00.000Z",
"refreshToken": "refresh-token-string",
"refreshTokenExpiration": "2026-02-28T10:30:00.000Z",
"user": {
"id": "user-uuid",
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"phoneNumber": "+49 170 1234567",
"photoUrl": "https://example.com/photo.jpg",
"mailLang": "EN",
"isSuperAdmin": false,
"lastLoginTime": "2026-01-29T10:30:00",
"featureAllowed": true
},
"mfaEnabled": false,
"mfaType": null,
"secretImageUri": null,
"lastCompanyId": "60ccd1a7-5348-47b2-9ef6-...",
"requiresRecaptchaV2": false,
"message": null,
"active": true,
"isAppLogin": false
}

Basic Response (JwtBasicResponse)

{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expirationDate": "2026-01-30T10:30:00.000Z"
}

Response Fields


Account Information Fields

FieldTypeDescription
idStringUser unique identifier
superAdminBooleanWhether user has super admin privileges
companiesArray<AuthorizedCompany>List of companies user is authorized to access
jwtStringJWT access token. Used in R-Auth header for API requests
expirationDateDateTimeJWT token expiration date
refreshTokenStringRefresh token for obtaining new access tokens
refreshTokenExpirationDateTimeRefresh token expiration date
userObjectUser detail information
mfaEnabledBooleanWhether multi factor authentication is enabled
mfaTypeEnumMFA type (GOOGLE, WHATSAPP)
secretImageUriStringGoogle Authenticator QR code URI
lastCompanyIdStringLast selected company ID
requiresRecaptchaV2BooleanWhether reCAPTCHA v2 verification is required
messageStringStatus message (e.g., "MFA required")
activeBooleanWhether user account is active
isAppLoginBooleanWhether this is a mobile app login

Parameter Values Reference Table

currentCountry Values (Sample List)

ValueDescription
DEGermany
ATAustria
RORomania
KZKazakhstan
TRTurkey
FIFinland
FRFrance
ITItaly
NLNetherlands
ESSpain
SESweden
PLPoland
BEBelgium
DKDenmark
NONorway
MYMalaysia
SGSingapore
AUAustralia
NZNew Zealand
JPJapan
EGEgypt
RSSerbia
GLOBALGlobal (default)

Company Information Fields

FieldTypeDescription
idStringCompany unique identifier
nameStringCompany name
taxNumberStringTax number
vatNumberStringVAT number
emailStringCompany email address
websiteStringCompany website
addressStringAddress
cityStringCity
stateStringState or Region
countryEnumCountry code
postalCodeStringPostal code
phoneNumberStringPhone number
faxNumberStringFax number
creditIntegerAvailable credit
userCountIntegerTotal user count
portalTypeEnumPortal type
mailLanguageEnumEmail language
currencyCodeStringCurrency code
sftpBooleanWhether SFTP integration is active
isSubCompanyBooleanWhether it's a sub company
featureAllowedBooleanWhether feature access is granted
participantsArrayPeppol participant information

User Information Fields

FieldTypeDescription
idStringUser unique identifier
emailStringUser email address
firstNameStringUser first name
lastNameStringUser last name
phoneNumberStringUser phone number
photoUrlStringUser photo URL
mailLangEnumUser email language
isSuperAdminBooleanWhether user has super admin privileges
lastLoginTimeDateTimeLast login time
featureAllowedBooleanWhether feature access is granted

Enum Values Reference Table

mfaType Values

ValueDescription
GOOGLEGoogle Authenticator verification
WHATSAPPWhatsApp verification

portalType Values

ValueDescription
DEFAULTDefault portal
RECHNUNGGermany main portal
KZKazakhstan portal
RORomania portal
AUAustralia portal
ATAustria portal
BEBelgium portal
DKDenmark portal
EGEgypt portal
FIFinland portal
FRFrance portal
ITItaly portal
MYMalaysia portal
NLNetherlands portal
NONorway portal
PLPoland portal
RSSerbia portal
SESweden portal
SGSingapore portal

mailLanguage Values

ValueDescription
DEGerman
ENEnglish
TRTurkish
RORomanian
PLPolish
FRFrench
ITItalian
ESSpanish
NLDutch

200 - Login Successful

Basic Response (JwtBasicResponse)

{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expirationDate": "2026-01-30T10:30:00.000Z"
}

401 - Unauthorized

{
"timestamp": "2026-01-29T10:30:00.000Z",
"status": 401,
"error": "Unauthorized",
"message": "Invalid email or password"
}

403 - MFA Required

{
"id": "user-uuid",
"mfaEnabled": true,
"mfaType": "GOOGLE",
"message": "MFA verification required",
"jwt": null
}

429 - Too Many Requests

{
"timestamp": "2026-01-29T10:30:00.000Z",
"status": 429,
"error": "Too Many Requests",
"message": "Too many failed login attempts. Please try again later.",
"requiresRecaptchaV2": true
}

3. Search Processing History POST

Purpose of Use: The POST /invoice/document-process/search endpoint serves as the central monitoring and querying interface for all document processing activities within the system. Every document whether it is an invoice, credit note, or waybill that enters or leaves the platform passes through an asynchronous processing pipeline. This endpoint provides full visibility into that pipeline.

Endpoint Information

PropertyValue
URL/invoice/document-process/search
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)
Required AuthorityADMIN, INCOMING_INVOICE_DISPLAY, or OUTGOING_INVOICE_DISPLAY (at least one)

Example Request

curl --location 'https://api-fr-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": "2024-01-01",
"to": "2026-02-28"
}
}'

Request Parameters

FieldTypeRequiredDescription
companyIdUUIDYesUnique identifier of the company to search
directionString (Enum)NoDocument direction filter (INCOMING or OUTGOING)
sourceString (Enum)NoSource system filter
filenameStringNoExact match filter by filename
statusString (Enum)NoDocument processing status filter
createdAtObject (DateRange)NoCreation date range filter
createdAt.fromString (LocalDate)NoStart date (inclusive). Format: yyyy-MM-dd. Must be past or present
createdAt.toString (LocalDate)NoEnd date (inclusive). Format: yyyy-MM-dd. Must be past or present

Query Parameters (Pagination)

FieldTypeDefaultDescription
pageInteger0Page number (0 indexed)
sizeInteger20Number of records per page (max 100)
sortStringcreatedAt,descSort field and direction. Format: field,asc|desc

Enum Value Reference

direction Values (Document Direction)

ValueDescription
INCOMINGIncoming document
OUTGOINGOutgoing document

status Values (Processing Status)

ValueDescription
PENDINGQueued and waiting for processing
PROCESSINGCurrently being processed
COMPLETEDSuccessfully completed
FAILEDProcessing failed (retriable)
SENDING_FAILEDFailed at the sending stage
PERMANENT_FAILEDPermanently failed (will not be retried)

source Values (Source and Target System)

ValueDescription
ERPERP integration
PORTALWeb portal
PORTAL_OCRPortal upload via OCR
EMAIL_OCROCR via email
EMAILEmail
PEPPOLPeppol network
SFTPSFTP connection
KSEFPoland KSeF system
ANAFRomania ANAF system
LHDNMMalaysia LHDNM system
NEMHANDELDenmark NemHandel
RS_APISerbia API
ETAEgypt ETA system
ERACUNeRacun system
HARVESTHarvest integration
SHOPIFYShopify integration
AMAZON_SPAmazon SP API
EBAYeBay integration
HUBSPOTHubSpot integration
LAZADALazada integration
STRIPEStripe integration
SERVICEInternal service

documentType Values (Document Format)

ValueDescription
PEPPOL_BISPeppol BIS 3.0
XRECHNUNG_CIIXRechnung (CII)
ZUGFERDZUGFeRD
FACTUR_XFactur X
CIICross Industry Invoice
CIDCID format
RO_EFACTURARomania e Factura
MY_INVOISMalaysia MyInvois
MY_PINTMalaysia PINT
DK_OIOUBLDenmark OIOUBL
EG_INVOICEEgypt invoice
HR_INVOICECroatia invoice
UAE_PINTUAE PINT
KZ_ESF_V2Kazakhstan ESF v2
KSEFPoland KSeF
KSEF_OFFLINEPoland KSeF (offline)

waybillType Values (Waybill Type)

ValueDescription
RS_WAYBILL_DESPATCHSerbia despatch waybill
RS_WAYBILL_RECEIPTSerbia receipt waybill
RS_APPLICATION_RESPONSESerbia application response
RO_ETRANSPORTRomania e Transport

Responses


200 - Successful Response

{
"content": [
{
"trackingId": "a1b2c3d4-...",
"companyId": "60ccd1a7-...",
"direction": "INCOMING",
"documentType": "XRECHNUNG",
"waybillType": null,
"source": "ERP",
"target": "PEPPOL",
"status": "COMPLETED",
"filename": "invoice_2024_001.xml",
"invoiceNumber": "INV-2024-001",
"documentId": "f5e6d7c8-...",
"sendingResult": "OK",
"errorType": null,
"errors": null,
"additionalData": null,
"createdAt": "2024-06-15T10:30:00",
"statusUpdatedAt": "2024-06-15T10:30:45",
"completedAt": "2024-06-15T10:31:00"
}
],
"totalElements": 150,
"totalPages": 8,
"number": 0,
"size": 20
}

Response Fields

FieldTypeDescription
contentArray<Object>Page content (document processing records)
content[].trackingIdUUIDProcessing tracking identifier
content[].companyIdUUIDCompany identifier
content[].directionString (Enum)Document direction (INCOMING / OUTGOING)
content[].documentTypeString (Enum)Document format (see documentType enum table)
content[].waybillTypeString (Enum) | nullWaybill type (only for waybill documents)
content[].sourceString (Enum)Source system of the document
content[].targetString (Enum) | nullTarget system for the document
content[].statusString (Enum)Current processing status
content[].filenameStringOriginal filename
content[].invoiceNumberString | nullInvoice number
content[].documentIdUUID | nullAssociated document identifier
content[].sendingResultString | nullSending result message
content[].errorTypeString (Enum) | nullError type code (on failed processes)
content[].errorsObject | nullError details (validation errors, message list, or text)
content[].additionalDataObject | nullCountry or document type specific metadata
content[].createdAtString (DateTime)Creation timestamp. Format: yyyy-MM-ddTHH:mm:ss
content[].statusUpdatedAtString (DateTime)Last status update timestamp
content[].completedAtString (DateTime) | nullCompletion timestamp (only when COMPLETED)
totalElementsLongTotal number of matching records
totalPagesIntegerTotal number of pages
numberIntegerCurrent page number (0-indexed)
sizeIntegerNumber of records per page

400 - Bad Request

Trigger: When the companyId field is sent as null in the request body (@NotNull validation) or when required fields are missing.
Scenario: Sending a request without providing companyId.

{
"errorMessage": "Document process required fields: companyId",
"errorType": "DOCUMENT_PROCESS_REQUIRED_FIELDS",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-8f2a1b3c",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}

400 - Bad Request

Trigger: When the request body JSON format is malformed, an invalid enum value is sent, or the date format is incorrect.

Scenario: Sending a value like "UNKNOWN_STATUS" that is not defined in the enum for the status field, or sending an invalid date like "2024-13-45" for the createdAt.from field.

{
"errorMessage": "Invalid request. Cannot deserialize value of type `DocumentProcessStatus` from String \"UNKNOWN_STATUS\"",
"errorType": "INVALID_REQUEST",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-4d5e6f7a",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}

401 - Unauthorized

Trigger: When the R-Auth header is not provided or the JWT token signature is invalid. This error is caught at the Spring Security filter chain and does not reach the RestExceptionHandler.

Scenario: Sending a request without the header or with a corrupted/tampered token.

{
"error": "Unauthorized",
"message": "Full authentication is required to access this resource",
"status": 401
}

401 - Unauthorized

Trigger: When the JWT token is valid but the user does not have any of the ADMIN, INCOMING_INVOICE_DISPLAY, or OUTGOING_INVOICE_DISPLAY authorities on the specified companyId. Thrown by AuthorizationService.checkAnyAuthorityByCompanyAndUser().

Scenario: Performing a search with a companyId for which the user has no access permissions.

{ 

"errorMessage": "User is not authorized for this operation",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"errorId": "corr-9a8b7c6d",
"status": 401,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}

404 - Not Found

Trigger: When the provided companyId value is not found in the database. A NotFoundException is thrown by CompanyService.

Scenario: Sending a UUID as companyId that has been deleted or never existed.

{
"errorMessage": "Company not found!",
"errorType": "COMPANY_NOT_FOUND",
"errorTitle": "NOT_FOUND",
"errorId": "corr-1b2c3d4e",
"status": 404,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}

498 - Token Expired

Trigger: When the JWT token has expired. Returned by CustomAuthenticationEntryPoint at the Spring Security filter level.

Scenario: Sending a request with an expired JWT token.

{
"errorMessage": "Your session has expired. Please login again.",
"errorType": "TOKEN_EXPIRED",
"errorTitle": "UNAUTHORIZED",
"status": null,
"timestamp": null,
"path": null
}

Note: Since this response is generated at the Security filter level, the timestamp, path, and status fields are not populated by enrichResponse and return null. A custom HTTP status code of 498 is used.

500 - Internal Server Error

Trigger: When an unexpected error occurs on the server side (database connection failure, NullPointerException, etc.). Caught by the RestExceptionHandler catch-all handler.

Scenario: Database access failure, unexpected runtime exception.

{
"errorMessage": "An unexpected error occurred",
"errorType": "SERVER_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "corr-5e6f7a8b",
"status": 500,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/document-process/search"
}

Response Structure Reference (ExceptionResponse)

FieldTypeDescriptionInclusion Condition
errorMessageStringHuman readable error descriptionAlways
errorTypeStringMachine readable error code (ErrorType enum name)Always
errorTitleString (HttpStatus)HTTP status description (BAD_REQUEST, UNAUTHORIZED, etc.)Always
errorIdStringCorrelation ID (for log tracing)If present in ThreadContext
statusIntegerHTTP status code (numeric)Always
timestampString (DateTime)Timestamp when the error occurredBy RestExceptionHandler
pathStringURI of the requestBy RestExceptionHandler
dataStringAdditional data informationIf present (@JsonInclude NON_NULL)
detailsMap<String, Object>Additional detail informationIf present (@JsonInclude NON_NULL)
validationErrorsArray<ValidationError>Field level validation errorsIf present (@JsonInclude NON_NULL)

Note: The ExceptionResponse class uses @JsonInclude(JsonInclude.Include.NON_NULL). Therefore, fields with null values are excluded from the JSON response.

4. Send Document Async POST

Purpose of Use: This endpoint enables ERP systems to transmit e-invoice data to the docnova portal asynchronously. It is designed to enhance system responsiveness and efficiently manage the process queue during high-volume data transfers.

After generating an invoice in compliance with German legal standards (XRechnung or ZUGFeRD), the ERP system converts the document into base64 format and transmits it to the portal. Since this method operates asynchronously, the ERP system receives a tracking ID (trackingId) without waiting for the full processing of the document. This prevents delays in ERP-side workflows, and the final status of the document can be queried later using the provided tracking ID.

Endpoint Information

PropertyValue
URL/invoice/send-document-async
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationJWT Token (R-Auth header) or API Key

Example Request

curl --location 'https://api-fr-stage.docnova.ai/invoice/send-document-async' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: {{jwt_token}}' \
--data-raw '{
"apiKey": "{{your_api_key}}",
"base64Document": "{{base64_encoded_xml}}",
"base64Pdf": "{{base64_encoded_pdf}}",
"businessType": "B2B",
"compId": "{{company_uuid}}",
"invoiceSource": "PORTAL",
"invoiceType": "ZUGFERD",
"receiverEmails": [
"recipient@example.com"
],
"mailTemplateId": "{{template_id}}"
}'

Request Parameters

FieldTypeRequiredDescription
compIdString (UUID)Conditional*Company unique identifier. Required if apiKey is not provided.
apiKeyStringConditional*API key. Required if compId is not provided.
base64DocumentStringConditional**Base64-encoded XML document. Required if base64Pdf is not provided.
base64PdfStringConditional**Base64-encoded PDF document. Required if base64Document is not provided.
invoiceTypeEnumConditional***Invoice format type. Required if waybillType is not provided.
waybillTypeEnumConditional***Waybill format type. Required if invoiceType is not provided.
businessTypeEnumNoBusiness model type (B2B, B2C, B2G).
invoiceSourceEnumNoDocument source.
receiverEmailsArray<String>NoList of recipient email addresses.
mailTemplateIdStringNoEmail template identifier.

Note:

  • (*) At least one of compId or apiKey must be provided.
  • (**) At least one of base64Document or base64Pdf must be provided.
  • (***) At least one of invoiceType or waybillType must be provided.

businessType Values

ValueDescription
B2BBusiness to Business
B2CBusiness to Consumer
B2GBusiness to Government

invoiceSource Values

ValueDescription
PORTALSubmission via web portal
PORTAL_OCRPortal with OCR processing
EMAILVia email
EMAIL_OCREmail with OCR processing
ERPERP system integration
PEPPOLVia Peppol network
LHDNMMalaysia LHDNM system
NEMHANDELDenmark NemHandel
SERVICEService integration
HARVESTHarvest integration
SHOPIFYShopify integration
AMAZON_SPAmazon SP-API integration
EBAYeBay integration
HUBSPOTHubSpot integration
ANAFRomania ANAF system
LAZADALazada integration
SFTPVia SFTP
KSEFPoland KSeF system
RS_APISerbia API
ETAEgypt ETA system
ERACUNIndonesia e-Racun
STRIPEStripe integration

invoiceType Values

ValueGroupDescription
PEPPOL_BISXRECHNUNGPeppol BIS 3.0 format
XRECHNUNGXRECHNUNGGerman XRechnung format
RO_EFACTURAXRECHNUNGRomania e-Factura format
ZUGFERDZUGFERDZUGFeRD format (PDF/A-3 with XML)
FACTUR_XZUGFERDFactur-X format (France)
XRECHNUNG_CIIZUGFERDXRechnung CII profile
CIIZUGFERDCross Industry Invoice format
CIDZUGFERDCID format
PDFZUGFERDPDF format
MY_INVOISCountry-SpecificMalaysia MyInvois format
MY_PINTCountry-SpecificMalaysia PINT format
DK_OIOUBLCountry-SpecificDenmark OIOUBL format
EG_INVOICECountry-SpecificEgypt e-Invoice format
HR_INVOICECountry-SpecificCroatia e-Invoice format
UAE_PINTCountry-SpecificUAE PINT format
KZ_ESF_V2KazakhstanKazakhstan ESF v2
KSEFPolandPoland KSeF format
KSEF_OFFLINEPolandPoland KSeF offline

waybillType Values

ValueDescription
RS_WAYBILL_DESPATCHSerbia despatch waybill
RS_WAYBILL_RECEIPTSerbia receipt waybill
RS_APPLICATION_RESPONSESerbia application response
RO_ETRANSPORTRomania e-Transport

Responses

200 - Successful Response

{
"trackingId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": "PENDING",
"message": "Document queued for processing"
}

Response Fields

FieldTypeDescription
trackingIdUUIDUnique process tracking identifier. This ID can be used to query the processing status.
statusEnumCurrent status of the process.
messageStringDescriptive message about the status.

status Values

ValueDescription
PENDINGProcess queued, not yet started
PROCESSINGProcess in progress
COMPLETEDProcess completed successfully
FAILEDProcess failed
SENDING_FAILEDSending failed
PERMANENT_FAILEDPermanent failure, will not be retried

400 - Bad Request

{
"trackingId": null,
"status": "FAILED",
"message": "Either invoiceType or waybillType must be provided"
}

401 - Unauthorized

{
"timestamp": "2026-01-29T10:30:00.000Z",
"status": 401,
"error": "Unauthorized",
"message": "Invalid or expired token"
}

500 - Internal Server Error

{
"trackingId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "FAILED",
"message": "An unexpected error occurred"
}

5. 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 /invoice/document-status/{trackingId} endpoint.

Endpoint Information

PropertyValue
URL/invoice/send-document-async-json
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/invoice/send-document-async-json' \
--header 'accept: */*' \
--header 'R-Auth: eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJNTU0iLCJzdWIiOiJsYmxyRWNuT2JZUVN3KzNtQ29yM1RJSGFLOFQ4UmlwTGlwai9QREtkVk9pNktPazNSOEhldEdES0FQNzJoQStwV00rZUJLREtLWmpZWXBEN1pzK3JCZz09IiwiY2xhaW0iOiJJU0dXSXIvb2F3elUrdnVPK1FleWx4UzUrL280NnhNR3lFdXE2ZDVyaEpuRjNVRW1xVFRya01uUTRzZng5ZmhQWklyOW1Qb3lIUVV4RnpYMU82WkpndkVoVkRoTElWV2F4L1JCNUVVY0xUaz0iLCJ1c2VyVHlwZSI6IkNMSUVOVCIsImV4cCI6MTc4MjIxNzIyMX0.gg4J1DZ8URY5DrFApiPZ81Pb_QmLMn9W16PppRA1dv7syxbmRQakPYs8w4Op-WVf64SgPtBDCaoNL1d2bZ3O0g' \
--header 'Content-Type: application/json' \
--data-raw '{
"apiKey": "tBhGHW7gREjwJ0AGcAK5GNO8pWORIjw4",
"businessType": "B2B",
"ublDto": {
"UBLVersionID": {
"Value": "2.1",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"CustomizationID": {
"Value": "urn:cen.eu:en16931:2017#compliant#urn:peppol:france:billing:cius:1.0::2.1",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"ProfileID": {
"Value": "B1",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"ID": {
"Value": "35000205577",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"IssueDate": {
"Value": "2025-01-17"
},
"DueDate": {
"Value": "2025-01-17"
},
"InvoiceTypeCode": {
"Value": "380",
"listAgencyID": "",
"listID": "",
"listVersionID": "",
"name": ""
},
"Note": [
{
"Value": "BANQUE POPULAIRE AUVERGNE RHÔNE ALPES IBAN : FR76 1680 7004 0082 0722 9721 667 SWIFT : CCBPFRPPGRE"
}
],
"TaxPointDate": {
"Value": "2026-06-17"
},
"DocumentCurrencyCode": {
"Value": "EUR",
"listAgencyID": "",
"listID": "",
"listVersionID": "",
"name": ""
},
"CompanyId": "b7844db0-57a1-4f5d-af65-...",
"Format": "EASY_INVOICE",
"Type": "FR_UBL_CIUS",
"ProfileType": "EN16931",
"IsPeppolParticipant": false,
"PeppolParticipantId": "",
"OrderReference": {
"ID": {
"Value": "969118",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"SalesOrderID": {
"Value": "0000969118",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
}
},
"AccountingSupplierParty": {
"Party": {
"EndpointID": {
"Value": "271688503",
"schemeID": "0002",
"schemeAgencyID": "",
"schemeAgencyName": ""
},
"PartyName": [
{
"Name": {
"Value": "Kerakoll France"
}
}
],
"PostalAddress": {
"StreetName": {
"Value": "Avenue de l'\''industrie"
},
"BuildingNumber": {
"Value": "25"
},
"CityName": {
"Value": "Corbas Cedex"
},
"PostalZone": {
"Value": "69964"
},
"Country": {
"IdentificationCode": {
"Value": "FR",
"listAgencyID": "",
"listID": "",
"listVersionID": ""
}
}
},
"PartyTaxScheme": [
{
"CompanyID": {
"Value": "FR99271688503",
"schemeID": "",
"schemeAgencyID": "",
"schemeAgencyName": ""
},
"TaxScheme": {
"ID": {
"Value": "VAT",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
}
}
}
],
"PartyLegalEntity": [
{
"RegistrationName": {
"Value": "Kerakoll France"
},
"CompanyID": {
"Value": "FR99271688503",
"schemeID": "",
"schemeAgencyID": "",
"schemeAgencyName": ""
},
"CompanyLegalForm": null
}
],
"Contact": {
"Name": {
"Value": "Kerakoll France"
},
"ElectronicMail": null,
"Telephone": null
}
}
},
"AccountingCustomerParty": {
"Party": {
"EndpointID": {
"Value": "142057869",
"schemeID": "0002",
"schemeAgencyID": "",
"schemeAgencyName": ""
},
"PartyName": [
{
"Name": {
"Value": "PLATTARD CARRELAGES-VILLEFRANCHE"
}
}
],
"PostalAddress": {
"StreetName": {
"Value": "3027008449225"
},
"AdditionalStreetName": null,
"CityName": {
"Value": "VILLEFRANCHE SUR SAONE"
},
"PostalZone": {
"Value": "69654"
},
"Country": {
"IdentificationCode": {
"Value": "FR",
"listAgencyID": "",
"listID": "",
"listVersionID": ""
}
}
},
"PartyTaxScheme": [
{
"CompanyID": {
"Value": "FR99142057869",
"schemeID": "",
"schemeAgencyID": "",
"schemeAgencyName": ""
},
"TaxScheme": {
"ID": {
"Value": "VAT",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
}
}
}
],
"PartyLegalEntity": [
{
"RegistrationName": {
"Value": "PLATTARD CARRELAGES-VILLEFRANCHE"
},
"CompanyID": null,
"CompanyLegalForm": null
}
],
"Contact": {
"Name": {
"Value": "PLATTARD CARRELAGES-VILLEFRANCHE"
},
"Telephone": {
"Value": "0478801221"
},
"ElectronicMail": {
"Value": "jeremy-gandois@plattard.com"
}
}
}
},
"PaymentMeans": [
{
"PaymentMeansCode": {
"Value": "42",
"listAgencyID": "",
"listID": "",
"listVersionID": "",
"name": ""
},
"PayeeFinancialAccount": null
}
],
"TaxTotal": [
{
"TaxAmount": {
"Value": "15.76",
"currencyID": "EUR"
},
"TaxSubtotal": [
{
"TaxableAmount": {
"Value": "78.81",
"currencyID": "EUR"
},
"TaxAmount": {
"Value": "15.76",
"currencyID": "EUR"
},
"TaxCategory": {
"ID": {
"Value": "S",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"Percent": {
"Value": "20",
"format": ""
},
"TaxScheme": {
"ID": {
"Value": "VAT",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
}
}
}
}
]
}
],
"LegalMonetaryTotal": {
"LineExtensionAmount": {
"Value": "78.81",
"currencyID": "EUR"
},
"TaxExclusiveAmount": {
"Value": "78.81",
"currencyID": "EUR"
},
"TaxInclusiveAmount": {
"Value": "94.57",
"currencyID": "EUR"
},
"AllowanceTotalAmount": {
"Value": "",
"currencyID": "EUR"
},
"ChargeTotalAmount": {
"Value": "",
"currencyID": "EUR"
},
"PrepaidAmount": {
"Value": "",
"currencyID": "EUR"
},
"PayableAmount": {
"Value": "94.57",
"currencyID": "EUR"
}
},
"InvoiceLine": [
{
"ID": {
"Value": "10",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"InvoicedQuantity": {
"Value": "12.000",
"unitCode": "KGM"
},
"LineExtensionAmount": {
"Value": 41.86,
"currencyID": "EUR"
},
"Item": {
"Name": {
"Value": "K0001E.01"
},
"Description": null,
"ClassifiedTaxCategory": [
{
"ID": {
"Value": "S",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"Percent": {
"Value": "20",
"format": ""
},
"TaxScheme": {
"ID": {
"Value": "VAT",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
}
}
}
]
},
"Price": {
"PriceAmount": {
"Value": "3.4883",
"currencyID": "EUR"
},
"BaseQuantity": null
}
},
{
"ID": {
"Value": "20",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"InvoicedQuantity": {
"Value": "12.000",
"unitCode": "KGM"
},
"LineExtensionAmount": {
"Value": 36.95,
"currencyID": "EUR"
},
"Item": {
"Name": {
"Value": "K0001I.01"
},
"Description": null,
"ClassifiedTaxCategory": [
{
"ID": {
"Value": "S",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
},
"Percent": {
"Value": "20",
"format": ""
},
"TaxScheme": {
"ID": {
"Value": "VAT",
"schemeAgencyID": "",
"schemeAgencyName": "",
"schemeID": ""
}
}
}
]
},
"Price": {
"PriceAmount": {
"Value": "3.0792",
"currencyID": "EUR"
},
"BaseQuantity": null
}
}
],
"BillingReference": null,
"AdditionalDocumentReference": null,
"AllowanceCharge": null,
"Delivery": null,
"BuyerReference": null,
"PartnerUuid": "e960da1f-4240-44d0-9070-...",
"DraftUuid": "",
"ExternalInvoiceId": "",
"InvoiceUuid": "",
"OcrUuid": "",
"LeitwegId": "",
"ehfNorwayForetaksregisteret": false,
"ehfNorwayPaymentAccountKind": "BBAN"
}
}
'

Request Parameters

Body Parameters


Root Object
Field NameTypeRequiredDescription
apiKeystringConditionalAPI key used to identify the company. Required if ublDto.CompanyId is not provided.
ublDtoobject (UBLDto)YesUBL 2.1 compliant invoice data structure containing all invoice details.
ublDto — Document Object
Field NameTypeRequiredDescription
ublDto.Typestring (enum)OptionalDocument format type. E.g.: PEPPOL_BIS, XRECHNUNG, ZUGFERD. See Parameter Values Reference table for full list.
ublDto.IsPeppolParticipantbooleanOptionalIndicates whether the recipient is registered on the Peppol network. If true, the document is routed via Peppol.
ublDto.CompanyIdstring (UUID)ConditionalUUID of the sending company. Required if apiKey is not provided.
ublDto.ProfileTypestring (enum)OptionalZUGFeRD / Factur-X profile type. Default: EN16931.
ublDto.CustomizationID.ValuestringOptionalInvoice customization identifier (urn value). Specifies PEPPOL / EN16931 compliance.
ublDto.ID.ValuestringOptionalInvoice number / unique document identifier.
ublDto.IssueDate.Valuestring (ISO 8601)OptionalInvoice issue date. Format: YYYY-MM-DD.
ublDto.DueDate.Valuestring (ISO 8601)OptionalInvoice due date. Format: YYYY-MM-DD.
ublDto.InvoiceTypeCode.ValuestringOptionalUN/CEFACT invoice type code. E.g.: 380 = Commercial Invoice, 381 = Credit Note, 384 = Corrected Invoice.
ublDto.Note[].ValuestringOptionalFree-text note attached to the invoice.
ublDto.DocumentCurrencyCode.ValuestringOptionalInvoice currency code (ISO 4217). E.g.: EUR, USD, GBP.
ublDto.BuyerReference.ValuestringOptionalBuyer reference number (Buyer Reference / Leitweg-ID).
ublDto.OrderReference.ID.ValuestringOptionalPurchase order number.
ublDto.OrderReference.SalesOrderID.ValuestringOptionalSales order number.
ublDto.AccountingSupplierPartyobjectOptionalSupplier / seller information. The Party object contains EndpointID (Peppol ID), PartyName, PostalAddress, PartyTaxScheme, PartyLegalEntity, and Contact sub-objects.
ublDto.AccountingSupplierParty.Party.EndpointID.ValuestringOptionalSupplier's Peppol Endpoint ID value.
ublDto.AccountingSupplierParty.Party.EndpointID.schemeIDstringOptionalEndpoint ID scheme code. E.g.: 9930 = German Tax No, 0088 = GLN.
ublDto.AccountingCustomerPartyobjectOptionalCustomer / buyer information. The Party object contains EndpointID, PartyName, PostalAddress, PartyTaxScheme, PartyLegalEntity, and Contact sub-objects.
ublDto.Delivery[].ActualDeliveryDate.Valuestring (ISO 8601)OptionalActual delivery date. Format: YYYY-MM-DD.
ublDto.Delivery[].DeliveryLocation.AddressobjectOptionalDelivery address. Contains StreetName, CityName, PostalZone, and Country sub-fields.
ublDto.PaymentMeans[].PaymentMeansCode.ValuestringOptionalPayment method code. E.g.: 58 = SEPA Credit Transfer, 30 = Credit Transfer, 49 = Direct Debit.
ublDto.PaymentMeans[].PayeeFinancialAccount.ID.ValuestringOptionalPayee bank account IBAN number.
ublDto.PaymentMeans[].PayeeFinancialAccount.Name.ValuestringOptionalBank account holder name.
ublDto.PaymentTerms[].Note[].ValuestringOptionalFree-text description of payment terms.
ublDto.TaxTotal[].TaxAmount.ValuenumberOptionalTotal tax amount.
ublDto.TaxTotal[].TaxAmount.currencyIDstringOptionalCurrency code for the tax amount (ISO 4217).
ublDto.TaxTotal[].TaxSubtotal[].TaxableAmount.ValuenumberOptionalTaxable base amount.
ublDto.TaxTotal[].TaxSubtotal[].TaxCategory.ID.ValuestringOptionalTax category code. E.g.: S = Standard, Z = Zero Rated, E = Exempt, AE = Reverse Charge.
ublDto.TaxTotal[].TaxSubtotal[].TaxCategory.Percent.ValuenumberOptionalTax rate percentage. E.g.: 19, 7, 10.
ublDto.LegalMonetaryTotal.LineExtensionAmount.ValuenumberOptionalSum of invoice line net amounts (excluding tax).
ublDto.LegalMonetaryTotal.TaxExclusiveAmount.ValuenumberOptionalTotal amount excluding VAT.
ublDto.LegalMonetaryTotal.TaxInclusiveAmount.ValuenumberOptionalTotal amount including VAT.
ublDto.LegalMonetaryTotal.PayableAmount.ValuenumberOptionalNet payable amount.
ublDto.InvoiceLine[].ID.ValuestringOptionalInvoice line sequence number.
ublDto.InvoiceLine[].InvoicedQuantity.ValuenumberOptionalInvoiced quantity.
ublDto.InvoiceLine[].InvoicedQuantity.unitCodestringOptionalUnit of measure code (UN/ECE Rec. 20). E.g.: MTQ = Cubic Metre, C62 = Each, KGM = Kilogram.
ublDto.InvoiceLine[].LineExtensionAmount.ValuenumberOptionalInvoice line net amount (excluding tax).
ublDto.InvoiceLine[].Item.Name.ValuestringOptionalProduct / service name.
ublDto.InvoiceLine[].Item.SellersItemIdentification.ID.ValuestringOptionalSeller's item/product code.
ublDto.InvoiceLine[].Price.PriceAmount.ValuenumberOptionalUnit price.
ublDto.InvoiceLine[].Price.BaseQuantity.ValuenumberOptionalBase quantity the price applies to. Typically 1.
receiverEmailsarray (string)OptionalRecipient email addresses for sending the invoice via email after processing.
mailTemplateIdstringOptionalCustom mail template ID to be used for email delivery.
businessTypestring (enum)OptionalBusiness model type: B2B, B2C, or B2G.

Notes:

  • At least one of apiKey or ublDto.CompanyId must be provided. Both cannot be null simultaneously.
  • When ublDto.CompanyId is not provided, the system resolves the company via the apiKey.
  • For AccountingSupplierParty and AccountingCustomerParty, the EndpointID.schemeID uses Peppol Participant Identifier Scheme codes (e.g.: 9930 = German Tax No, 0088 = GLN, 0184 = Danish CVR).
  • InvoiceLine[].InvoicedQuantity.unitCode uses UN/ECE Recommendation 20 unit codes (e.g.: MTQ = Cubic Metre, C62 = Each, KGM = Kilogram, LTR = Litre).

Responses

200 - Successful Response

Request accepted successfully. The document has been placed in the processing queue. Use the returned trackingId to query processing status at /invoice/document-status/{trackingId}.

Response body (AsyncERPResponse)

{
"trackingId": "{{entity_uuid}}",
"status": "PENDING",
"message": "Document process started successfully"
}

Response Fields

FieldTypeDescription
trackingIdstring (UUID)Document processing tracking ID. Used in the /invoice/document-status/{trackingId} endpoint.
statusstring (enum)Immediate processing status of the document. Returns PENDING initially.
messagestringInformational message about the process initiation.

Parameter Value Reference

Document Format Type (ublDto.Type)

ValueDescription
PEPPOL_BISPEPPOL BIS Billing 3.0 format (UBL-based)
XRECHNUNGGermany XRechnung format (UBL-based)
ZUGFERDZUGFeRD format (PDF/A-3 + embedded XML)
FACTUR_XFrance Factur-X format (PDF/A-3 + embedded XML)
XRECHNUNG_CIIGermany XRechnung CII format
CIIUN/CEFACT Cross Industry Invoice format
CIDCross Industry Document format
MY_INVOISMalaysia MyInvois format
MY_PINTMalaysia PINT format
DK_OIOUBLDenmark OIOUBL format
RO_EFACTURARomania e-Invoice format
UAE_PINTUAE PINT format
HR_INVOICECroatia invoice format
EG_INVOICEEgypt invoice format
KSEFPoland KSeF format

Profile Type (ublDto.ProfileType)

ValueDescription
EN16931EN 16931 compliant profile (default)
EXTENDEDExtended profile
BASICBasic profile

Business Model Type (businessType)

ValueDescription
B2BBusiness to Business
B2CBusiness to Consumer
B2GBusiness to Government

400 - Bad Request

Trigger: When both apiKey and ublDto.CompanyId are null.

Response body:

{
"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"
}

An IllegalArgumentException is thrown when both apiKey and ublDto.CompanyId are null, returning a 400 Bad Request response.

Trigger: When the provided apiKey does not match any record in the system.

Response body:

{
"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"
}

An IllegalArgumentException is thrown when the apiKey provided does not match any registered company, returning a 400 Bad Request response.

401 - Unauthorized

Trigger: When the JWT token is invalid or expired, or the user is not authorized for the specified company.

Response body:

{
"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"
}

An AuthorizationServiceException is thrown when the JWT token in the R-Auth header is invalid/expired or when the authenticated user does not have access to the specified company, returning a 401 Unauthorized response.

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/send-document-async-json"
}

Returns a 500 Internal Server Error when an unexpected server-side error occurs.

6. 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

PropertyValue
URL/invoice/document-status/{trackingId}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/invoice/document-status/{trackingId}' \ 
--header 'Accept: */*' \
--header 'R-Auth: {JWT_TOKEN}'
}'

Request Parameters

Path Parameters

FieldTypeRequiredDescription
trackingIdUUIDYesThe tracking identifier returned from an asynchronous document submission. This is the trackingId value included in the response of send-document-async, send-document-async-json, send-by-file-async, or send-portal-new-async endpoints.

Responses

200 - Successful Response

{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "FR_UBL_CIUS",
"waybillType": null,
"source": "ERP",
"target": null,
"status": "COMPLETED",
"filename": "invoice_2025.xml",
"invoiceNumber": "INV-2025-001234",
"documentId": "f47ac10b-58cc-4372-a567-...",
"sendingResult": "SUCCESS",
"errorType": null,
"errors": null,
"additionalData": null,
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:45",
"completedAt": "2025-06-15T10:30:45"
}

Success Response Field Descriptions

FieldTypeDescription
trackingIdUUIDUnique tracking identifier for the document processing
companyIdUUIDUnique identifier of the company the document belongs to
directionString (Enum)Document direction: INCOMING or OUTGOING
documentTypeString (Enum)Document format (e.g., XRECHNUNG, UBL, ZUGFERD)
waybillTypeString (Enum)Waybill type. Only populated for waybill operations
sourceString (Enum)Source platform the document was submitted from (e.g., ERP, PORTAL)
targetString (Enum) | nullTarget platform for the document
statusString (Enum)Current processing status: PENDING, PROCESSING, COMPLETED, FAILED, SENDING_FAILED, PERMANENT_FAILED
filenameStringName of the processed file
invoiceNumberString | nullInvoice number assigned to the document. Populated when processing completes
documentIdUUID | nullUnique system identifier of the created document. Populated when processing completes
sendingResultString | nullSending result (e.g., SUCCESS, SENT_TO_PEPPOL). Populated when processing completes
errorTypeString (Enum) | nullError category when an error occurs. Null for successful operations
errorsObject | nullError details. Variable type: can be List<ValidationError>, List<String>, or String
additionalDataObjectCountry specific additional metadata. Structure varies by country/document type (e.g., Poland KSeF: ksefNumber, Romania: submissionId)
createdAtDateTimeTimestamp when the processing record was created (ISO 8601)
statusUpdatedAtDateTimeTimestamp when the status was last updated (ISO 8601)
completedAtDateTime | nullTimestamp when processing completed. Null while processing is ongoing

Parameter Value Reference

DocumentProcessStatus — Possible Status Values

ValueDescription
PENDINGDocument is queued, processing has not started yet
PROCESSINGDocument is actively being processed (conversion, validation, sending, etc.)
COMPLETEDDocument processing completed successfully
FAILEDAn error occurred during document processing (may be retried)
SENDING_FAILEDDocument was created but failed during the sending phase
PERMANENT_FAILEDDocument processing permanently failed (will not be retried)

DocumentType — Document Direction

ValueDescription
INCOMINGIncoming document
OUTGOINGOutgoing document

DataType — Document Format

ValueDescription
PEPPOL_BISPeppol BIS 3.0 UBL format
XRECHNUNGXRechnung (Germany) UBL format
RO_EFACTURARomania eFactura format
MY_INVOISMalaysia MyInvois format
MY_PINTMalaysia PINT format
DK_OIOUBLDenmark OIOUBL format
EG_INVOICEEgypt e-Invoice format
HR_INVOICECroatia e-Invoice format
UAE_PINTUAE PINT format
ZUGFERDZUGFeRD format
FACTUR_XFactur-X (France) format
XRECHNUNG_CIIXRechnung CII format
CIIUN/CEFACT CII format
PDFUnstructured PDF (paper invoices, images, etc.)
KSEFPoland KSeF format
KSEF_OFFLINEPoland KSeF Offline format
KZ_ESF_V2Kazakhstan ESF v2 format

InvoiceSource — Document Source

ValueDescription
ERPSubmitted via ERP integration
PORTALSubmitted via web portal
PEPPOLReceived via Peppol network
EMAILReceived via email
SFTPTransferred via SFTP
KSEFVia KSeF system
ANAFVia ANAF system (Romania)
ERACUNVia eRacun system (Croatia)
OthersPORTAL_OCR, EMAIL_OCR, LHDNM, NEMHANDEL, SERVICE, HARVEST, SHOPIFY, AMAZON_SP, EBAY, HUBSPOT, LAZADA, RS_API, ETA, STRIPE

WaybillDataType — Waybill Type

ValueDescription
RS_WAYBILL_DESPATCHSerbia despatch waybill
RS_WAYBILL_RECEIPTSerbia receipt waybill
RS_APPLICATION_RESPONSESerbia application response
RO_ETRANSPORTRomania eTransport waybill

ErrorType — Error Types Specific to This Endpoint

ValueMessage
INVOICE_PROCESS_NOT_FOUNDTracking ID not found
VALIDATION_FAILEDValidation failed!
INVOICE_NULL_COULD_NOT_SAVEInvoice is NULL and/or could not be saved!
ZUGFERD_VALIDATION_ERRORZUGFeRD validation error
INVOICE_CREATION_FAILEDInvoice creation failed!
INVOICE_SENDING_FAILEDInvoice sending failed: {details}

401 - Unauthorized

Returned when the R-Auth header is missing, contains an invalid JWT token, or the token has expired.

{
"status": 401,
"error": "Unauthorized",
"message": "Full authentication is required to access this resource"
}
DetailDescription
HTTP Status401 Unauthorized
TriggerJWT token is missing, malformed, expired, or signature verification failed
ResolutionSend a valid, non-expired JWT token in the R-Auth header

404 - Not Found

Returned when the provided trackingId does not exist in the database.
Response Body: null (body is empty)

DetailDescription
HTTP Status404 Not Found
Response Bodynull (body is empty)
TriggerNo DocumentProcessEntity record matches the given trackingId in the database
Internal Error TypeINVOICE_PROCESS_NOT_FOUND — "Tracking ID not found"
ResolutionVerify the trackingId value is correct. Use the value returned in the response of the async submission endpoint

500 - Internal Server Error

Returned when an unexpected server error occurs during the status query.
Response Body: null (body is empty)

DetailDescription
HTTP Status500 Internal Server Error
Response Bodynull (body is empty)
TriggerDatabase connection failure, entity conversion error, or other unexpected runtime exceptions
ResolutionCheck server logs. Contact the support team if the issue persists

Status-Based Response Examples

PENDING — Queued for Processing


{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": null,
"documentType": "XRECHNUNG",
"status": "PENDING",
"documentId": null,
"invoiceNumber": null,
"sendingResult": null,
"errorType": null,
"errors": null,
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:00",
"completedAt": null
}

PROCESSING — Currently Processing

{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "XRECHNUNG",
"status": "PROCESSING",
"documentId": "f47ac10b-58cc-4372-a567-...",
"invoiceNumber": "INV-2025-001234",
"sendingResult": null,
"errorType": null,
"errors": null,
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:20",
"completedAt": null
}

FAILED — Processing Failed (Validation Error)


{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": null,
"documentType": "ZUGFERD",
"status": "FAILED",
"documentId": null,
"invoiceNumber": null,
"sendingResult": null,
"errorType": "VALIDATION_FAILED",
"errors": [
{
"field": "invoiceNumber",
"message": "Invoice number is required"
},
{
"field": "issueDate",
"message": "Issue date format is invalid"
}
],
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:15",
"completedAt": "2025-06-15T10:30:15"

}

FAILED — Processing Failed (General Error)

{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "XRECHNUNG",
"status": "FAILED",
"documentId": null,
"invoiceNumber": null,
"sendingResult": null,
"errorType": "INVOICE_NULL_COULD_NOT_SAVE",
"errors": [
"Invoice is NULL and/or could not be saved! XML parsing error at line 42"
],
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:30:12",
"completedAt": "2025-06-15T10:30:12"
}

SENDING_FAILED — Sending Failed

{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "PEPPOL_BIS",
"status": "SENDING_FAILED",
"documentId": "f47ac10b-58cc-4372-a567-...",
"invoiceNumber": "INV-2025-001234",
"sendingResult": null,
"errorType": "INVOICE_SENDING_FAILED",
"errors": [
"Invoice sending failed: Peppol access point unreachable"
],
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:31:00",
"completedAt": "2025-06-15T10:31:00"
}

COMPLETED — With Country-Specific Metadata (Poland KSeF)

{
"trackingId": "e20a112a-fcb2-4da2-9efd-...",
"companyId": "a1b2c3d4-e5f6-7890-abcd-...",
"direction": "OUTGOING",
"documentType": "KSEF",
"status": "COMPLETED",
"documentId": "f47ac10b-58cc-4372-a567-...",
"invoiceNumber": "FA/2025/06/001",
"sendingResult": "SUCCESS",
"errorType": null,
"errors": null,
"additionalData": {
"sessionReferenceNumber": "20250615-SE-ABC123",
"invoiceReferenceNumber": "20250615-IR-DEF456",
"ksefNumber": "1234567890-20250615-..."
},
"createdAt": "2025-06-15T10:30:00",
"statusUpdatedAt": "2025-06-15T10:31:30",
"completedAt": "2025-06-15T10:31:30"

}

7. Get Invoice/Document Status GET

Purpose of Use: This endpoint is used to query the real-time processing status of an invoice/document by using the trackingId returned from an asynchronous document submission request.

After an invoice or document is submitted through an async flow, the first response may only contain a trackingId. This endpoint allows the client to follow the internal processing lifecycle of that document, including whether it is queued, processing, failed, or completed.

Once a documentId has been assigned to the document, this endpoint also returns invoice-level status information such as invoiceStatus and invoiceStatusDate. If the document has not yet been assigned a final documentId, those fields may be null, and only the process-level status fields should be used.

The request requires that the authenticated user in the R-Auth JWT has authority over the queried companyId.


Endpoint Information

PropertyValue
URL/invoice/get-document-status-by-tracking
MethodGET
Content-TypeNone — query parameters only, no request body
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth: {{jwt_token}}

Example Request

curl -X GET 'https://api-fr-stage.docnova.ai/invoice/get-document-status-by-tracking?companyId={{company_uuid}}&trackingId={{tracking_uuid}}' \
-H 'accept: */*' \
-H 'R-Auth: {{jwt_token}}'

Request Parameters

FieldTypeRequiredDescription
companyIdString (UUID)YesUnique identifier of the company that the queried tracking record belongs to. The requesting user must hold a role in this company.
trackingIdString (UUID)YesThe tracking identifier returned in the response of the document's asynchronous submission request. The document status is looked up via this identifier.

Notes

  • The R-Auth header is mandatory.
  • The user in the JWT must have a role in the company matching companyId.
  • If trackingId is not associated with companyId, for example when trying to access a record belonging to another company, a 401 Unauthorized response is returned.
  • If the tracking process is found but no documentId has been assigned yet, only the process-level status fields are returned.

Responses


200 - Successful Response

{
"trackingId": "{{tracking_uuid}}",
"documentId": "{{document_uuid}}",
"invoiceStatus": "SENT_TO_PEPPOL",
"invoiceStatusDate": "2026-01-15T12:00:00",
"processStatus": "COMPLETED",
"processStatusUpdatedAt": "2026-01-15T12:00:00"
}

Description: Request succeeded. If the document has not yet been assigned a documentId, the documentId, invoiceStatus, and invoiceStatusDate fields are null, and only processStatus / processStatusUpdatedAt are meaningful.

Response Fields

FieldTypeDescription
trackingIdString (UUID)Echoes the trackingId sent in the request. Always populated.
documentIdString (UUID)Populated once the document is assigned a final ID. null if the document has not yet been assigned.
invoiceStatusString (Enum)Populated once documentId is assigned. Contains the invoice's country/channel-specific final status. null if documentId is not yet assigned.
invoiceStatusDateString (ISO 8601)Timestamp of the last update to invoiceStatus. null if documentId is not yet assigned.
processStatusString (Enum)Status of the document's own processing pipeline. Always populated, even before documentId is assigned.
processStatusUpdatedAtString (ISO 8601)Timestamp of the last update to processStatus. Always populated.

Parameter Values Reference Table

processStatus Values
ValueDescription
PENDINGProcess has not started yet; queued.
PROCESSINGDocument is currently being processed.
FAILEDProcessing failed; may be retried.
SENDING_FAILEDAn error occurred during the sending stage.
PERMANENT_FAILEDPermanent failure; will not be retried.
COMPLETEDProcess completed successfully.
invoiceStatus Values
ValueDescription
CREATEDInvoice/document has been created.
SAVED_AS_UBLSaved in UBL format.
SAVED_AS_ZUGFERDSaved in ZUGFeRD format.
SAVED_AS_FACTUR_XSaved in Factur-X format.
SAVED_AS_CIISaved in CII format.
SAVED_AS_CIDSaved in CID format.
READY_FOR_KSEFReady for submission to KSeF in Poland.
SENT_TO_ACCESS_POINTSent to the Access Point.
OCR_WAITINGWaiting for OCR processing.
OCR_PARSEDSuccessfully parsed by OCR.
OCR_FAILEDOCR processing failed.
OCR_PARSED_PENDING_PAYMENTOCR completed, awaiting payment.
OCR_WAITING_TOKENWaiting for a token for OCR.
CANCELEDCanceled.
PENDINGPending.
SAVED_AS_PDFSaved as PDF.
DELETEDDeleted.
COMPLETED_BY_MELA_AICompleted by Mela AI.
SENT_VIA_EMAILSent via email.
SENT_VIA_SFTPSent via SFTP.
SENT_TO_PEPPOLSent to the Peppol network.
SUCCESSOperation succeeded.
INVALID_PARAMETERSInvalid parameters.
TRANSPORT_ERRORPeppol transport error; no automatic retry.
TRANSPORT_ERROR_NO_RETRYPeppol transport error; retry disabled.
NO_SIGNAL_MESSAGE_RECEIVEDNo signal message received.
AS4_ERROR_MESSAGE_RECEIVEDAS4 error message received.
INVALID_SIGNAL_MESSAGE_RECEIVEDInvalid signal message received.
SMP_LOOKUP_FAILEDSMP lookup failed.
CREDIT_BLOCKEDPayment blocked due to credit limit.
France invoiceStatus Values
ValueDescription
FR_DEPOSITEDDeposited to PPF in France.
FR_REJECTEDRejected by PPF.
FR_RECEIVEDReceived by PPF.
FR_AVAILABLEAvailable in PPF.
FR_PROCESSINGProcessing in PPF.
FR_APPROVEDApproved by PPF.
FR_PARTIALLY_APPROVEDPartially approved by PPF.
FR_DISPUTEDDisputed in PPF.
FR_SUSPENDEDSuspended in PPF.
FR_PLATFORM_ISSUEDIssued by the platform in France.
FR_REFUSEDRefused by PPF.
FR_PAYMENT_SENTPayment sent in France.
FR_COLLECTEDPayment collected in France.
FR_COMPLETEDFrance process completed.
FR_CANCELLEDCancelled in the France process.

All error responses share the following structure:

{
"errorMessage": "<human-readable message>",
"errorType": "<error type key>",
"errorTitle": "<HTTP status name>",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/get-document-status-by-tracking"
}

400 - Bad Request

Tracking ID Not Found

{
"errorMessage": "Tracking ID not found",
"errorType": "INVOICE_PROCESS_NOT_FOUND",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/get-document-status-by-tracking"
}

Description: An ApiError(INVOICE_PROCESS_NOT_FOUND) is thrown when the trackingId is not found in the database.

Note: Although Swagger annotation documents this case as 404, the code currently calls withStatus() on this exception, so RestExceptionHandler returns the default 400 Bad Request.

401 - Unauthorized

{
"errorMessage": "User is not authorized for this operation",
"errorType": "AUTHORIZATION_FAILED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "{{correlation_id}}",
"timestamp": "2026-01-15T12:00:00",
"path": "/invoice/get-document-status-by-tracking"
}

Trigger: The user in the R-Auth JWT has no role or authority in the given companyId, or the trackingId belongs to a different company than the given companyId.

500 - Internal 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/get-document-status-by-tracking"
}

Trigger: An unexpected server-side error occurs.

This may happen because of a database connectivity issue, an unhandled exception, or another server-side runtime error.

8. Retrieve Doc by ID and Type GET

Purpose of Use: The GET /invoice/get-document/{documentId}/{documentTypes} endpoint allows downloading a previously stored invoice or document in a specific format such as PDF, XML, or JSON.

The client provides the document UUID (documentId) and the desired output format (documentTypes). The API returns the document content as Base64 encoded data. This is mainly used in ERP integrations to programmatically fetch, view, archive, or store invoice documents.

When the requested format is pdf, the API returns the printable or viewable PDF file content as Base64 encoded data.

Endpoint Information

PropertyValue
URL/invoice/get-document//{documentTypes}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/invoice/get-document/{documentId}/pdf' \
--header 'Accept: */*' \
--header 'R-Auth: {auth-token}'
}'

Request Parameters

Path Parameters

Field NameTypeRequiredDescription
documentIdString (UUID)YesUnique identifier of the document. Must be in UUID v4 format. Example: 550e8400-e29b-41d4-a716-...
documentTypesString (Enum)YesRequested document format type. Multiple types can be separated by hyphen -. Example: PDF, XML

Header Parameters

Field NameTypeRequiredDescription
R-AuthString (JWT)YesAuthentication token. JWT signed with HS512 algorithm.
AcceptStringNoAccepted response media type. Default: /

documentTypes Parameter Values

ValueFormat TypeDescription
PDFFormatType.PDFReturns Base64-encoded PDF representation of the invoice
XMLFormatType.XMLReturns Base64-encoded UBL XML content of the invoice
JSONFormatType.JSONReturns Base64-encoded UBL DTO JSON content of the invoice
PDF-XMLMultiple formatsMultiple formats can be requested simultaneously using hyphen separator
XML-PDF-JSONMultiple formatsAll three formats can be requested at once

Note: JSON format is only supported for invoices processed by OCR (OCR_PARSED) or completed by MelAI (COMPLETED_BY_MELAI_AI).

Responses

200 - Successful Response

{
"documents": [
{
"file_type": "PDF",
"data": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC..."
}
]
}

Successful Response Field Descriptions

Field NameTypeDescription
documentsList<Document>List of documents in requested formats. Contains one Document object per format.
documents[].file_typeString (Enum)Document format type. Possible values: PDF, XML, JSON
documents[].dataString (Base64)Base64-encoded content of the document. When decoded for PDF, produces a valid PDF file.

Multi-Format Response Example

{
"documents": [
{
"file_type": "XML",
"data": "PD94bWwgdmVy... (base64)"
},
{
"file_type": "PDF",
"data": "JVBERi0xLjQK... (base64)"
}
]
}

400 - Bad Request

Returned when an invalid documentTypes value is provided.


{

"errorMessage": "Unsupported document type: DOCX",
"errorType": "INVALID_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-def456",
"status": 400,
"timestamp": "2026-02-11T14:31:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../docx"
}

FieldDescription
errorMessageSpecifies the unsupported document type and which type was invalid.
errorTypeINVALID_ARGUMENT An invalid parameter was provided.
status400

400 - Bad Request

Returned when the document's OCR processing has not yet completed (waiting state).

{
"errorMessage": "Invoice is waiting for MelaAIParser. Please try again later",
"errorType": "INVALID_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-ghi789",
"status": 400,
"timestamp": "2026-02-11T14:32:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../json"
}

FieldDescription
errorMessageIndicates the invoice has not been processed by MelaAI yet and should be retried later.
errorTypeINVALID_ARGUMENT The invoice is not in a processable state currently.
status400

401 - Unauthorized

Returned when an invalid or missing R-Auth token is provided.


{
"errorMessage": "Authentication is required. Please complete the authentication process.",
"errorType": "AUTHENTICATION_REQUIRED",
"errorTitle": "UNAUTHORIZED",
"errorId": "corr-abc123",
"status": 401,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../pdf"
}

FieldDescription
errorMessageIndicates that the authentication process must be completed.
errorTypeAUTHENTICATION_REQUIRED Token is missing, expired, or invalid.
status401

404 - Not Found

Returned when no document matches the provided UUID. Specifically occurs when JSON format is requested and the invoice is not found.

{
"errorMessage": "af6e8982-b791-4704-bc06-d4655faa4b4c Invoice not found!",
"errorType": "NOT_FOUND_INVOICE",
"errorTitle": "NOT_FOUND",
"errorId": "corr-jkl012",
"status": 404,
"timestamp": "2026-02-11T14:33:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../json"
}

FieldDescription
errorMessageReturns a not found message along with the document UUID.
errorTypeNOT_FOUND_INVOICE No matching invoice record exists in the database.
status404

500 - Internal Server Error

Returned when an unexpected error occurs (e.g., file cannot be retrieved from S3, PDF conversion fails).

{ 

"errorMessage": "Internal server error",
"errorType": "SERVER_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "corr-mno345",
"status": 500,
"timestamp": "2026-02-11T14:34:00",
"path": "/invoice/get-document/af6e8982-b791-4704-bc06-.../pdf"
}
FieldDescription
errorMessageGeneric server error message.
errorTypeSERVER_ERROR An unexpected error occurred.
status500

Common Error Response Field Descriptions

Field NameTypeDescription
errorMessageStringHuman readable description of the error
errorTypeStringProgrammatic classification code of the error
errorTitleString (HttpStatus)Text representation of the HTTP status code
errorIdStringRequest correlation ID (for log tracking)
statusIntegerHTTP status code (numeric)
timestampString (ISO 8601)Timestamp when the error occurred
pathStringEndpoint path where the error occurred
detailsMap<String, Object>Additional error details (if available)
validationErrorsList<ValidationError>List of validation errors (if available)

9. Search Document with Filter 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 filtering criteria.

This API enables users to list documents associated with their company by applying filters such as date range, document direction (incoming or outgoing), invoice status, and document format (ZUGFERD, XRECHNUNG, etc.). Results are returned with pagination support, and each page includes the total document count, tax exclusive total amount, and tax inclusive total amount.

Endpoint Information

PropertyValue
URL/invoice/search-documents
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

{ 
curl --location 'https://api-fr-stage.docnova.ai/invoice/search-documents' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"companyId": "<COMPANY_UUID>",
"documentType": "OUTGOING",
"endDate": "2026-01-31",
"page": 0,
"size": 10,
"startDate": "2026-01-01",
"status": "SAVED_AS_ZUGFERD",
"type": "ZUGFERD"
}'
}

Request Parameters

FieldTypeRequiredDescription
companyIdUUIDYesUnique identifier of the company to search documents for
documentTypeString (Enum)NoDocument direction filter. Used to filter incoming or outgoing documents
statusString (Enum)NoInvoice status filter. Returns invoices in a specific status
typeString (Enum)NoDocument format type filter. Filters by invoice format
startDateString (ISO Date)NoSearch start date. Format: YYYY-MM-DD
endDateString (ISO Date)NoSearch end date. Format: YYYY-MM-DD
tinStringNoTax Identification Number filter
uitStringNoUIT identifier filter
referenceDocumentStringNoSearch by reference document number
pageIntegerNoPage number (0-based). Default: 0
sizeIntegerNoNumber of records per page. Default: 50

Parameter Values

documentType Values

ValueDescription
INCOMINGIncoming documents (invoices sent by suppliers)
OUTGOINGOutgoing documents (invoices sent to customers)

type Values

ValueGroupDescription
MY_INVOISMY_INVOISMalaysian MyInvois format
MY_PINTMY_PINTMalaysian PINT format
DK_OIOUBLDK_OIOUBLDanish OIOUBL format
EG_INVOICEEG_INVOICEEgyptian e-Invoice format
HR_INVOICEHR_INVOICECroatian eRacun format
UAE_PINTUAE_PINTUAE PINT format
ZUGFERDZUGFERDZUGFeRD format (PDF + embedded XML)
FACTUR_XZUGFERDFrench Factur-X format
XRECHNUNG_CIIZUGFERDXRechnung CII format
CIIZUGFERDUN/CEFACT CII format
CIDZUGFERDCID format
PDFZUGFERDUnstructured invoices (paper, images, etc.)
KSEFKSEFPolish KSeF format
KSEF_OFFLINEKSEF_OFFLINEPolish KSeF offline format
KZ_ESF_V2KZ_ESF_V2Kazakhstan e-Invoice v2 format

Note: When using the type filter on the search-documents endpoint, only XRECHNUNG, ZUGFERD, and FACTUR_X values actively filter results. Other values return an empty result set.

status Values

CategoryValueDescription
GeneralCREATEDInvoice created
PENDINGAwaiting processing
CANCELEDCancelled
DELETEDDeleted
SENT_VIA_EMAILSent via email
SavedSAVED_AS_UBLSaved as UBL
SAVED_AS_ZUGFERDSaved as ZUGFeRD
SAVED_AS_FACTUR_XSaved as Factur-X
SAVED_AS_CIISaved as CII
SAVED_AS_CIDSaved as CID
SAVED_AS_KSEFSaved as KSeF
SAVED_AS_PDFSaved as PDF
OCROCR_WAITINGOCR processing pending
OCR_PARSEDOCR completed successfully
OCR_FAILEDOCR processing failed
OCR_PARSED_PENDING_PAYMENTOCR completed, payment pending
OCR_WAITING_TOKENOCR waiting for token
COMPLETED_BY_MELA_AICompleted by Mela AI
PeppolSENT_TO_PEPPOLSent to Peppol network
SENT_TO_ACCESS_POINTSent to Access Point
SUCCESSSuccessfully delivered
TRANSPORT_ERRORTransport error
INVALID_PARAMETERSInvalid parameters
NO_SIGNAL_MESSAGE_RECEIVEDNo signal message received
AS4_ERROR_MESSAGE_RECEIVEDAS4 error message received
INVALID_SIGNAL_MESSAGE_RECEIVEDInvalid signal message received
INCOMING_RESPONSE_ACKNOWLEDGEDIncoming response acknowledged (MLR/MLS)
INCOMING_RESPONSE_REJECTEDIncoming response rejected
INCOMING_RESPONSE_ACCEPTEDIncoming response accepted
OUTGOING_RESPONSE_ACKNOWLEDGEDOutgoing response acknowledged (MLR/MLS)
OUTGOING_RESPONSE_REJECTEDOutgoing response rejected
OUTGOING_RESPONSE_ACCEPTEDOutgoing response accepted
Romania (ANAF)SENT_TO_ANAFSent to ANAF
PORTAL_OKAYPortal approved
PORTAL_ERRORPortal error
PORTAL_ERRORSPortal multiple errors
PORTAL_SYSTEM_ERRORPortal system error
PORTAL_IN_PROCESSPortal processing
Poland (KSeF)KSEF_PENDINGKSeF processing
KSEF_ACCEPTEDKSeF accepted
KSEF_REJECTEDKSeF rejected
KSEF_DUPLICATEKSeF duplicate record
Malaysia (LHDNM)LHDNM_SUBMITTEDSubmitted to LHDNM
LHDNM_VALIDLHDNM valid
LHDNM_INVALIDLHDNM invalid
LHDNM_CANCELLEDLHDNM cancelled
LHDNM_REJECT_REQUESTEDLHDNM rejection requested
LHDNM_REJECTEDLHDNM rejected
LHDNM_ERRORLHDNM error
Egypt (ETA)ETA_SUBMITTEDSubmitted to ETA
Croatia (eRacun)ERACUN_ERROReRacun error
ERACUN_PENDINGeRacun pending
ERACUN_WAITING_TO_SENDeRacun waiting to send
ERACUN_SENTeRacun sent
ERACUN_RECEIVEDeRacun received
ERACUN_APPROVEDeRacun approved
ERACUN_REJECTEDeRacun rejected
ERACUN_FULLY_PAIDeRacun fully paid
ERACUN_PARTIALLY_PAIDeRacun partially paid
ERACUN_DELIVERY_FAILEDeRacun delivery failed
DenmarkSENT_TO_NEMHANDELSent to Nemhandel
OtherCREDIT_BLOCKEDCredit blocked (returns masked data)

Responses

200 - Successful Response

{ 
"totalCount": 2,
"netTotal": 1500.00,
"total": 1785.00,
"invoiceList": [
{
{
"id": "a1b2c3d4-e5f6-7890-abcd-...",
"companyId": "60ccd1a7-5348-47b2-9ef6-...",
"userId": "user-uuid",
"customerName": "Muster GmbH",
"supplierName": "Lieferant AG",
"supplierId": "supplier-uuid",
"supplierVat": "DE123456789",
"status": "SAVED_AS_ZUGFERD",
"invoiceNumber": "INV-2026-001",
"taxExclusiveAmount": 750.00,
"taxInclusiveAmount": 892.50,
"lineExtensionAmount": 750.00,
"payableAmount": 892.50,
"allowanceTotalAmount": 0.00,
"currency": "EUR",
"createdTime": "2026-01-15T10:30:00",
"localCreatedTime": "2026-01-15T11:30:00",
"issueDate": "2026-01-15",
"deliveryDate": "2026-01-20",
"dueDate": "2026-02-15",
"supplierCountryCode": "DE",
"supplierEndpoint": "0204:DE123456789",
"customerId": "customer-uuid",
"customerVat": "DE987654321",
"customerEndpoint": "0204:DE987654321",
"customerCountryCode": "DE",
"typeCode": "380",
"documentType": "OUTGOING",
"errorMessage": null,
"lastUpdatedTime": "2026-01-15T10:30:00",
"localLastUpdatedTime": "2026-01-15T11:30:00",
"type": "ZUGFERD",
"source": "PORTAL",
"sendViaPeppol": false,
"statusTime": "2026-01-15T10:30:00",
"localStatusTime": "2026-01-15T11:30:00",
"fileName": "invoice_001.pdf",
"ocrParser": null,
"paymentDetails": null,
"profileType": "EN16931",
"isActive": true,
"countrySpecificData": null
}

]
}
}

Successful Response Field Descriptions

Top-Level Fields

FieldTypeDescription
totalCountLongTotal number of documents matching the filters
netTotalDoubleTax-exclusive total amount (excludes CREDIT_BLOCKED)
totalDoubleTax-inclusive total amount (excludes CREDIT_BLOCKED)
invoiceListArray<Invoice>List of invoice objects

Invoice Object Fields

FieldTypeDescription
idString (UUID)Unique identifier of the invoice
companyIdString (UUID)Company ID the invoice belongs to
userIdString (UUID)User ID who created the invoice
customerNameStringCustomer (buyer) name
supplierNameStringSupplier (seller) name
supplierIdStringSupplier ID
supplierVatStringSupplier VAT number
statusString (Enum)Current invoice status
invoiceNumberStringInvoice number
taxExclusiveAmountDoubleTax-exclusive amount
taxInclusiveAmountDoubleTax-inclusive amount
lineExtensionAmountDoubleLine items total amount
payableAmountDoubleAmount payable
allowanceTotalAmountDoubleTotal allowance/discount amount
currencyStringCurrency code (ISO 4217: EUR, USD, TRY, etc.)
createdTimeString (DateTime)Creation timestamp (UTC)
localCreatedTimeString (DateTime)Creation timestamp (local time)
issueDateString (Date)Invoice issue date
deliveryDateString (Date)Delivery date
dueDateString (Date)Due date
supplierCountryCodeStringSupplier country code (ISO 3166-1 alpha-2)
supplierEndpointStringSupplier Peppol endpoint
customerIdStringCustomer ID
customerVatStringCustomer VAT number
customerEndpointStringCustomer Peppol endpoint
customerCountryCodeStringCustomer country code
typeCodeStringInvoice type code (e.g., 380=Invoice, 381=Credit Note)
documentTypeString (Enum)Document direction: INCOMING or OUTGOING
errorMessageStringError message (if any)
lastUpdatedTimeString (DateTime)Last update timestamp (UTC)
localLastUpdatedTimeString (DateTime)Last update timestamp (local time)
typeString (Enum)Document format type (DataType)
sourceString (Enum)Invoice source (PORTAL, ERP, PEPPOL, EMAIL, etc.)
sendViaPeppolBooleanWhether sent via Peppol
statusTimeString (DateTime)Status change timestamp (UTC)
localStatusTimeString (DateTime)Status change timestamp (local time)
fileNameStringFile name
ocrParserString (Enum)OCR parser type
paymentDetailsObjectPayment details (null for certain statuses)
profileTypeString (Enum)ZUGFeRD profile type: BASIC, EN16931, EXTENDED
isActiveBooleanWhether the invoice is active
countrySpecificDataObjectCountry-specific additional data

Note: Invoices with CREDIT_BLOCKED status are masked — only id, companyId, documentType, type,invoiceNumber ,supplierName,supplierVat , status and isActive fields are returned; all other fields are null.

400 - Bad Request

Returned when an invalid parameter value is provided (e.g., incorrect enum value, malformed UUID format).

{
"errorMessage": "Invalid value 'INVALID_STATUS' for parameter 'status'",
"errorType": "ILLEGAL_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "corr-abc123-def456",
"status": 400,
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/search-documents"
}

Error Response Fields

FieldTypeDescription
errorMessageStringHuman-readable error description
errorTypeStringError type code
errorTitleStringHTTP status name
errorIdStringCorrelation ID (for log tracing)
statusIntegerHTTP status code
timestampString (DateTime)Error occurrence time
pathStringRequest path

401 - Unauthorized

Returned when an invalid, expired, or missing JWT token is provided.

{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"errorId": "corr-abc123-def456",
"status": 401,
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/search-documents"
}

Unauthorized Error Response Fields

FieldTypeDescription
errorMessageStringAuthorization error description
errorTypeStringFixed value: NOT_AUTHORITY
errorTitleStringHTTP status name: UNAUTHORIZED
errorIdStringCorrelation ID
statusInteger401
timestampString (DateTime)Error occurrence time
pathStringRequest path

500 - Internal Server Error

Returned in case of database connection errors, unexpected runtime exceptions, or other server-side failures.

{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "corr-abc123-def456",
"status": 500,
"timestamp": "2026-01-15T10:30:00",
"path": "/invoice/search-documents"
}

Server Error Response Fields

FieldTypeDescription
errorMessageStringGeneral error message
errorTypeStringRUNTIME_ERROR, IO_ERROR, or SERVER_ERROR
errorTitleStringHTTP status name: INTERNAL_SERVER_ERROR
errorIdStringCorrelation ID (for log tracing)
statusInteger500
timestampString (DateTime)Error occurrence time
pathStringRequest path

10. Get Invoice Details GET

Purpose of Use:
The GET /invoice/get-invoice/{invoiceId} endpoint allows retrieving the full structured details of a single invoice, including header data, party details, tax breakdown, and all invoice line items, in one consistent JSON structure regardless of the invoice's underlying document format, such as UBL, CII, Factur-X, etc.

Endpoint Information

PropertyValue
URL/invoice/get-invoice/{invoiceId}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header, JWT token

Example Request

curl --location 'https://api-fr-stage.docnova.ai/invoice/get-invoice/{invoiceId}' \
--header 'R-Auth: {your JWT}'

Request Parameters

Field NameTypeRequiredDescription
invoiceIdString (UUID)YesUnique identifier of the invoice. Must be in UUID v4 format. Obtained from the id field in the search-documents response.
R-AuthString (JWT)YesAuthentication token. JWT signed with HS512 algorithm.

Responses


200 - Successful Response

Returns an object with two top-level fields: invoice, the full invoice data, and paymentDetails, the payment status summary.

{
"invoice": {
"Type": "FACTUR_X",
"ProfileType": "EN16931",
"CustomizationID": {
"Value": "urn:cen.eu:en16931:2017"
},
"ID": {
"Value": "EXAMPLE-INV-001"
},
"IssueDate": {
"Value": "2026-07-29"
},
"DueDate": {
"Value": "2026-08-05"
},
"InvoiceTypeCode": {
"Value": "380"
},
"DocumentCurrencyCode": {
"Value": "EUR"
},
"AccountingSupplierParty": {
"Party": {
"PartyIdentification": [
{
"ID": {
"schemeID": "0225",
"Value": "000000000"
}
}
],
"PartyName": [
{
"Name": {
"Value": "Example Seller SAS"
}
}
],
"PostalAddress": {
"StreetName": {
"Value": "1 Example Street"
},
"CityName": {
"Value": "Paris"
},
"PostalZone": {
"Value": "75000"
},
"Country": {
"IdentificationCode": {
"Value": "FR"
}
}
},
"PartyTaxScheme": [
{
"CompanyID": {
"Value": "FR00000000000"
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
]
}
},
"AccountingCustomerParty": {
"Party": {
"PartyIdentification": [
{
"ID": {
"schemeID": "0225",
"Value": "000000001"
}
}
],
"PartyName": [
{
"Name": {
"Value": "Example Buyer SAS"
}
}
],
"PostalAddress": {
"StreetName": {
"Value": "2 Example Avenue"
},
"CityName": {
"Value": "Paris"
},
"PostalZone": {
"Value": "75008"
},
"Country": {
"IdentificationCode": {
"Value": "FR"
}
}
},
"PartyTaxScheme": [
{
"CompanyID": {
"Value": "FR00000000001"
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
]
}
},
"TaxTotal": [
{
"TaxAmount": {
"currencyID": "EUR",
"Value": 227.5
},
"TaxSubtotal": [
{
"TaxableAmount": {
"currencyID": "EUR",
"Value": 1000
},
"TaxAmount": {
"currencyID": "EUR",
"Value": 200
},
"TaxCategory": {
"ID": {
"Value": "S"
},
"Percent": {
"Value": 20
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
},
{
"TaxableAmount": {
"currencyID": "EUR",
"Value": 500
},
"TaxAmount": {
"currencyID": "EUR",
"Value": 27.5
},
"TaxCategory": {
"ID": {
"Value": "S"
},
"Percent": {
"Value": 5.5
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
},
{
"TaxableAmount": {
"currencyID": "EUR",
"Value": 300
},
"TaxAmount": {
"currencyID": "EUR",
"Value": 0
},
"TaxCategory": {
"ID": {
"Value": "Z"
},
"Percent": {
"Value": 0
},
"TaxExemptionReasonCode": {
"Value": "VATEX-EU-O"
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
}
]
}
],
"LegalMonetaryTotal": {
"LineExtensionAmount": {
"currencyID": "EUR",
"Value": 1800
},
"TaxExclusiveAmount": {
"currencyID": "EUR",
"Value": 1800
},
"TaxInclusiveAmount": {
"currencyID": "EUR",
"Value": 2027.5
},
"PayableAmount": {
"currencyID": "EUR",
"Value": 2027.5
}
},
"InvoiceLine": [
{
"ID": {
"Value": "1"
},
"InvoicedQuantity": {
"unitCode": "EA",
"Value": 1
},
"LineExtensionAmount": {
"currencyID": "EUR",
"Value": 1000
},
"Item": {
"Name": {
"Value": "Standard rate item"
},
"ClassifiedTaxCategory": [
{
"ID": {
"Value": "S"
},
"Percent": {
"Value": 20
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
]
},
"Price": {
"PriceAmount": {
"currencyID": "EUR",
"Value": 1000
}
}
},
{
"ID": {
"Value": "2"
},
"InvoicedQuantity": {
"unitCode": "EA",
"Value": 1
},
"LineExtensionAmount": {
"currencyID": "EUR",
"Value": 500
},
"Item": {
"Name": {
"Value": "Reduced rate item"
},
"ClassifiedTaxCategory": [
{
"ID": {
"Value": "S"
},
"Percent": {
"Value": 5.5
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
]
},
"Price": {
"PriceAmount": {
"currencyID": "EUR",
"Value": 500
}
}
},
{
"ID": {
"Value": "3"
},
"InvoicedQuantity": {
"unitCode": "EA",
"Value": 1
},
"LineExtensionAmount": {
"currencyID": "EUR",
"Value": 300
},
"Item": {
"Name": {
"Value": "VAT-exempt item"
},
"ClassifiedTaxCategory": [
{
"ID": {
"Value": "Z"
},
"Percent": {
"Value": 0
},
"TaxScheme": {
"ID": {
"Value": "VAT"
}
}
}
]
},
"Price": {
"PriceAmount": {
"currencyID": "EUR",
"Value": 300
}
}
}
]
},
"paymentDetails": {
"paymentStatus": "SENT",
"paidAmount": 0.0,
"totalAmount": 2027.5,
"remainingAmount": 2027.5,
"paymentDate": null
}
}

Response Fields

FieldTypeDescription
invoiceobjectFull structured invoice data.
invoice.TypestringUnderlying invoice document type, e.g. FACTUR_X.
invoice.ProfileTypestringInvoice profile type, e.g. EN16931.
invoice.ID.ValuestringBusiness invoice number.
invoice.IssueDate.ValuedateInvoice issue date.
invoice.DueDate.ValuedateInvoice due date.
invoice.InvoiceTypeCode.ValuestringInvoice type code, e.g. 380.
invoice.DocumentCurrencyCode.ValuestringInvoice currency, e.g. EUR.
invoice.AccountingSupplierPartyobjectSupplier party details.
invoice.AccountingCustomerPartyobjectCustomer party details.
invoice.TaxTotalarrayTax total and tax breakdown information.
invoice.LegalMonetaryTotalobjectInvoice monetary totals.
invoice.InvoiceLinearrayInvoice line items.
paymentDetailsobjectPayment status summary.
paymentDetails.paymentStatusstringCurrent payment status.
paymentDetails.paidAmountnumberAmount already paid.
paymentDetails.totalAmountnumberTotal invoice amount.
paymentDetails.remainingAmountnumberRemaining unpaid amount.
paymentDetails.paymentDatedatetimePayment date, if available.

401 - Unauthorized

{
"errorMessage": "User is not authorized for this operation",
"errorType": "NOT_AUTHORITY",
"status": 401,
"timestamp": "2026-07-29T12:00:00",
"path": "/invoice/get-invoice/{invoiceId}"
}

404 - Not Found

Returned when no invoice exists with the given invoiceId.

{
"errorMessage": "{invoiceId} Invoice not found!",
"errorType": "NOT_FOUND_INVOICE",
"status": 404,
"timestamp": "2026-07-29T12:00:00",
"path": "/invoice/get-invoice/{invoiceId}"
}

500 - Internal Server Error

Returned when invoiceId is not a valid UUID.

{
"errorMessage": "Invalid UUID string: {invoiceId}",
"errorType": "RUNTIME_ERROR",
"status": 500,
"timestamp": "2026-07-29T12:00:00",
"path": "/invoice/get-invoice/{invoiceId}"
}

11. Merge PDF and XML POST

Purpose of Use: This endpoint is used to merge a PDF invoice document with a ZUGFeRD/Factur-X compliant XML invoice data to create a ZUGFeRD-compliant PDF/A-3 document.

Detailed Description:

  • Combines the visual PDF invoice with the structured XML invoice data into a single file intended for the recipient.
  • The XML data is embedded into the PDF document as an attachment named factur-x.xml.
  • Before merging, the XML data is validated against the ZUGFeRD schema. If validation fails, an error is returned.
  • The result is a hybrid e-invoice document that is both human-readable (PDF) and machine-processable (embedded XML).
  • This endpoint is specifically designed for producing ZUGFeRD/Factur-X standard-compliant documents used in German (DE) e-invoicing processes.

Endpoint Information

PropertyValue
URLPOST /invoice/merge-zugferd-pdf-xml
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthenticationR-Auth header (JWT Token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/invoice/merge-zugferd-pdf-xml' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--data '{
"base64Pdf": "<BASE64_ENCODED_PDF>",
"base64Xml": "<BASE64_ENCODED_XML>"
}'

Request Body Parameters

Field NameTypeRequiredDescription
base64PdfStringYesBase64-encoded PDF document to be merged. Must contain a valid PDF file.
base64XmlStringYesBase64-encoded ZUGFeRD/Factur-X XML invoice data to be merged. Must conform to the ZUGFeRD schema (EN 16931).

Parameter Value Constraints

ParameterAccepted ValueConstraintSource
base64PdfValid Base64 StringMust be a Base64 encoding of a valid PDF document. Invalid Base64 or corrupted PDF returns an error.ErpController.java
base64XmlValid Base64 StringMust be XML conforming to ZUGFeRD EN 16931:2017 schema. Validated by Mustang ZUGFeRDValidator.ValidationService.java
file_type (response)PDF, XML, SIGN, JSON, GPDF, HTMLThis endpoint always returns PDF.FormatType.java

Responses

200 - Successful Response

{
"file_type": "PDF",
"data": "<BASE64_ENCODED_MERGED_PDF>"
}

Successful Response Field Descriptions

Field NameTypeDescription
file_typeStringFormat of the returned file. Always PDF for this endpoint.
dataStringBase64-encoded merged ZUGFeRD PDF document. Contains the XML data embedded as factur-x.xml.

400 - Bad Request

Returned when the base64Pdf or base64Xml is not a valid Base64 string or the decoded data is corrupted.

{
"errorMessage": "Illegal base64 character ...",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "<CORRELATION_ID>",
"timestamp": "2026-02-11T10:30:00",
"path": "/invoice/merge-zugferd-pdf-xml"
}
Field NameTypeDescription
errorMessageStringDetailed description of the error
errorTypeStringError classification. API_ERROR in this case
errorTitleStringHTTP status code name: BAD_REQUEST
statusIntegerHTTP status code: 400
errorIdStringRequest tracking identifier (Correlation ID)
timestampString (ISO 8601)Time when the error occurred
pathStringRequest URL path

400 - Bad Request

Returned when the XML data does not conform to the schema, along with validation errors.

{
"errorMessage": "Validation failed!",
"errorType": "VALIDATION_FAILED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "<CORRELATION_ID>",
"timestamp": "2026-02-11T10:30:00",
"path": "/invoice/merge-zugferd-pdf-xml",
"validationErrors": [
{
"field": "/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:ID",
"code": "BR-02",
"message": "An Invoice shall have an Invoice number."
}
]
}

validationErrors Array Field Descriptions

Field NameTypeDescription
fieldStringXML XPath location where the error was found
codeStringZUGFeRD/EN 16931 business rule code (e.g., BR-02, BR-CO-15)
messageStringDetailed description of the validation error

400 - Bad Request

Returned when the validation result cannot be parsed.

{
"errorMessage": "JAXBException occurred: ...",
"errorType": "VALIDATION_FAILED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "<CORRELATION_ID>",
"timestamp": "2026-02-11T10:30:00",
"path": "/invoice/merge-zugferd-pdf-xml"
}

401 - Unauthorized

Returned when the R-Auth header is missing, the JWT token is expired, or the token is invalid.

{
"errorMessage": "Unauthorized",
"errorType": "UNAUTHORIZED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"errorId": "<CORRELATION_ID>",
"timestamp": "2026-02-11T10:30:00",
"path": "/invoice/merge-zugferd-pdf-xml"
}

500 - Internal Server Error

Returned when an unexpected error occurs during PDF merging (corrupted PDF structure, memory issues, etc.).

{
"errorMessage": "An unexpected error occurred during PDF merging",
"errorType": "API_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"errorId": "<CORRELATION_ID>",
"timestamp": "2026-02-11T10:30:00",
"path": "/invoice/merge-zugferd-pdf-xml"
}

Note: The "catch (Exception e)" block in the controller throws all exceptions as ApiError, which defaults to HTTP 400. However, errors caught at the Spring framework level (e.g., JSON parse errors) may return HTTP 500.

12. Generate PDF POST

Purpose of Use: This API endpoint generates a human-readable PDF invoice document from structured XML invoice data (ZUGFeRD, Factur-X, XRechnung, etc.). The submitted Base64-encoded XML data is first transformed into HTML via XSLT templates, then converted into a professionally formatted PDF file using the iText 7 library. For ZUGFeRD/Factur-X/CII formats, the original XML data is embedded within the PDF file (PDF/A-3 compliant), creating a hybrid invoice. Optionally, the country and vatNumber fields can be used to match company records, enabling company logo placement and country-specific language settings on the PDF. It is specifically designed for invoice visualization, printing, and archiving processes in ERP integrations (SAP, etc.).

Endpoint Information

PropertyValue
URL/invoice/generate/pdf
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthenticationR-Auth header (JWT Bearer Token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/invoice/generate/pdf' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'R-Auth: eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJNTU0iLCJzdWIiOiJwNjR9.IpGPX...' \
--data '{
"base64XML": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KC...",
"country": "DE",
"type": "ZUGFERD",
"vatNumber": "DE777111222"
}

Request Parameters

Field NameTypeRequiredDescription
base64XMLStringYesBase64-encoded invoice XML data. Must be a valid XML in UBL 2.1, CrossIndustryInvoice (CII), or the relevant country-specific format.
typeEnum (DataType)YesInvoice format type. Specifies the standard of the provided XML. Valid values are listed in the table below.
countryEnum (Country)NoCountry code of the invoice (ISO 3166-1 alpha-2). When used together with vatNumber, company matching is performed to add logo and language settings to the PDF.
vatNumberStringNoVAT number of the invoicing company. When used together with country, it matches against the company record in the system.

Valid Values for type Parameter

UBL-Based Formats

ValueDescriptionXSLT Group
XRECHNUNGGerman XRechnung standard (EN 16931 compliant)XRECHNUNG
PEPPOL_BISPEPPOL BIS 3.0 standardXRECHNUNG
RO_EFACTURARomania e-Factura formatXRECHNUNG
MY_INVOISMalaysia MyInvois formatMY_INVOIS
MY_PINTMalaysia PINT formatMY_PINT
DK_OIOUBLDenmark OIOUBL formatDK_OIOUBL
EG_INVOICEEgypt invoice formatEG_INVOICE
HR_INVOICECroatia invoice formatHR_INVOICE
UAE_PINTUAE PINT formatUAE_PINT

CII / ZUGFeRD-Based Formats

ValueDescriptionXSLT Group
ZUGFERDZUGFeRD 2.x format (XML-embedded PDF)ZUGFERD
FACTUR_XFrench Factur-X formatZUGFERD
XRECHNUNG_CIIXRechnung CII formatZUGFERD
CIIUN/CEFACT CrossIndustryInvoiceZUGFERD
CIDCrossIndustryDocument formatZUGFERD
PDFUnstructured invoice (paper invoices, images, etc.)ZUGFERD

Other Formats

ValueDescriptionXSLT Group
KZ_ESF_V2Kazakhstan ESF v2 formatKZ_ESF_V2
KSEFPoland KSeF formatKSEF
KSEF_OFFLINEPoland KSeF offline formatKSEF_OFFLINE

country Parameter

Country CodeCountryPDF Language
DEGermanyGerman (DE)
ATAustriaGerman (DE)
FRFranceFrench (FR)
ITItalyItalian (IT)
NLNetherlandsDutch (NL)
RORomaniaRomanian (RO)
ESSpainSpanish (ES)
TRTurkeyTurkish (TR)
KZKazakhstanKazakh (KK)
MYMalaysiaMalay (MS)
BNBruneiMalay (MS)
All othersEnglish (EN)

Responses

200 - Successful Response

PropertyValue
HTTP Status200
Content-Typeapplication/octet-stream
BodyBinary PDF data (byte array)
%PDF-1.7
%����
1 0 obj
<<
/Pages 2 0 R
/Type /Catalog
/Names 21 0 R
/Metadata 27 0 R
>>
endobj
5 0 obj
<<

400 - Bad Request

Trigger Condition: When the XML data is invalid, Base64 cannot be decoded, XSLT transformation fails, or any error occurs during iText PDF generation.

{
"errorMessage": "PDF convert error: [detail message]",
"errorType": "PDF_CONVERT_ERROR",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}

Possible Detail Messages:

  • PDF convert error: PDF conversion failed due to an unexpected error — XSLT template not found or unexpected error during HTML-to-PDF conversion
  • PDF convert error: Illegal base64 character — The base64XML field is not in valid Base64 format
  • PDF convert error: [XSLT transformation error]` — XML structure does not match the expected format

400 - Bad Request — Invalid Parameter

Trigger Condition: When an invalid enum value is sent for the type field or required fields are missing.

{
"errorMessage": "Invalid argument! Argument: type",
"errorType": "INVALID_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}

400 - Bad Request — Invalid PDF Type

Trigger Condition: When the submitted type value is an unsupported format for PDF conversion.

{
"errorMessage": "Invalid PDF type",
"errorType": "INVALID_PDF_TYPE",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}

400 - Bad Request — Empty XML Data

Trigger Condition: When the base64XML field is sent as null or empty.

{
"errorMessage": "Data XML cannot be NULL!",
"errorType": "NULL_DATA_XML",
"errorTitle": "BAD_REQUEST",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}

401 - Unauthorized

Trigger Condition: When the R-Auth header is missing, the JWT token has expired, or an invalid token is provided.

{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 401,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}

500 - Internal Server Error

Trigger Condition: When an unexpected server error occurs (XSLT file cannot be loaded, insufficient memory, etc.).

{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"errorId": "a1b2c3d4-e5f6-7890-abcd-...",
"status": 500,
"timestamp": "2026-02-11T14:30:00",
"path": "/invoice/generate/pdf"
}

Error Codes and Response Details

The following errors are specific to this endpoint. All error responses follow the ExceptionResponse format:

Error Response Structure

Field NameTypeDescription
errorMessageStringDetailed description of the error
errorTypeStringError type identifier
errorTitleStringHTTP status name (BAD_REQUEST, INTERNAL_SERVER_ERROR, etc.)
errorIdStringCorrelation ID (for log tracing)
statusIntegerHTTP status code (400, 500, etc.)
timestampString (ISO 8601)Time when the error occurred
pathStringRequested URL path

13. Send Invoice via E-mail POST

Purpose of Use This API endpoint enables sending invoices to recipients via email. Users can select one or more invoices and send them in the desired format (PDF, XML, etc.) to specified email addresses. Invoice files are automatically converted to the requested format and attached to the email. Before sending, the user’s authorization is verified; only users with ADMIN or OUTGOING_INVOICE_SEND_EMAIL authority can perform this operation. Email delivery is first attempted via AWS SES; if that fails, an SMTP fallback mechanism is activated. Upon successful delivery, the invoice status is updated to SENT_VIA_EMAIL and the action is logged in the invoice history.

Endpoint Information

PropertyValue
URL/email/send
MethodPOST
Content-Typemultipart/form-data
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthenticationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/email/send' \
--header 'Content-Type: multipart/form-data' \
--header 'Accept: */*' \
--header 'R-Auth: <JWT_TOKEN>' \
--form 'invoiceIdList="<INVOICE_UUID>"' \
--form 'companyId="<COMPANY_UUID>"' \
--form 'body="Your Invoice is attached."' \
--form 'subject="2026_006"' \
--form 'formatTypes="PDF"' \
--form 'toList="recipient@example.com"'

Request Parameters

FieldTypeRequiredDescription
invoiceIdListList<UUID>YesList of invoice IDs to be sent. Multiple invoices can be included.
companyIdUUIDYesThe company ID that the invoices belong to.
formatTypesList<FormatType>YesFormat(s) in which invoice attachments will be generated. Multiple formats can be specified.
toListList<String>NoList of recipient email addresses.
ccListList<String>NoList of CC (Carbon Copy) recipient email addresses.
bccListList<String>NoList of BCC (Blind Carbon Copy) recipient email addresses.
subjectStringNoEmail subject line. If omitted, a template or default subject is used.
bodyStringNoEmail body text. If omitted, a template or default content is used.
attachmentsList<MultipartFile>NoAdditional file attachments (beyond the auto-generated invoice files).

FormatType Values

ValueDescription
PDFInvoice attached in PDF format
XMLInvoice attached in XML (UBL/CII) format
SIGNSigned invoice file attached
JSONInvoice attached in JSON format
GPDFInvoice attached in graphic PDF format
HTMLInvoice attached in HTML format

Attachment Constraints

ConstraintValue
Maximum file count3
Maximum file size (per file)5 MB
Allowed content typesapplication/pdf, application/xml, text/xml, image/png, image/jpg, image/jpeg, message/rfc822, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

Responses

200 - Successful Response

FieldTypeValueDescription
HTTP StatusInteger200Operation successful
BodyBooleantrueEmail sent successfully
true

400 - Bad Request

Condition: invoiceIdList field is empty or not provided.

{
"errorMessage": "Validation failed",
"errorType": "VALIDATION_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send",
"validationErrors": [
{
"field": "invoiceIdList",
"message": "must not be empty"
}
]
}

400 - Bad Request — Validation Error (companyId null)

Condition: companyId field is not provided.

{
"errorMessage": "Validation failed",
"errorType": "VALIDATION_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send",
"validationErrors": [
{
"field": "companyId",
"message": "must not be null"
}
]
}

400 - Bad Request — Validation Error (formatTypes empty)

Condition: formatTypes field is empty or not provided.

{
"errorMessage": "Validation failed",
"errorType": "VALIDATION_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send",
"validationErrors": [
{
"field": "formatTypes",
"message": "must not be empty"
}
]
}

400 - Bad Request — Invoice Not Found

Condition: No invoice found matching the provided invoiceIdList and companyId combination.

{
"errorMessage": "Invoices not found with id list [d2fc7bb5-4ffe-44ab-b9e9-92a833df65ec]",
"errorType": "INVALID_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send"
}

400 - Bad Request — Invoice Attachment Generation Failed

Condition: Invoice file could not be generated in the requested format (e.g., file not found in S3).

{
"errorMessage": "Attachments not found with invoice id list [d2fc7bb5-4ffe-44ab-b9e9-92a833df65ec]",
"errorType": "INVALID_ARGUMENT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send"
}

400 - Bad Request — Attachment Count Exceeded

Condition: More than 3 additional files were uploaded.

{
"errorMessage": "Maximum 3 files are allowed, found 5",
"errorType": "EMAIL_ATTACHMENT_COUNT_EXCEED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send"
}

400 - Bad Request — Attachment File Size Exceeded

Condition: An attachment exceeds the 5 MB limit.

{
"errorMessage": "Maximum 5MB file size is allowed, report.pdf file size is 8MB",
"errorType": "EMAIL_ATTACHMENT_FILE_SIZE_EXCEED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send"
}

400 - Bad Request — Attachment Content Type Not Allowed

Condition: The uploaded file's content type is not in the allowed list.

{
"errorMessage": "Allowed content types are [application/pdf, application/xml, text/xml, image/png, image/jpg, image/jpeg, message/rfc822, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet], malware.exe file content type is application/octet-stream",
"errorType": "EMAIL_ATTACHMENT_CONTENT_TYPE_NOT_ALLOWED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send"
}

400 - Bad Request — Email Sending Failed

Condition: Email could not be sent via both AWS SES and SMTP.

{
"errorMessage": "Failed to send email: Connection refused",
"errorType": "EMAIL_SENDING_FAILED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send"
}

401 - Unauthorized

Condition: Invalid or expired JWT token provided in the R-Auth header.

{
"errorMessage": "Unauthorized",
"errorType": "UNAUTHORIZED",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send"
}

403 - Forbidden

Condition: The user does not have ADMIN or OUTGOING_INVOICE_SEND_EMAIL authority.

{ 

"errorMessage": "Access denied",
"errorType": "FORBIDDEN",
"errorTitle": "FORBIDDEN",
"status": 403,
"timestamp": "2026-02-11T14:30:00",
"path": "/email/send"

}

14. 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

PropertyValue
URL/peppol/search-mlr
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

{
curl --location 'https://api-fr-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

FieldTypeRequiredFormatDescription
companyIdString (UUID)Yesxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxUnique identifier of the company to query
documentIdString (UUID)Noxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxPeppol document identifier (instance identifier)
counterpartParticipantIdStringNo{scheme}:{identifier} (e.g., 9930:de111222777)Counterpart’s Peppol participant identifier
invoiceIdStringNoFree textInvoice number or identifier
fromDateString (ISO Date)Noyyyy-MM-dd (e.g., 2025-09-09)Search start date (inclusive)
toDateString (ISO Date)Noyyyy-MM-dd (e.g., 2026-09-09)Search end date (inclusive)

Request Headers

HeaderTypeRequiredDescription
R-AuthString (JWT)YesUser authentication token. JWT signed with HS512 algorithm
AcceptStringNoDefault /. Response is returned as application/json

Parameter Values

counterpartParticipantId Format

SchemeDescriptionExample
9930Germany VAT number9930:de111222777
0204Leitweg-ID0204:1234567890123
0088EAN location code0088:1234567890123

responseType Response Type Enum Values

ValueDescription
ACCEPTANCEDocument was accepted by the counterpart
ACKNOWLEDGINGDocument was acknowledged (received) by the counterpart
REJECTIONDocument was rejected by the counterpart

statusReasonCode Status Reason Code Enum Values

ValueDescription
BUSINESS_RULE_VIOLATION_FATALBusiness rule violation. Critical error. Document was not processed
BUSINESS_RULE_VIOLATION_WARNINGBusiness rule violation. Warning. Document can still be processed
SYNTAX_VIOLATIONSyntax 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

FieldTypeDescription
idUUIDUnique identifier of the MLR record
companyIdStringIdentifier of the related company
documentIdStringPeppol document identifier
responseTypeEnum (MessageLevelResponseType)Overall response type: ACCEPTANCE, ACKNOWLEDGING, REJECTION
receivedTimeDateTime (ISO 8601)Date and time the MLR response was received
counterpartParticipantIdStringCounterpart’s Peppol participant identifier
invoiceIdStringRelated invoice number
responseLinesList<SearchMLRLineResponse>MLR detail lines

Response Detail Lines

FieldTypeDescription
idUUIDUnique identifier of the detail line
errorFieldString (nullable)The field / XPath expression where the error occurred
responseCodeEnum (MessageLevelResponseType)Line level response code: ACCEPTANCE, ACKNOWLEDGING, REJECTION
descriptionString (nullable)Error or status description
statusReasonCodeEnum (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

FieldTypeDescription
errorMessageStringHuman readable description of the error
errorTypeStringError classification code (e.g., NOT_AUTHORITY, RUNTIME_ERROR)
errorTitleString (HttpStatus)HTTP status code name (e.g., BAD_REQUEST, UNAUTHORIZED, INTERNAL_SERVER_ERROR)
statusIntegerHTTP status code numeric value (e.g., 400, 401, 500)
errorIdString (nullable)Correlation ID used for log tracing
dataString (nullable)Additional data (if available)
detailsMap<String, Object> (nullable)Detailed error information (if available)
validationErrorsList<ValidationError> (nullable)Field level validation errors (if available)
timestampDateTime (ISO 8601)Time when the error occurred
pathStringEndpoint path where the error occurred

15. 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

PropertyValue
URL/peppol/send-mlr
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthenticationR-Auth header (JWT token)

Example Request


curl --location 'https://api-fr-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 NameTypeRequiredDescription
invoiceIdString (UUID)YesUnique identifier of the invoice to send the MLR for (UUID format)
responseCodeEnum (MessageLevelResponseType)YesOverall response code for the invoice
errorLinesArray<MLRErrorLine>NoList of error details in the invoice. Can be left empty
errorLines Array Element
Field NameTypeRequiredDescription
descriptionStringNoHuman readable description of the error
errorFieldStringNoUBL/XML field path where the error was detected (XPath-like)
responseCodeEnum (MessageLevelResponseType)NoResponse code specific to this error line
statusReasonCodeEnum (MLRStatusReasonCode)NoClassification code of the error

Allowed Parameter Values


MessageLevelResponseType (responseCode)
ValueDescription
ACCEPTANCEInvoice accepted. It has been processed and approved
ACKNOWLEDGINGInvoice received. Receipt is confirmed but not yet fully processed
REJECTIONInvoice rejected. Not processed due to errors
MLRStatusReasonCode (statusReasonCode)
ValueDescription
BUSINESS_RULE_VIOLATION_FATALFatal business rule violation. A critical error that prevents the invoice from being processed
BUSINESS_RULE_VIOLATION_WARNINGWarning level business rule violation. The invoice can be processed but correction is recommended
SYNTAX_VIOLATIONSyntax error. Format or schema incompatibility in the XML/UBL structure

Responses

200 - Successful Response

FieldTypeValueDescription
HTTP StatusInteger200Operation successful
BodyString"MLR sent successfully"Response text returned from the Access Point service
"MLR sent successfully"

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.

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.

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 NameTypeDescription
errorMessageStringDetailed description of the error
errorTypeStringError classification code (e.g., NOT_FOUND_INVOICE, API_ERROR)
errorTitleString (HttpStatus)HTTP status name (e.g., NOT_FOUND, BAD_REQUEST)
errorIdStringCorrelation identifier (for log tracing)
statusIntegerHTTP status code (e.g., 400, 404, 500)
dataStringAdditional data (if available)
detailsMap<String, Object>Additional detail information (if available)
validationErrorsArray<ValidationError>Validation error list (if available)
timestampString (ISO 8601)Timestamp of when the error occurred
pathStringEndpoint path of the request

16. Search SIREN number GET

Purpose of Use This endpoint queries the PPF (Plateforme Publique de Facturation) — France's official public e-invoicing platform — to retrieve basic directory information about a French legal entity using its 9-digit SIREN number from the Annuaire (Directory) system.

SIREN (Système d'Identification du Répertoire des Entreprises) is the unique 9-digit identifier assigned to French companies by INSEE. Through this endpoint, callers can retrieve the company's legal name, entity type (public/private), administrative status, and directory record details in a single request.

Typical use cases:

  • Verifying that a SIREN is registered and active in the PPF Annuaire before sending an e-invoice to a French recipient
  • Determining whether a company belongs to the public or private sector in order to select the correct e-invoicing channel
  • Checking the diffusible (publishable) status of a legal entity during the onboarding flow
  • Retrieving the company's PPF instance ID for use in subsequent directory queries

Endpoint Information

PropertyValue
URL/annuaire/FR/siren/{siren}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request


curl --location 'https://api-fr-stage.docnova.ai/annuaire/FR/siren/123456789' \
--header 'Accept: application/json' \
--header 'R-Auth: <JWT_TOKEN>'

Request Parameters

FieldTypeRequiredDescription
sirenStringYesThe 9-digit French SIREN number for the target legal entity

Path Parameter Values

FieldRuleValid ExampleInvalid Example
sirenExactly 9 digits; leading zeros are preserved271688503271-685, 27168850, ABCDEFGHI, 2716885030

Responses

200 - Successful Response

{
"siren": "271688503",
"raisonSociale": "SIREN_271688503",
"typeEntite": "Privée assujettie",
"etatAdministratif": "A",
"diffusible": "O",
"historisation": {
"idInstance": 1003843,
"dateDebutEffet": null,
"dateDefinition": null,
"creePar": null,
"masque": null
}
}

400 - Bad Request

Returned when the SIREN parameter does not consist of exactly 9 digits.

{
"error": "VALIDATION_ERROR",
"message": "SIREN must be exactly 9 digits for French companies",
"code": "FR_SIREN_INVALID"
}

Description: The client has sent a value with fewer or more than 9 digits, or a non-numeric character. The SIREN format is validated against the regex pattern ^\d{9}$.

401 - Unauthorized

Returned when the JWT token in the R-Auth header cannot be verified.

{
"error": "UNAUTHORIZED",
"message": "Invalid or expired authentication token",
"code": "AUTH_TOKEN_INVALID"
}

Description: The token has expired, its signature is invalid, or the header is missing. The system internally attempts to obtain a new token; if that also fails, this error is propagated to the client. Token TTL is 50 minutes.

403 - Forbidden

Returned when the authenticated user does not have access rights to the requested SIREN record.

{
"error": "FORBIDDEN",
"message": "Access denied to this resource",
"code": "ACCESS_DENIED"
}

Description: Authentication succeeds, but the authorization layer rejects the request. This may result from PPF Annuaire access policies or user role restrictions.

404 - Not Found

Returned when the provided SIREN number is not registered in the PPF Annuaire.

{
"error": "NOT_FOUND",
"message": "No entity found for SIREN: 271688503",
"code": "COMPANY_NOT_FOUND"
}

Description: Even though the SIREN format is valid, no matching record exists in France's official directory. The company may not yet have registered with PPF, or the record may have been removed.

422 - Unprocessable Entity

Returned when the request is technically valid but cannot be processed due to business logic constraints.

{
"error": "UNPROCESSABLE_ENTITY",
"message": "PPF Annuaire registration failed. Please verify your company information and try again.",
"code": "FR_PPF_ONBOARD_FAILED"
}

Description: Typically triggered by data inconsistencies in the PPF system for the queried SIREN, or when the company is not marked as publishable (diffusible).

500 - Internal Server Error

Returned when an unexpected error occurs while communicating with the upstream PPF Annuaire service.

{
"error": "INTERNAL_SERVER_ERROR",
"message": "An unexpected error occurred while contacting PPF Annuaire",
"code": "GENERAL_ERROR"
}

Description: May be triggered by the upstream PPF API being unreachable, a timeout (default 15,000 ms), or an unexpected response format from the PPF Annuaire service.

17. Search SIRET number GET

Purpose of Use This endpoint queries the PPF (Plateforme Publique de Facturation) Annuaire to retrieve detailed information about a specific French business establishment using its 14-digit SIRET number.

SIRET (Système d'Identification du Répertoire des Établissements) is a unique 14-digit code that identifies a specific establishment (branch, headquarters, factory, etc.) of a French company. The first 9 digits are the company's SIREN number; the last 5 digits are the NIC (Numéro Interne de Classement) code that distinguishes the specific establishment.

Typical use cases:

  • Verifying that a SIRET is registered and active in the PPF Annuaire before sending an e-invoice to a French establishment
  • Retrieving the branch address (postal code, city, country) and establishment-level invoicing parameters
  • Determining whether the establishment is publishable (diffusible) and its administrative status
  • Obtaining the idInstance value to use in onboarding or routing flows

Endpoint Information

PropertyValue
URL/annuaire/FR/siret/{siret}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request


curl --location 'https://api-fr-stage.docnova.ai/annuaire/FR/siret/27168850399286' \
--header 'Accept: application/json' \
--header 'R-Auth: <JWT_TOKEN>'

Request Parameters

FieldTypeRequiredDescription
siretStringYesThe 14-digit French SIRET number for the target establishment

Path Parameter Values

FieldRuleValid ExampleInvalid Example
siretExactly 14 digits; leading zeros are preserved. The first 9 digits must match the parent company's SIREN.27168850399286, 000000000000012716885039928 (13 digits), 271688503992860 (15 digits), 2716-8850-3992-86, ABCDEFGHIJKLMN

Responses

200 - Successful Response

{
"siret": "27168850399286",
"siren": "271688503",
"denomination": "Valideur 27168850399286",
"typeEtablissement": "S",
"diffusible": "O",
"etatAdministratif": "A",
"adresse": {
"ligneAdresse1": "test street",
"ligneAdresse2": null,
"ligneAdresse3": null,
"codePostal": "75001",
"localite": "test city",
"codePays": "FR",
"libellePays": "France (la)",
"subDivisionPays": null
},
"historisation": {
"idInstance": 1015764,
"dateDebutEffet": null,
"dateDefinition": null,
"creePar": null,
"masque": null
}
}

Response Fields

FieldTypeDescription
siretStringThe queried 14-digit SIRET number.
sirenStringThe parent company's 9-digit SIREN number.
denominationStringOfficial establishment name (may differ from parent company name).
typeEtablissementStringEstablishment type (e.g., 'S' = secondary, 'P' = principal).
diffusibleStringPublishability flag: "O" = Yes, "N" = No.
etatAdministratifStringAdministrative status enum (e.g., "A", "F").
adresseObjectEstablishment address details.
historisationObjectAudit metadata for the record (idInstance, dates, creator, mask).

400 - Bad Request

Returned when the SIRET parameter does not consist of exactly 14 digits.

{
"error": "VALIDATION_ERROR",
"message": "Invalid SIRET: must be exactly 14 digits",
"code": "FR_SIRET_INVALID"
}

Description: The client has sent a value with fewer or more than 14 digits, or a non-numeric character. The SIRET format is validated against the regex pattern ^\d{14}$.

401 - Unauthorized

Returned when the JWT token in the R-Auth header cannot be verified.

{
"error": "UNAUTHORIZED",
"message": "Invalid or expired authentication token",
"code": "AUTH_TOKEN_INVALID"
}

403 - Forbidden

{
"error": "FORBIDDEN",
"message": "Access denied to this resource",
"code": "ACCESS_DENIED"
}

404 - Not Found

{
"error": "NOT_FOUND",
"message": "No establishment found for SIRET: 27168850399286",
"code": "COMPANY_NOT_FOUND"
}

422 - Unprocessable Entity

{
"error": "UNPROCESSABLE_ENTITY",
"message": "PPF Annuaire registration failed. Please verify your company information and try again.",
"code": "FR_PPF_ONBOARD_FAILED"
}

500 - Internal Server Error

{
"error": "INTERNAL_SERVER_ERROR",
"message": "An unexpected error occurred while contacting PPF Annuaire",
"code": "GENERAL_ERROR"
}

Description: May be triggered by the upstream PPF API being unreachable, a timeout (default 15,000 ms), or an unexpected response format returned by the PPF Annuaire service.

18. PPF Directory Line Instance Lookup GET

Purpose of Use: This endpoint is a live proxy to the PPF Annuaire API. When called, Docnova immediately forwards the request to the PPF's external /ligne-annuaire/id-instance:{idInstance} endpoint, returns the raw PPF response, and does not cache or store the result. The caller receives a real-time snapshot of the directory line as it currently exists in the national PPF Annuaire.

The PPF Annuaire (Portail Public de Facturation Directory) is France's central registry of all VAT-registered companies and their associated Plateformes Agréées, also known as approved e-invoicing platforms. Every company participating in the French e-invoicing mandate must have at least one ligne d'annuaire or directory line entry that specifies:

  • Which PA (Plateforme Agréée) the company is connected to, and via which channel
  • The company's addressing granularity (SIREN, SIRET, SUFFIXE, or CODE_ROUTAGE)
  • The routing and addressing identifiers needed to deliver e-invoices to the company
  • Validity dates, effect start and end dates, and historisation metadata

An idInstance is a unique numeric identifier assigned by the PPF to each version of a directory line entry. Because a company's annuaire entry can change over time, for example when switching platforms or updating routing codes, each historical version is preserved and assigned its own idInstance.

This endpoint is used for the following purposes:

  • Precise version lookup: Retrieve a specific historical version of a directory line using its immutable idInstance, even after the entry has been superseded by a newer version.
  • Annuaire data verification: Verify that a directory line known to Docnova still matches the live PPF Annuaire record for the same instance number. This is used in onboarding diagnostics and reconciliation.
  • Platform and routing detail retrieval: Fetch the full plateforme, etablissement, uniteLegale, and codeRoutage detail blocks that are needed to construct valid Peppol / PPF delivery addresses for the target company.
  • Support and audit use cases: Support teams use this endpoint to inspect the exact PPF record for a given instance, diagnose routing failures, and confirm validity dates.

🔄 Live PPF proxy — no caching: This endpoint makes a real-time call to the PPF Annuaire API on every request. The response reflects the current state of the PPF directory, not a Docnova-stored snapshot. Availability and latency depend on the PPF Annuaire API.

Server-Side Flow

StepProcessDescription
1AuthenticationThe R-Auth JWT is validated by the Spring Security filter chain. The authenticated user principal is extracted.
2Input validationidInstance is checked to be non-blank. A blank value throws a validation error and returns 400.
3PPF availability checkIf PPF integration is disabled in the Docnova configuration, the service returns null immediately and maps the response to 404 or 503, depending on environment configuration.
4External PPF callDocnova builds the URL /ligne-annuaire/id-instance:{idInstance} and makes an authenticated GET request to the PPF Annuaire API using a cached Bearer token stored in Redis. If the PPF returns 401, Docnova invalidates the cached token, re-authenticates, and retries the request once.
5PPF 404 handlingIf the PPF returns 404, meaning the instance was not found, Docnova returns null, and the response maps to 404.
6ResponseReturns HTTP 200 OK with the full AnnuaireLigneAnnuaireResponse JSON object mapped from the PPF response.

Endpoint Information

PropertyValue
URL/annuaire/FR/directory-line/instance/{idInstance}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)
Integration TypeLive PPF Proxy

Example Request

curl --location 'https://api-fr-stage.docnova.ai/annuaire/FR/directory-line/instance/{idInstance}' \
--header 'Accept: */*' \
--header 'R-Auth: <jwt-token>'

This endpoint has no query parameters and no request body. The only inputs are the idInstance path variable and the authentication token.

Request Parameters

Header Parameters

FieldTypeRequiredDescription
R-Authstring (JWT)YesUser session JWT token. Sent without a Bearer prefix. Signed with HS512; sub carries the encrypted user ID, claim carries authorization data, and userType holds CLIENT or ADMIN.
AcceptstringNo*/* or application/json. Defaults to JSON if omitted.

Path Parameters

ParameterTypeRequiredFormat / ExampleDescription
idInstancestring (numeric)Yes1013330The PPF-assigned unique numeric instance identifier of the directory line entry to retrieve. Assigned by the PPF when a ligne d'annuaire is created or updated. Each historical version of a directory line has a distinct idInstance. Must be non-blank; numeric string format is expected. No UUID format is required.

Responses


200 - Successful Response

Returns HTTP 200 OK with an AnnuaireLigneAnnuaireResponse object. The structure is nested: top-level addressing fields are accompanied by embedded plateforme, uniteLegale, etablissement, historisation, and codeRoutage objects.

{
"identifiantAdressage": "123456789",
"matriculePlateforme": "0001",
"identifiantRoutage": "0009:0001",
"siren": "123456789",
"siret": "12345678900014",
"suffixeAdressage": null,
"dateFinEffet": null,
"dateFinEffective": null,
"historisation": {
"idInstance": 1013330,
"dateDebutEffet": "2026-01-01",
"dateDefinition": "2025-12-20T09:00:00Z",
"creePar": "DOCNOVA_PA",
"masque": false
},
"plateforme": {
"typePlateforme": "PA",
"matriculePlateforme": "0001",
"raisonSocialePlateforme": "Melasoft SAS",
"nomCommercialPlateforme": "Docnova",
"contactOuUrlPlateforme": "https://docnova.ai",
"statutPlateforme": "ACTIF"
},
"uniteLegale": {
"siren": "123456789",
"raisonSociale": "ACME FRANCE SAS",
"typeEntite": "PM",
"etatAdministratif": "A",
"diffusible": "O"
},
"etablissement": {
"siret": "12345678900014",
"siren": "123456789",
"denomination": "ACME FRANCE SAS - SIEGE",
"typeEtablissement": "SIEGE",
"diffusible": "O",
"etatAdministratif": "A",
"adresse": {
"ligneAdresse1": "10 RUE DE LA PAIX",
"ligneAdresse2": null,
"ligneAdresse3": null,
"codePostal": "75001",
"localite": "PARIS",
"codePays": "FR",
"libellePays": "France",
"subDivisionPays": null
},
"donneesB2gComplementaires": null
},
"codeRoutage": null
}
Response Body — Top-Level Fields
FieldTypeNullableDescription
identifiantAdressagestringYesThe primary addressing identifier of the company in the PPF Annuaire. Contains the SIREN (9 digits) when maille is SIREN, SIRET (14 digits) when maille is SIRET, or the routing code value for CODE_ROUTAGE.
matriculePlateformestringYesPPF registration code of the Plateforme Agréée that handles this company's e-invoices. Used as the network address of the PA in Peppol routing.
identifiantRoutagestringYesFull routing identifier in the format {schemeId}:{value}, for example 0009:0001. Used by the PPF to route incoming e-invoices to the correct PA endpoint.
sirenstring (9)YesThe 9-digit SIREN of the company this directory line belongs to.
siretstring (14)YesThe 14-digit SIRET of the specific establishment, if this entry is registered at SIRET granularity. null for SIREN-level entries.
suffixeAdressagestringYesSuffix appended to the SIRET for sub-unit identification. Populated only when the annuaire maille is SUFFIXE.
dateFinEffetLocalDateYesThe planned end date of this directory line's validity. null if the entry is open-ended and still active.
dateFinEffectiveLocalDateYesThe actual effective end date as confirmed by the PPF. May differ from dateFinEffet if the closure was processed at a different time.
historisationobjectYesVersion and audit metadata assigned by the PPF to this specific instance. See historisation below.
plateformeobjectYesFull detail of the Plateforme Agréée associated with this directory line. See plateforme below.
uniteLegaleobjectYesLegal entity (SIREN-level) details of the company. See uniteLegale below.
etablissementobjectYesEstablishment (SIRET-level) details including address and B2G configuration. See etablissement below.
codeRoutageobjectYesRouting code detail block. Populated only when the annuaire maille is CODE_ROUTAGE. null for SIREN, SIRET, and SUFFIXE entries. See codeRoutage below.
historisation — Version & Audit Metadata
FieldTypeNullableDescription
idInstanceintegerNoThe PPF-assigned unique instance number of this directory line version. Matches the idInstance supplied in the request path.
dateDebutEffetLocalDateYesThe date from which this directory line version became effective in the PPF.
dateDefinitionOffsetDateTimeYesThe exact date-time when this instance was defined, created, or updated in the PPF Annuaire. ISO 8601 with timezone offset.
creeParstringYesIdentifier of the actor, PA matricule or PPF internal identifier, that created this instance.
masquebooleanYesIf true, this directory line has been hidden or masked in the PPF Annuaire. A masked entry is not visible to other PAs for routing purposes.
plateforme — Associated Plateforme Agréée
FieldTypeNullableDescription
typePlateformestringYesPlatform type code. Typically PA (Plateforme Agréée) or PPF (Portail Public de Facturation itself).
matriculePlateformestringYesThe PPF-assigned registration number of the platform. Used as the routing endpoint identifier in e-invoice transmission.
raisonSocialePlateformestringYesLegal company name of the platform operator.
nomCommercialPlateformestringYesCommercial or brand name of the platform, for example Docnova.
contactOuUrlPlateformestringYesContact email address or URL of the platform for support or integration queries.
statutPlateformestringYesAdministrative status of the platform in the PPF registry. Common values: ACTIF (active), SUSPENDU (suspended), FERME (closed).
FieldTypeNullableDescription
sirenstring (9)Yes9-digit SIREN of the legal entity.
raisonSocialestringYesLegal company name registered with INSEE.
typeEntitestringYesEntity type: PM (Personne Morale / legal person) or PP (Personne Physique / natural person).
etatAdministratifstringYesAdministrative status from INSEE: A (Actif / active) or C (Cessé / ceased).
diffusiblestringYesINSEE diffusion flag: O (diffusible / public) or N (non-diffusible / private). Non-diffusible entities have restricted access in public directories.
etablissement — Establishment (SIRET Level)
FieldTypeNullableDescription
siretstring (14)Yes14-digit SIRET of the establishment.
sirenstring (9)YesParent SIREN of the establishment.
denominationstringYesEstablishment name or designation. May include branch suffix, for example - SIEGE.
typeEtablissementstringYesType of establishment: SIEGE (registered head office) or SECONDAIRE (secondary establishment).
diffusiblestringYesINSEE diffusion flag: O or N.
etatAdministratifstringYesAdministrative status: A (active) or F (fermé / closed).
adresseobjectYesPostal address of the establishment. See etablissement.adresse fields below.
donneesB2gComplementairesobjectYesB2G (Business-to-Government) supplementary data. null for purely B2B companies. See donneesB2gComplementaires below.
etablissement.adresse — Postal Address
FieldTypeNullableDescription
ligneAdresse1stringYesFirst address line, including street number and name.
ligneAdresse2stringYesSecond address line, for example building, floor, or additional location information.
ligneAdresse3stringYesThird address line for additional details.
codePostalstringYesFrench postal code, 5 digits.
localitestringYesCity or locality name.
codePaysstring (2)YesISO 3166-1 alpha-2 country code, for example FR.
libellePaysstringYesFull country name in French.
subDivisionPaysstringYesCountry subdivision code (ISO 3166-2). Rare; mostly null for French addresses.
etablissement.donneesB2gComplementaires — B2G Supplementary Data
FieldTypeNullableDescription
gestionEngagementJuridiquebooleanYesWhether legal commitment management is enabled for this entity in the B2G context.
gestionStatutMiseEnPaiementbooleanYesWhether payment status management is active.
gestionCodeServicebooleanYesWhether service code management is enabled.
moaUniquementbooleanYesIf true, this entity operates as buyer (MOA — Maître d'Ouvrage) only in B2G flows.
gestionEngagementJuridiqueOuServicebooleanYesCombined flag indicating whether legal commitment or service code management is enabled.
moabooleanYesWhether this entity is designated as MOA (project owner / buyer) in the B2G procurement flow.
codeRoutage — Routing Code Detail (CODE_ROUTAGE Maille Only)
FieldTypeNullableDescription
identifiantRoutagestringYesThe routing code identifier assigned to this sub-unit.
typeIdentifiantRoutagestringYesType of the routing identifier, also known as the scheme.
libelleCodeRoutagestringYesHuman-readable label for the routing code.
gestionEngagementJuridiquebooleanYesB2G legal commitment flag at routing code level.
etatAdministratifstringYesAdministrative status of this routing code: A (active) or F (closed).
adresseobjectYesPostal address associated with this routing code. Same structure as etablissement.adresse.

Enum Values

FrancePpfMaille — Annuaire Addressability Granularity

Determines which of the nested objects is populated and which top-level identifier is used.

ValueidentifiantAdressage ContainsPopulated Nested ObjectDescription
SIREN9-digit SIRENuniteLegaleCompany is registered at SIREN level. All invoices addressed to this company, regardless of establishment, are routed to the same PA.
SIRET14-digit SIRETetablissementCompany is registered at establishment level. Different SIRET numbers may route to different PAs.
SUFFIXESIRET + suffixetablissement + suffixeAdressageSub-unit of an establishment identified by an additional suffix. Used for large organizations with complex internal routing.
CODE_ROUTAGErouting code valuecodeRoutageCustom routing code; used by large corporate groups where neither SIREN nor SIRET granularity is sufficient.

All error responses share the following structure:

{
"errorMessage": "<human-readable message>",
"errorType": "<error type key>",
"errorTitle": "<HTTP status name>",
"status": 404,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/annuaire/FR/directory-line/instance/1013330"
}

400 - Bad Request

Returned when the idInstance path variable is present but empty or blank.

{
"errorMessage": "idInstance must not be blank",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/annuaire/FR/directory-line/instance/"
}

Condition: The idInstance path variable is present but empty or blank, for example /instance/ or /instance/ .

Server behavior: FranceAnnuaireApiService.validateNotBlank() throws IllegalArgumentException; RestExceptionHandler maps it to 400.

401 - Unauthorized

Returned when the R-Auth header is missing, malformed, or the JWT token is expired.

{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/annuaire/FR/directory-line/instance/1013330"
}

Condition: The R-Auth header is missing, malformed, or the JWT exp claim has passed.

Server behavior: Spring Security filter chain rejects the request before the controller is reached.

404 - Not Found

Returned when the PPF Annuaire API returns 404.

{
"errorMessage": "Not Found",
"errorType": "NOT_FOUND",
"errorTitle": "NOT_FOUND",
"status": 404,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/annuaire/FR/directory-line/instance/1013330"
}

Condition: The PPF Annuaire API returned 404, meaning no directory line exists for the given idInstance, or the instance number has never been assigned by the PPF.

Server behavior: FranceAnnuaireApiService.doGetAttempt() receives a 404 from PPF and returns null; the controller's toResponse(null) maps to a 404 HTTP response.

500 - Internal Server Error

Returned when an unexpected exception occurs while communicating with the PPF Annuaire API.

{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/annuaire/FR/directory-line/instance/1013330"
}

Condition: An unexpected exception occurred while communicating with the PPF Annuaire API, such as network timeout, malformed PPF response, or an unhandled HTTP error status from the PPF.

Server behavior: The try/catch in doGetAttempt() catches the exception and rethrows it as a RuntimeException; RestExceptionHandler maps it to 500.

503 - Service Unavailable

Returned when the PPF Annuaire integration is disabled in the Docnova server configuration.

{
"errorMessage": "PPF integration is currently unavailable",
"errorType": "SERVER_ERROR",
"errorTitle": "SERVICE_UNAVAILABLE",
"status": 503,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/annuaire/FR/directory-line/instance/1013330"
}

Condition: The PPF Annuaire integration is disabled in the Docnova server configuration (config.isEnabled() = false). This typically happens in maintenance or staging environments where the PPF connection is intentionally turned off.

Server behavior: The service returns null immediately without calling PPF; response mapping returns 404 or 503, depending on environment configuration.

19. Reporting Create Report POST

Purpose of Use: This endpoint manually creates a France Flux 10 e-reporting report occurrence — a B2C or B2B/international transaction e-report, or a payment (collection) e-report — for cases where the caller's own system holds the business data directly and needs to register a report occurrence without going through Docnova's invoice pipeline. Docnova normally generates these reports automatically from invoices/payments processed through the platform; this endpoint is the manual alternative.

This endpoint is used for the following purposes:

  • B2C sales e-reporting: Submitting a TRANSACTION_B2C occurrence for a domestic sale to an individual customer that never went through Docnova as an invoice.
  • B2B international invoice e-reporting: Submitting a TRANSACTION_B2B occurrence for an invoice issued to a non-French B2B counterparty.
  • Payment (collection) e-reporting: Submitting a PAYMENT_B2B/PAYMENT_B2C occurrence for the collection of an invoice already reported elsewhere.
  • Historical/migration loading: Bulk-registering past e-reporting occurrences during onboarding.

Important: One request body shape (FranceReportRequest) is shared by all four report families — not every field is valid for every family. Sending invoiceId on any item, or a structure outside the four supported families (the internal TRANSACTION_COMBINED/PAYMENT_COMBINED batch types are never valid here), rejects the whole request.

Server-Side Flow

StepProcessDescription
1AuthenticationThe R-Auth JWT is validated by the Spring Security filter chain. The authenticated user's uid is extracted via @AuthenticationPrincipal JwtUser.
2Company resolutioncompanyId (or apiKey, if companyId is omitted) resolves the target company. If neither is supplied, the request is rejected.
3Structure & cardinality validationstructure is checked against the four supported manual families; item count is checked against the family's rule (exactly 1 for TRANSACTION_B2B/PAYMENT_B2B/PAYMENT_B2C, 1..N for TRANSACTION_B2C).
4Declarant role validationdeclarantRoleCode is checked per family — required explicit SE/BY for TRANSACTION_B2B; defaults to SE for the others, anything else rejected.
5VAT breakdown & field validationEach item's vatBreakdown is checked for correct grouping and family-specific field restrictions (e.g. taxCategoryCode rejected for TRANSACTION_B2C).
6Duplicate checkThe request is checked against existing invoices/reports in the system for the same invoice number + issue date.
7PersistenceA new report record is created in DRAFT status and saved.
8ResponseReturns HTTP 200 OK with the full FranceReportResponse JSON object.

Endpoint Information

PropertyValue
URL/reporting/FR/report
MethodPOST
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location --request POST 'https://api-fr-stage.docnova.ai/reporting/FR/report' \
--header 'Accept: */*' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <jwt-token>' \
--data '{
"structure": "TRANSACTION_B2C",
"companyId": "<company-id>",
"items": [
{
"invoiceNumber": "<invoice-number>",
"invoiceIssueDate": "2026-04-08",
"currency": "EUR",
"category": "GOODS",
"vatBreakdown": [
{ "taxRate": 20, "taxableAmount": 500.00, "taxAmount": 100.00 }
]
}
]
}'

Request Parameters

Body Parameters

FieldTypeRequiredDescription
structurestring (enum)YesOne of TRANSACTION_B2B, TRANSACTION_B2C, PAYMENT_B2B, PAYMENT_B2C. TRANSACTION_COMBINED/PAYMENT_COMBINED are internal batch types and are rejected if sent.
companyIdstring (UUID)Required unless apiKey sentTarget company.
apiKeystringRequired unless companyId sentAlternative way to identify the target company.
declarantRoleCodestring (enum)See descriptionSE (Seller) or BY (Buyer/self-billing). Required explicitly for TRANSACTION_B2B — no default. Defaults to SE for TRANSACTION_B2C/PAYMENT_B2B/PAYMENT_B2C; any other value is rejected.
itemsarrayYes, non-emptySee item fields below. Cardinality: exactly 1 for TRANSACTION_B2B/PAYMENT_B2B/PAYMENT_B2C; 1..N for TRANSACTION_B2C (category slices of one invoice).

Item Fields (items[])

FieldTx B2BTx B2CPay B2BPay B2CDescription
invoiceId🚫🚫🚫🚫Must never be sent — rejects the whole request if present on any item.
invoiceNumberRequiredRequiredRequiredOptionalOccurrence's invoice number.
invoiceIssueDateRequiredRequiredRequiredRequiredInvoice issue date (payment reference date for Payment).
currencyRequiredRequiredRequiredRequiredAny ISO 4217 for Transactions; EUR only for Payments.
categorynot usedRequiredn/an/aGOODS/SERVICE/NON_TAXABLE/MARGIN_SCHEME. MIXED is never accepted — split into separate items first.
paymentDaten/an/aRequiredRequiredCollection date.
counterpartyCompanyId / counterpartyVatIdOptional🚫 must be absentOptional🚫 must be absentCounterparty business identifiers.
vatAmountServer-derived for EUR; caller-required for non-EURServer-derived for EUR; caller-required for non-EURn/an/aCanonical EUR VAT amount — Docnova does not convert currency for a non-EUR occurrence.
vatBreakdownRequired, non-emptyRequired, non-emptyRequired, non-emptyRequired, non-emptySee VAT breakdown fields below.

taxableAmount and (for Payments) collectedAmount/collectedAmountExclVat/collectedVatAmount are always server-derived from vatBreakdown — do not send them, they are silently overwritten.

VAT Breakdown Fields (items[].vatBreakdown[])

FieldTx B2BTx B2CPaymentsDescription
taxRateRequired*Required*Required*Plain percentage, must be a valid French VAT rate. *Not required only when the item's taxableAmount is exactly zero.
taxableAmount / taxAmountOptional (recommended)Optional (recommended)Optional (recommended)Feeds the server-derived totals — omitting it understates them.
taxCategoryCode / vatExemptionReasonCode / vatExemptionReasonOptional🚫 rejecteddo not send (ignored)B2B-only reverse-charge/exemption concept.

Duplicate VAT rate buckets within one item are rejected, not merged: TRANSACTION_B2B groups by rate and normalized taxCategoryCode/vatExemptionReasonCode; every other family groups by rate alone.

Responses

200 - Successful Response

Returns HTTP 200 OK with the newly created FranceReportResponse (status DRAFT).

{
"reportId": "<report-id>",
"status": "DRAFT",
"reportType": "TRANSACTION_B2C",
"source": "ERP",
"invoiceNumber": "<invoice-number>",
"occurrenceDate": "2026-04-08",
"currency": "EUR",
"itemCount": 1,
"totalAmount": 500.00,
"createdTime": "2026-04-08T09:12:00",
"ppfAckStatus": null,
"ppfErrorMessage": null,
"ppfErrorCode": null
}

See the Reporting Search Status documentation for the full response field reference — ppfAckStatus/ppfErrorCode/ppfErrorMessage remain null until the occurrence is later included in a submitted batch.

400 - Bad Request: Missing Items

Returned when items is missing or empty.

{
"errorMessage": "Report items must contain at least one item",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

400 - Bad Request: Unsupported Structure

{
"errorMessage": "Manual report creation is not supported for this report structure.",
"errorType": "MANUAL_REPORT_STRUCTURE_NOT_SUPPORTED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

Condition: structure is missing, or is one of the internal batch types TRANSACTION_COMBINED/PAYMENT_COMBINED, or any other unsupported value.

400 - Bad Request: invoiceId Not Allowed

{
"errorMessage": "invoiceId must not be provided when creating a manual report. Reports for invoices already registered in Docnova must be handled through the existing invoice.",
"errorType": "MANUAL_REPORT_INVOICE_ID_NOT_ALLOWED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

Condition: invoiceId was set on an item. This field exists on the shared DTO only for internal/automatic flows — never send it manually.

400 - Bad Request: Wrong Item Count

{
"errorMessage": "A manual TRANSACTION_B2B report request must contain exactly one item — TRANSACTION_B2B is one occurrence per invoice.",
"errorType": "MANUAL_TRANSACTION_B2B_MUST_HAVE_SINGLE_ITEM",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

Condition: items does not contain exactly one entry for TRANSACTION_B2B — analogous MANUAL_PAYMENT_B2B_MUST_HAVE_SINGLE_ITEM / MANUAL_PAYMENT_B2C_MUST_HAVE_SINGLE_ITEM error types apply the same rule to PAYMENT_B2B/PAYMENT_B2C. Only TRANSACTION_B2C may carry more than one item.

400 - Bad Request: VAT Breakdown Not Grouped

{
"errorMessage": "The submitted VAT breakdown is not correctly grouped for TRANSACTION_B2C: duplicate rate=20 - this family groups by VAT rate only, merge same-rate entries into one before submitting.",
"errorType": "MANUAL_REPORT_VAT_BREAKDOWN_NOT_GROUPED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

Condition: Two or more vatBreakdown entries on the same item resolve to the same grouping key — the request must already be grouped, duplicates are rejected rather than merged automatically.

400 - Bad Request: B2C VAT Breakdown Field Not Allowed

{
"errorMessage": "TRANSACTION_B2C vatBreakdown entries must not set taxCategoryCode, vatExemptionReasonCode or vatExemptionReason — these fields have no B2C XML representation (only taxRate/taxableAmount/taxAmount are used); they are reserved for TRANSACTION_B2B.",
"errorType": "MANUAL_TRANSACTION_B2C_VAT_BREAKDOWN_FIELD_NOT_ALLOWED",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

400 - Bad Request: Payment Currency Must Be EUR

{
"errorMessage": "Manual payment reports must be in EUR: invoice=<invoice-number>, currency=GBP",
"errorType": "MANUAL_PAYMENT_CURRENCY_MUST_BE_EUR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

Condition: PAYMENT_B2B/PAYMENT_B2C currency (from currency and/or paymentCurrency) does not resolve to EUR, or the two fields disagree with each other.

401 - Unauthorized

Returned when the R-Auth header is missing, malformed, or the JWT token is expired.

{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

409 - Conflict: Duplicate Report

{
"errorMessage": "This transaction already exists in the system and cannot be entered manually. An invoice with invoice number '<invoice-number>' and issue date '2026-04-05' already exists in the system. A manual report cannot be created for this invoice.",
"errorType": "MANUAL_REPORT_NOT_ALLOWED_EXISTING_SYSTEM_TRANSACTION",
"errorTitle": "CONFLICT",
"status": 409,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

Condition: An invoice with the same invoice number and issue date already exists in Docnova (either as a real invoice, or as a previously-created report for the same occurrence) — a manual report cannot duplicate it. The analogous MANUAL_PAYMENT_REPORT_NOT_ALLOWED_EXISTING_INVOICE error is used when the duplicate check is specifically against payment reporting for an invoice already present in the system.

500 - Internal Server Error

Returned when an unexpected runtime exception occurs while processing the request — for example, if the target company's France module is not enabled/configured, or a database/mapping failure occurs.

{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report"
}

20. Reporting Edit Report PUT

Purpose of Use: Replaces the content of an existing manually-created report occurrence. Used to correct a mistake in a report still in DRAFT, or to resubmit a CORRECTABLE report that PPF rejected at content level. For Payment reports, this is also usable on MERGED reports (unless a transmission for them is currently in flight) — Payment does not share Transaction's "locked once merged" rule.

Typical use cases:

  • Fixing a typo or wrong amount in a DRAFT report before it is picked up by the next batch.
  • Resubmitting a CORRECTABLE occurrence after PPF rejected the batch it was part of.
  • Correcting a MERGED payment report before its next transmission attempt.

Important: This is a full replacement, not a patch — the entire items array is replaced. For a multi-item TRANSACTION_B2C occurrence, resend every item, not just the one that changed.

Server-Side Flow

StepProcessDescription
1AuthenticationThe R-Auth JWT is validated; uid extracted.
2Company resolution & authorizationThe report's owning company is resolved from reportId; the caller must hold ADMIN on that company or the request is rejected.
3Provenance checkThe target report must have been created manually and be one of the four manual-supported families — editing a Docnova-generated (automatic) report through this endpoint is rejected.
4Same validation as CreateStructure/cardinality/declarant-role/VAT-breakdown checks all reapply, identically to POST /reporting/FR/report.
5Editable-status checkTransaction family: only DRAFT/CORRECTABLE may be edited. Payment family: DRAFT/CORRECTABLE/MERGED may be edited, unless the report's current transmission is still in flight (awaiting PPF acknowledgment).
6PersistenceThe entire items array is replaced on the existing record; for Transaction, a CORRECTABLE report returns to DRAFT.
7ResponseReturns HTTP 200 OK with the updated FranceReportResponse.

Endpoint Information

PropertyValue
URL/reporting/FR/report/{reportId}
MethodPUT
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token) — caller must additionally be ADMIN on the report's owning company

Example Request

curl --location --request PUT 'https://api-fr-stage.docnova.ai/reporting/FR/report/<report-id>' \
--header 'Accept: */*' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <jwt-token>' \
--data '{
"structure": "TRANSACTION_B2C",
"companyId": "<company-id>",
"items": [
{
"invoiceNumber": "<invoice-number>",
"invoiceIssueDate": "2026-04-08",
"currency": "EUR",
"category": "GOODS",
"vatBreakdown": [
{ "taxRate": 20, "taxableAmount": 550.00, "taxAmount": 110.00 }
]
}
]
}'

Request Parameters

Path Parameters

ParameterTypeRequiredDescription
reportIdUUIDYesThe Docnova system UUID of the report to edit. Obtained from a prior Create response, or from GET /reporting/FR/list.

Body Parameters

Same shape as POST /reporting/FR/report — see the Reporting Create Report documentation for the full structure/companyId/declarantRoleCode/items/VAT-breakdown field reference. All the same per-family validation rules apply identically on edit.

Responses

200 - Successful Response

Returns HTTP 200 OK with the updated FranceReportResponse — same shape as Create's response.

400 - Bad Request

{
"errorMessage": "Report not found: <report-id>",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

Condition: No report exists in Docnova for the given reportId.

400 - Bad Request: Not Manually Created

{
"errorMessage": "This report was not created manually and cannot be edited or deleted through the manual report endpoints.",
"errorType": "MANUAL_REPORT_ACTION_NOT_ALLOWED_FOR_AUTO_REPORT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

Condition: The target report was generated automatically by Docnova (not through this manual API) — only manually-created reports can be edited here.

400 - Bad Request: Transmission In Flight

{
"errorMessage": "This report's transmission is still in flight (awaiting PPF acknowledgment) and cannot be edited or deleted yet.",
"errorType": "MANUAL_REPORT_TRANSMISSION_IN_FLIGHT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

Condition: A MERGED Payment report whose containing transmission has already been dispatched to PPF and is still awaiting acknowledgment — wait for the current transmission to resolve before editing.

For a TRANSACTION_B2B/TRANSACTION_B2C report in a non-editable status (not DRAFT or CORRECTABLE), the request is rejected with the message "Only DRAFT or CORRECTABLE reports can be edited", surfaced the same way as the other 400 errors above.

The same body-validation errors documented under Reporting Create Report (unsupported structure, invoiceId present, wrong item count, VAT breakdown grouping/field errors, non-EUR payment currency) apply identically here.

401 - Unauthorized

Returned both when the R-Auth header is missing/expired, and when the caller is authenticated but is not ADMIN on the report's owning company.

{
"errorMessage": "User is not authorized for this operation",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

This endpoint returns 401, not 403, for both "not authenticated" and "authenticated but insufficient permission" cases. Distinguish the two by errorMessage/errorType rather than by HTTP status alone.

500 - Internal Server Error

{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

21. Reporting Delete Report DELETE

Purpose of Use: Permanently deletes (or, where the underlying data has already been transmitted, clears to an empty correction marker) a manually-created report occurrence. Used to remove a report that was created in error, before it has progressed too far in its lifecycle to be safely deleted outright.

Important — Transaction vs Payment deletion behavior differs:

  • Transaction (TRANSACTION_B2B/TRANSACTION_B2C): only deletable while DRAFT or CORRECTABLE. A MERGED transaction report can never be deleted through this endpoint.
  • Payment (PAYMENT_B2B/PAYMENT_B2C): a DRAFT report is hard-deleted. A MERGED report can still be "deleted" — provided its transmission is not currently in flight — but is not physically removed: it is cleared to an empty correction marker (content fields reset, flagged as a pending correction) rather than hard-deleted, since the underlying PPF submission history must be preserved.

Server-Side Flow

StepProcessDescription
1AuthenticationThe R-Auth JWT is validated; uid extracted.
2Company resolution & authorizationThe report's owning company is resolved from reportId; the caller must hold ADMIN on that company.
3Provenance checkThe target report must be manually-created and one of the four manual-supported families.
4Status/family-specific deletion ruleSee "Important" above — Transaction requires DRAFT/CORRECTABLE; Payment allows MERGED (converted to a correction marker) but blocks if a transmission is in flight.
5ResponseReturns HTTP 204 No Content on success.

Endpoint Information

PropertyValue
URL/reporting/FR/report/{reportId}
MethodDELETE
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token) — caller must additionally be ADMIN on the report's owning company

Example Request

curl --location --request DELETE 'https://api-fr-stage.docnova.ai/reporting/FR/report/<report-id>' \
--header 'Accept: */*' \
--header 'R-Auth: <jwt-token>'

This endpoint has no query parameters and no request body. The only input is the reportId path variable and the authentication token.

Request Parameters

Path Parameters

ParameterTypeRequiredDescription
reportIdUUIDYesThe Docnova system UUID of the report to delete.

Responses

204 - Successful Response

Returns HTTP 204 No Content, empty body. The report has been deleted (Transaction) or cleared to a correction marker (Payment, if it was MERGED).

400 - Bad Request

{
"errorMessage": "Report not found",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

400 - Bad Request: Not Deletable

{
"errorMessage": "Transaction reports that are merged into an in-flight or already-submitted transmission cannot be deleted.",
"errorType": "MANUAL_TRANSACTION_REPORT_NOT_DELETABLE",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

Condition: A TRANSACTION_B2B/TRANSACTION_B2C report is not currently in a deletable status (DRAFT/CORRECTABLE).

400 - Bad Request: Transmission In Flight

{
"errorMessage": "This report's transmission is still in flight (awaiting PPF acknowledgment) and cannot be edited or deleted yet.",
"errorType": "MANUAL_REPORT_TRANSMISSION_IN_FLIGHT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

Condition: A MERGED Payment report whose containing transmission is currently awaiting PPF acknowledgment.

400 - Bad Request: Not Manually Created

{
"errorMessage": "This report was not created manually and cannot be edited or deleted through the manual report endpoints.",
"errorType": "MANUAL_REPORT_ACTION_NOT_ALLOWED_FOR_AUTO_REPORT",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

401 - Unauthorized

Returned both when the R-Auth header is missing/expired, and when the caller is authenticated but is not ADMIN on the report's owning company.

{
"errorMessage": "User is not authorized for this operation",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

500 - Internal Server Error

{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/report/<report-id>"
}

22. Reporting Get XML GET

Purpose of Use: Downloads the raw XML content that was (or would be) submitted to PPF for a single report occurrence, returned directly as application/xml rather than wrapped in a JSON envelope. Used for legal archival of the exact document transmitted, or to inspect the generated XML for troubleshooting.

This endpoint is used for the following purposes:

  • Compliance archival: Storing the exact XML transmitted to PPF for a given report, for legal retention requirements.
  • Pre-submission preview: Inspecting what the generated XML will look like for a DRAFT report before it is submitted.
  • Rejection diagnosis: Reviewing the exact XML that was sent, when investigating a content-level PPF rejection.

Important — XML source depends on report state:

Report StateXML Source
Report has its own stored XMLReturned as-is from storage — the exact document already transmitted.
MERGED into a batch, no own stored XMLInherited from the parent batch's stored XML.
Neither of the above (e.g. still DRAFT)Generated on the fly as a preview — reflects the current item content, not yet a submitted document.

Server-Side Flow

StepProcessDescription
1AuthenticationThe R-Auth JWT is validated; uid extracted.
2Company resolution & authorizationThe report's owning company is resolved from reportId; the caller must hold ADMIN on that company.
3XML resolutionSee the "Important" table above — stored XML, inherited batch XML, or a generated preview, in that priority order.
4ResponseReturns HTTP 200 OK with the raw XML string as the response body (Content-Type: application/xml), not a JSON wrapper.

Endpoint Information

PropertyValue
URL/reporting/FR/xml/{reportId}
MethodGET
Content-Typeapplication/xml
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token) — caller must additionally be ADMIN on the report's owning company

Example Request

curl --location 'https://api-fr-stage.docnova.ai/reporting/FR/xml/<report-id>' \
--header 'Accept: application/xml' \
--header 'R-Auth: <jwt-token>'

This endpoint has no query parameters and no request body. The only input is the reportId path variable and the authentication token.

Request Parameters

Path Parameters

ParameterTypeRequiredDescription
reportIdUUIDYesThe Docnova system UUID of the report whose XML you want to retrieve.

Responses

200 - Successful Response

Returns HTTP 200 OK with the raw XML document as the response body (Content-Type: application/xml) — not JSON.

<?xml version="1.0" encoding="UTF-8"?>
<TransactionReport>
...
</TransactionReport>

400 - Bad Request

{
"errorMessage": "Report not found",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/xml/<report-id>"
}

401 - Unauthorized

Returned both when the R-Auth header is missing/expired, and when the caller is authenticated but is not ADMIN on the report's owning company.

{
"errorMessage": "User is not authorized for this operation",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/xml/<report-id>"
}

500 - Internal Server Error

Returned when an unexpected error occurs — for example if the report is MERGED but its parent batch record cannot be found, or S3 retrieval of a stored XML fails.

{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/xml/<report-id>"
}

23. Reporting Search Status GET

Purpose of Use: This endpoint fetches the full detail and current status snapshot of a single France PPF report record identified by its Docnova-assigned reportId. It is the primary single-record status lookup used by the Docnova frontend to display the detail view of a specific report, and can be called programmatically to poll for status changes after a report has been submitted.

Under the French e-invoicing mandate, mandatory from 01/09/2026, every B2B/B2C transaction data and payment report sent to the PPF (Portail Public de Facturation) passes through a multi-stage lifecycle. The PPF asynchronously returns an acknowledgement (accusé de réception) — either Ok, Error, Pending, or Processing. This endpoint exposes the most recently persisted version of that acknowledgement alongside the full report record.

This endpoint is used for the following purposes:

  • Single-report detail view: The frontend calls this endpoint after a user clicks on a specific report in the reporting list to show its full detail, including PPF flow ID, rejection reason, and submission timeline.
  • Status verification after submission: Integrations can poll this endpoint after a report submission to determine whether the PPF has accepted or rejected it without fetching the full list.
  • PPF error diagnosis: When a report is REJECTED, the response includes ppfErrorCode and ppfErrorMessage populated from the PPF acknowledgement detail, allowing developers and support teams to understand the exact rejection reason.
  • Deadline monitoring: The submissionDeadline field is returned, enabling client applications to display urgency indicators for reports not yet submitted.

Important: This endpoint reads the cached status stored in the Docnova database. It does not actively call the PPF API on each request. The PPF acknowledgement status is refreshed by a background scheduler (pollSingleReportStatus) that periodically queries the PPF and updates the stored record. To see the very latest PPF status, the background polling must have run since the last PPF state change.

Server-Side Flow

StepProcessDescription
1AuthenticationThe R-Auth JWT is validated by the Spring Security filter chain. The authenticated user's uid is extracted via @AuthenticationPrincipal JwtUser.
2Report lookupThe service calls reportRepository.findById(reportId). If no record exists for this UUID, IllegalArgumentException("Report not found") is thrown and mapped to 400.
3DTO mappingThe found FranceReportEntity is mapped to FranceReportResponse via toResponse(). All persisted fields, including PPF acknowledgement data, are included.
4ResponseReturns HTTP 200 OK with the full FranceReportResponse JSON object.

🛰️ Background PPF polling (separate process): A scheduler (pollSingleReportStatus) periodically calls the PPF's flow status API, maps the PPF acknowledgement (Ok → ACCEPTED, Error → REJECTED) and persists the updated status back to the database. This endpoint reads that persisted state.

Endpoint Information

PropertyValue
URL/reporting/FR/status/{reportId}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/reporting/FR/status/{reportId}' \
--header 'Accept: */*' \
--header 'R-Auth: <jwt-token>'

This endpoint has no query parameters and no request body. The only input is the reportId path variable and the authentication token.

Request Parameters

Path Parameters

ParameterTypeRequiredFormat / ExampleDescription
reportIdUUIDYes0034cdf6-3032-4fe1-b276-21a83191aeeeThe Docnova system UUID of the specific France report record to retrieve. Obtained from the reportId field of the GET /reporting/FR/list response.

Responses

200 - Successful Response

Returns HTTP 200 OK with a single FranceReportResponse JSON object.

{
"reportId": "0034cdf6-3032-4fe1-b276-...",
"status": "ACCEPTED",
"reportType": "TRANSACTION_B2C",
"source": "PORTAL",
"category": "SERVICE",
"senderSiren": "123456789",
"ppfFlowId": "FRR-10.3-20260609-00042",
"trackingId": "TRK-9988776655",
"invoiceId": "aaaabbbb-cccc-dddd-eeee-...",
"invoiceNumber": "INV-2026-00451",
"itemCount": 3,
"totalAmount": 4850.00,
"submittedTime": "2026-06-09T10:15:00",
"createdTime": "2026-06-09T10:14:32",
"submissionDeadline": "2026-06-19T23:59:59",
"ppfAckStatus": "Ok",
"ppfErrorMessage": null,
"ppfErrorCode": null,
"lastStatusCheckTime": "2026-06-09T10:16:00"
}
{
"reportId": "0034cdf6-3032-4fe1-b276-...",
"status": "REJECTED",
"ppfAckStatus": "Error",
"ppfErrorMessage": "Le SIREN déclarant n'est pas enregistré dans l'annuaire PPF",
"ppfErrorCode": "501",
"lastStatusCheckTime": "2026-06-09T10:16:00"
}
Response Body — Report Status Fields
FieldTypeNullableDescription
reportIdUUIDNoUnique identifier of this report record in the Docnova system. Matches the reportId passed in the path.
statusFranceReportStatusNoCurrent Docnova-side lifecycle status of the report. Derived from PPF acknowledgement — transitions to ACCEPTED when ppfAckStatus = Ok, and to REJECTED when ppfAckStatus = Error.
reportTypeFranceReportTypeYesSpecific report type: B2C or B2B, transaction or payment declaration.
sourceInvoiceSourceYesOrigin channel of the underlying invoice document, for example PORTAL, ERP, or PPF.
categoryFranceCategoryYesBusiness nature of the reported transaction: SERVICE, GOODS, MIXED, or NON_TAXABLE.
senderSirenstringYes9-digit SIREN of the invoice sender, also known as the declarant company.
ppfFlowIdstringYesThe PPF-assigned flow identifier returned when the report was submitted, for example FRR-10.3-.... null before submission. Used internally by the background scheduler to poll PPF status.
trackingIdstringYesInternal Docnova tracking reference for this submission attempt.
invoiceIdUUIDYesDocnova UUID of the underlying invoice document this report is based on.
invoiceNumberstringYesHuman-readable invoice reference number.
itemCountintegerYesNumber of line items included in this report.
totalAmountBigDecimalYesTotal monetary amount reported, in the currency of the underlying invoice.
submittedTimeLocalDateTimeYesTimestamp when the report was successfully dispatched to the PPF. null if not yet submitted.
createdTimeLocalDateTimeNoTimestamp when the report record was created in the Docnova system.
submissionDeadlineLocalDateTimeYesThe PPF-mandated deadline by which this report must be submitted. Calculated from the company's vatRegime and the reporting period. null if not yet calculated.
ppfAckStatusstringYesRaw acknowledgement status string returned by the PPF. Possible values: Ok, Error, Pending, Processing. null if no PPF response received yet.
ppfErrorMessagestringYesHuman-readable rejection reason from the PPF acknowledgement detail. Populated only when ppfAckStatus = Error. Contains the PPF's reasonMessage from the first detail entry.
ppfErrorCodestringYesMachine-readable error code from the PPF. Populated when ppfAckStatus = Error. Contains the reasonCode from the PPF detail, or defaults to 501 (IRRECEVABLE) if no detail was returned.
lastStatusCheckTimeLocalDateTimeYesTimestamp of the most recent background PPF status polling attempt for this report. Used to assess staleness of the ppfAckStatus value.

PPF Acknowledgement Status Values

The ppfAckStatus field reflects the raw value returned by the PPF acknowledgement.status field. The background scheduler maps these values to the Docnova status field.

PPF Ack StatusMeaningDocnova Status Mapping
OkThe PPF has fully accepted and processed the report. No errors found.ACCEPTED
ErrorThe PPF rejected the report. ppfErrorCode and ppfErrorMessage contain the rejection details from PPF acknowledgement detail entries.REJECTED
PendingThe PPF has received the report but has not yet started processing it. Status will be polled again by the background scheduler.No Docnova status change
ProcessingThe PPF is currently validating the report. Status will be polled again by the background scheduler.No Docnova status change

⚠️ PPF error codes: When ppfAckStatus = Error, the ppfErrorCode field contains a Chorus Pro / PPF status code. The most common values are 500 (RECEVABLE — accepted) and 501 (IRRECEVABLE — rejected). If the PPF returns an error without detail entries, the code defaults to 501.

Enum Values

FranceReportStatus — Report Lifecycle Status

ValueDescription
DRAFTReport created but not yet sent for validation. Initial state.
VALIDATINGReport is undergoing format and business rule validation before submission.
SUBMITTEDReport dispatched to the PPF; awaiting acknowledgement (ppfAckStatus is Pending or Processing).
ACCEPTEDPPF returned ppfAckStatus = Ok. Report successfully processed.
REJECTEDPPF returned ppfAckStatus = Error. See ppfErrorCode and ppfErrorMessage for details.
ERRORA Docnova system-level failure prevented submission. Not a PPF rejection.
REPORTEDReport acknowledged and included in a PPF period summary.
MERGEDReport was merged with another period report.

FranceReportType — Specific Report Type

ValueGroupFlow PrefixDescription
TRANSACTION_B2CE_REPORTINGFRR-10.3B2C transaction e-report, domestic sales to non-business customers.
TRANSACTION_B2BE_REPORTINGFRR-10.1B2B international transaction e-report.
PAYMENT_B2BPAYMENTFRR-10.2B2B payment declaration report.
PAYMENT_B2CPAYMENTFRR-10.4B2C payment declaration report.

FranceCategory — Transaction Business Category

ValueDescription
SERVICEService-based items only.
GOODSPhysical goods only.
MIXEDBoth goods and services.
NON_TAXABLEOutside the scope of French TVA.

All error responses share the following structure:

{
"errorMessage": "<human-readable message>",
"errorType": "<error type key>",
"errorTitle": "<HTTP status name>",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/status/0034cdf6-3032-4fe1-b276-21a83191aeee"
}

400 - Bad Request

Returned when no report record exists in the Docnova database for the given reportId UUID.

{
"errorMessage": "Report not found",
"errorType": "BAD_REQUEST",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/status/0034cdf6-3032-4fe1-b276-21a83191aeee"
}

Condition: No report record exists in the Docnova database for the given reportId UUID. The ID may be incorrect, belong to a different company, or have been deleted.

Server behavior: reportRepository.findById() returns empty → service throws IllegalArgumentException("Report not found")RestExceptionHandler maps to 400.

400 - Bad Request: Invalid UUID Format

Returned when the reportId path variable is not a valid UUID string.

{
"errorMessage": "Invalid request parameters",
"errorType": "VALIDATION_ERROR",
"errorTitle": "BAD_REQUEST",
"status": 400,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/status/invalid-id"
}

Condition: The reportId path variable is not a valid UUID string, for example missing hyphens, wrong length, or non-hex characters.

Server behavior: Spring's path variable type conversion to UUID fails → BindException is thrown and caught by RestExceptionHandler.

401 - Unauthorized

Returned when the R-Auth header is missing, malformed, or the JWT token is expired.

{
"errorMessage": "Not authorized for this action",
"errorType": "NOT_AUTHORITY",
"errorTitle": "UNAUTHORIZED",
"status": 401,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/status/0034cdf6-3032-4fe1-b276-21a83191aeee"
}

Condition: The R-Auth header is missing, malformed, or the JWT exp claim has passed.

Server behavior: Spring Security filter chain rejects the request before it reaches the controller.

500 - Internal Server Error

Returned when an unexpected runtime exception occurs while processing the request.

{
"errorMessage": "An unexpected error occurred",
"errorType": "RUNTIME_ERROR",
"errorTitle": "INTERNAL_SERVER_ERROR",
"status": 500,
"timestamp": "2026-06-20T17:26:56.155059",
"path": "/reporting/FR/status/0034cdf6-3032-4fe1-b276-21a83191aeee"
}

Condition: Unexpected runtime exception, such as database connectivity failure, JPA query error, or entity-to-DTO mapping failure.

Server behavior: RuntimeException or Exception handler fires; error is logged server-side with stack trace.

24. Reporting Search Reports GET

Purpose of Use: This endpoint lists e-reporting and payment notification records created under France's mandatory tax reporting system in a paginated and filterable format. Under French tax law, businesses are required to submit two types of mandatory reports to the PPF (Plateforme Publique de Facturation):

  • E-Reporting: Periodic submission of tax data for B2C and international B2B transactions
  • Payment Reporting: Reporting of invoice payments from prior periods to the PPF

This endpoint allows querying both report groups through a single list interface. Rich filter options allow narrowing results by company, SIREN number, date range, report type, status, source channel, or PPF acknowledgement status. Results follow the standard Spring Data Page structure, making it possible to control page size and sorting for large datasets.

Typical use cases:

  • Listing all French tax reports for a specific company on a dashboard
  • Identifying failed or rejected reports using status=REJECTED or status=ERROR
  • Tracking PAYMENT_B2C type reports submitted within a specific date range
  • Monitoring pending reports by filtering on ppfAckStatus
  • Isolating reports for transactions from a specific sales channel using source=EBAY

Endpoint Information

PropertyValue
URL/reporting/FR/list
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/reporting/FR/list?companyId={companyId}&pageNumber=0&pageSize=20&dateFrom=2026-06-09&dateTo=2026-06-17&reportGroup=E_REPORTING' \
--header 'accept: */*' \
--header 'accept-language: en-US,en;q=0.9,tr;q=0.8,tk;q=0.7' \
--header 'content-type: application/json' \
--header 'origin: https://app-fr-stage.docnova.ai' \
--header 'priority: u=1, i' \
--header 'r-auth: '<JWT_TOKEN>' \
--header 'referer: https://app-fr-stage.docnova.ai/invoice-reporting' \
--header 'sec-ch-ua: "Google Chrome";v="149", "Chromium";v="149", "Not)A;Brand";v="24"' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'sec-ch-ua-platform: "Windows"' \
--header 'sec-fetch-dest: empty' \
--header 'sec-fetch-mode: cors' \
--header 'sec-fetch-site: same-site' \
--header 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36'

Request Parameters

Query Parameters

FieldTypeRequiredDescription
companyIdstring (UUID)YesThe unique identifier (UUID) of the company whose reports are being queried.
reportTypestring (enum)NoReport type filter. Narrows results to a specific transaction or payment type.
reportGroupstring (enum)NoReport group filter. If reportType is not specified, returns all types within this group.
sourcestring (enum)NoThe source platform or channel through which the invoice/transaction was created.
statusstring (enum)NoProcessing status filter for the report.
ppfAckStatusstringNoThe acknowledgement/notification status returned by PPF. Free-text, case-sensitive match.
categorystring (enum)NoInvoice/transaction category filter.
dateFromstring (date)NoStart date filter (inclusive). ISO 8601 format: YYYY-MM-DD. Matches from start of day.
dateTostring (date)NoEnd date filter (inclusive). ISO 8601 format: YYYY-MM-DD. Matches up to start of the following day.
sirenstringNoThe 9-digit SIREN number of the sending company. Performs a LIKE search on both the senderSiren field and the raw request JSON.
pageNumberintegerNoPage number to retrieve (0-based). Default: 0.
pageSizeintegerNoNumber of records per page. Default: 20.
sort.sortedbooleanNoIndicates whether sorting is applied. Managed via Spring Pageable.
sort.unsortedbooleanNoIndicates no sorting is applied.
offsetintegerNoPagination offset for the starting position.
pagedbooleanNoWhether a paged response is requested. Default: true.
unpagedbooleanNoWhether all records should be returned without pagination. Default: false.

Parameter Value Tables

reportType Possible Values

ValueGroupPPF Flow CodeDescription
TRANSACTION_B2CE_REPORTINGFRR-10.3E-reporting of B2C individual customer transaction data.
TRANSACTION_B2BE_REPORTINGFRR-10.1E-reporting of international B2B transaction data.
PAYMENT_B2BPAYMENTFRR-10.2Payment notification for B2B invoices.
PAYMENT_B2CPAYMENTFRR-10.4Payment notification for B2C invoices.

reportGroup Possible Values

ValueDescription
PAYMENTPayment notifications group. Includes PAYMENT_B2B and PAYMENT_B2C.
E_REPORTINGElectronic reporting group. Includes TRANSACTION_B2C and TRANSACTION_B2B.

status Possible Values

ValueDescription
DRAFTDraft. Not yet submitted and still editable.
VALIDATINGValidating. Being checked by the system before transmission to PPF.
SUBMITTEDSubmitted. Transmitted to PPF and awaiting acknowledgement.
ACCEPTEDAccepted. Successfully processed by PPF.
REJECTEDRejected. Refused by PPF and correction is required.
ERRORError. Transmission failed due to a technical error.
REPORTEDReported. Processing completed.
MERGEDMerged. Combined into another report.

category Possible Values

ValueDescription
SERVICEService invoice.
GOODSGoods or product invoice.
MIXEDMixed invoice containing both goods and services.
NON_TAXABLETransaction not subject to VAT.

source Selected Values

ValueDescription
PORTALCreated via web portal.
ERPERP system integration.
PEPPOLReceived via the PEPPOL network.
EBAYeBay sales channel.
SHOPIFYShopify e-commerce platform.
AMAZON_SPAmazon Seller Platform.
SFTPSFTP file transfer.
PPFDirectly from the PPF platform.
EMAILReceived via email.
MOBILEMobile application.
STRIPEStripe payment system.
TEMUTemu sales channel.

For the full list, refer to the InvoiceSource enum. Other values include: PORTAL_OCR, MOBILE_OCR, EMAIL_OCR, SERVICE, HARVEST, HUBSPOT, ANAF, LAZADA, KSEF, RS_API, ETA, ERACUN, KSEF_OFFLINE, LHDNM, NEMHANDEL.

Responses

200 - Successful Response

{
"content": [
{
"reportId": "3fa85f64-5717-4562-b3fc-...",
"status": "ACCEPTED",
"reportType": "PAYMENT_B2C",
"source": "EBAY",
"category": "NON_TAXABLE",
"senderSiren": "271688503",
"ppfFlowId": "FRR-10.4-20240101-001",
"trackingId": "TRK-2024-00123",
"invoiceId": "8a1e4c2d-1234-4abc-9def-...",
"invoiceNumber": "INV-2024-00456",
"itemCount": 12,
"totalAmount": 1540.50,
"submittedTime": "2024-06-01T10:30:00",
"createdTime": "2024-05-31T08:15:00",
"submissionDeadline": "2024-06-10T23:59:59",
"ppfAckStatus": "Ok",
"ppfErrorMessage": null,
"ppfErrorCode": null,
"lastStatusCheckTime": "2024-06-01T11:00:00"
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageNumber": 0,
"pageSize": 20,
"paged": true,
"unpaged": false
},
"totalPages": 5,
"totalElements": 87,
"last": false,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"size": 20,
"number": 0,
"first": true,
"numberOfElements": 20,
"empty": false
}
content[] — Report Record Fields
FieldTypeDescription
reportIdstring (UUID)Unique identifier of the report. Used as a reference in subsequent report operations.
statusstring (enum)Current processing status of the report. Uses FranceReportStatus.
reportTypestring (enum)Report type. Uses FranceReportType. Indicates which PPF flow this report belongs to.
sourcestring (enum)Source platform or channel through which the invoice/transaction was created. Uses InvoiceSource.
categorystring (enum)Invoice category. Uses FranceCategory.
senderSirenstring9-digit SIREN number of the sending company.
ppfFlowIdstringFlow identifier assigned by PPF. Used for tracking and debugging.
trackingIdstringInternal system tracking identifier.
invoiceIdstring (UUID)UUID of the invoice associated with this report.
invoiceNumberstringHuman-readable invoice number.
itemCountintegerNumber of transactions or line items covered by this report.
totalAmountnumber (decimal)Total monetary amount of the report.
submittedTimestring (datetime)Date and time the report was transmitted to PPF. ISO 8601 format.
createdTimestring (datetime)Date and time the report was created in the system. ISO 8601 format.
submissionDeadlinestring (datetime)Latest date and time by which the report must be submitted. ISO 8601 format.
ppfAckStatusstringAcknowledgement status text returned by PPF, for example Ok, Error, or Pending.
ppfErrorMessagestring | nullError message returned by PPF upon rejection.
ppfErrorCodestring | nullError code returned by PPF.
lastStatusCheckTimestring (datetime)Date and time of the most recent PPF status check. ISO 8601 format.

400 - Bad Request

Returned when an invalid value is sent for an enum-type parameter, such as status, reportType, or category.

{
"error": "BAD_REQUEST",
"message": "Failed to convert value of type 'String' to required type 'FranceReportStatus'; nested exception is: No enum constant FranceReportStatus.INVALID_VALUE",
"code": "INVALID_PARAMETER"
}

Description: Sending a value outside the defined enum set, such as status=INVALID_VALUE or reportType=UNKNOWN, causes a Spring type conversion failure. Providing dateFrom or dateTo in a format other than YYYY-MM-DD also triggers this error.

400 - Bad Request: Missing Required companyId

Returned when the mandatory companyId query parameter is absent.

{
"error": "BAD_REQUEST",
"message": "Required request parameter 'companyId' for method parameter type UUID is not present",
"code": "MISSING_PARAMETER"
}

Description: companyId is the only mandatory parameter for this endpoint and must be in UUID format. A missing value or an improperly formatted UUID, such as companyId=abc123, triggers this error.

401 - Unauthorized

Returned when the JWT token in the R-Auth header cannot be verified.

{
"error": "UNAUTHORIZED",
"message": "Invalid or expired authentication token",
"code": "AUTH_TOKEN_INVALID"
}

Description: The token has expired, its signature is invalid, or the header is missing entirely. Token TTL is 50 minutes.

403 - Forbidden

Returned when the authenticated user does not have access rights to reports belonging to the specified companyId.

{
"error": "FORBIDDEN",
"message": "Access denied to company reports",
"code": "ACCESS_DENIED"
}

Description: The authorization layer rejects the request when a user attempts to query reports using a companyId that does not belong to them.

500 - Internal Server Error

Returned when an unexpected error occurs during the database query or data transformation.

{
"error": "INTERNAL_SERVER_ERROR",
"message": "An unexpected error occurred while processing your request",
"code": "GENERAL_ERROR"
}

Description: Thrown when an unexpected error occurs in the JPA specification filter or the toResponse() data conversion method.

25. CDV/CDAR Lifecycle Overview

Purpose of Use: Four read/write endpoints for tracking and driving a French invoice through its CDV (Compte-rendu de Dépôt Vérifié) status lifecycle once it has been submitted via send-document-async / send-document-async-json.

A French invoice does not have one status. It has a snapshot showing where things stand right now, and a history showing every CDAR status event recorded so far, inbound or outbound.

These two are separate tables in the backend and separate endpoints here:

EndpointReturns
GET /cdar/last-cdv/{companyId}/{invoiceId}One object, current status
GET /cdar/history/{invoiceId}?companyId=Array, every status event, oldest first
POST /cdar/submit?statusName=Success or failure envelope
GET /cdar/detail/{invoiceCdvHistoryId}One object, full detail plus raw CDAR XML

Path parameter to have on hand: invoiceId in all four endpoints is Docnova's internal InvoiceEntity UUID, not the business invoice number, e.g. <INVOICE_NUMBER>.

The buyer and seller each hold their own separate InvoiceEntity for the same business invoice, so this UUID is different on each side.

Resolve it via get-document-status-by-tracking after submission, or via /invoice/search-documents.

Which one do I need?

Question you're answeringCall thisWhere you'd use it
"What's this invoice's CDV status right now?"last-cdvStatus badge in an invoice list, one lightweight call per invoice.
"How did it get there, what happened, and in what order?"historyTimeline or audit trail on an invoice detail page. This returns every event, so reserve it for detail views.

CDV/CDAR Status Code Reference

Full FranceProcessConditionCode enum as implemented. Includes statuses produced automatically by the platform, 200 to 203, alongside the manual ones from section 28, so both endpoints can be read against one table.

NameCodeLabelCategoryTerminalProduced via
DEPOSEE200DéposéeMandatoryAutomatic, invoice send
EMISE201Émise par la plateformeOptionalAutomatic, invoice send
RECUE202Reçue de la plateformeRecommendedAutomatic, inbound processing
MISE_A_DISPOSITION203Mise à dispositionRecommendedAutomatic, inbound processing
REJETEE213RejetéeMandatoryYesAutomatic, validation failure
PRISE_EN_CHARGE204Prise en chargeRecommended/cdar/submit, recipient
APPROUVEE205ApprouvéeRecommended/cdar/submit, recipient
APPROUVEE_PARTIELLEMENT206Approuvée partiellementRecommended/cdar/submit, recipient
EN_LITIGE207En litigeOptional/cdar/submit, recipient
SUSPENDUE208SuspendueOptional/cdar/submit, recipient
COMPLETEE209ComplétéeOptional/cdar/submit, sender
REFUSEE210RefuséeMandatoryYes/cdar/submit, recipient
PAIEMENT_TRANSMIS211Paiement transmisRecommended/cdar/submit, recipient
ENCAISSEE212EncaisséeMandatoryYes/cdar/submit, sender
VISEE214ViséeOptional/cdar/submit, sender
ANNULEE220AnnuléeOptionalYesAutomatic, on confirmation of a corrective document

Category (Mandatory / Recommended / Optional) is the StatusCategory value from the backend enum, not a restatement of the CDV specification text.

"Reaches PPF" in the tables below reflects the platform routing rule in code: only DEPOSEE, REJETEE, REFUSEE and ENCAISSEE are ever forwarded to PPF. Every other status is exchanged with the counterparty, PA, only.

Four terminal statuses. Once REFUSEE (210), ENCAISSEE (212), REJETEE (213) or ANNULEE (220) has been recorded, the lifecycle is closed and no further CDAR can be produced for that invoice.

ANNULEE is not submittable. It appears in this table because it can show up in last-cdv and history, but the platform produces it itself when a corrective document for the invoice is confirmed. POST /cdar/submit?statusName=ANNULEE returns CDAR_MANUEL_TRIGGER_FAILED.

24-hour PPF submission deadline: Per the specification, the four statuses that reach PPF — DEPOSEE (200), REFUSEE (210), ENCAISSEE (212) and REJETEE (213) — must reach the tax authority within 24 hours of being produced.


26. Get Current CDV Status GET

Purpose of Use: Returns the single current state snapshot for one invoice: latest CDV status, PPF transmission tracking, and lifecycle state. Use this for a status badge or summary view. Use history for the full timeline.

Rendering a status badge in an invoice list, one lightweight call per invoice, no need to fetch the full history.

For example, right after submitting invoice <INVOICE_NUMBER>, this endpoint returned currentCdvStatus: "EMISE", ppfAckStatus: "Pending". Enough on its own to show something like Delivered to platform, pending PPF acknowledgement in a list row, without touching history at all.

Endpoint Information

PropertyValue
URL/cdar/last-cdv/{companyId}/{invoiceId}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/cdar/last-cdv/{companyId}/{invoiceId}' \
--header 'R-Auth: <AUTH_TOKEN>'

Request Parameters

Path Parameters

FieldTypeRequiredDescription
companyIdUUIDYesDocnova company ID for the side viewing the invoice, buyer or seller.
invoiceIdUUIDYesDocnova InvoiceEntity ID, scoped to companyId.

Responses

200 - Successful Response

{
"id": "<ID>",
"invoiceNumber": "<INVOICE_NUMBER>",
"invoiceTypeCode": "380",
"invoiceDate": "<INVOICE_DATE>",
"currentCdvStatus": "DEPOSEE",
"invoiceStatus": "FR_DEPOSITED",
"source": "PORTAL",
"platform": "PPF",
"direction": "OUTBOUND",
"lifecycleStatus": "SUBMITTED",
"ppfFlowId": "<PPF_FLOW_ID>",
"trackingId": "<TRACKING_ID>",
"senderSiren": "<SENDER_SIREN>",
"recipientSiren": "<RECIPIENT_SIREN>",
"ppfAckStatus": "Pending",
"ppfErrorMessage": null,
"createdTime": "<CREATED_TIME>",
"submittedTime": "<SUBMITTED_TIME>",
"lastCdvReceivedTime": "<LAST_CDV_RECEIVED_TIME>"
}

Response Fields

FieldTypeDescription
idUUIDID of the CDV snapshot row itself.
invoiceNumberstringBusiness invoice number.
invoiceTypeCodestringUBL invoice type code, e.g. 380. Derived from the linked invoice; absent if not linked.
invoiceDatedatetimeInvoice issue date, from the linked invoice.
currentCdvStatusenumCurrent CDV status code name. See the status reference in section 25.
invoiceStatusenumDocnova's internal invoice lifecycle status, derived from currentCdvStatus for most statuses, e.g. DEPOSEE to FR_DEPOSITED.
sourceenumChannel the invoice originated from: PORTAL, ERP, SFTP, PEPPOL, etc.
platformenumPA or PPF, which platform the last recorded CDAR variant targeted.
directionenumOUTBOUND if this company produced it, or INBOUND if this company received it.
lifecycleStatusenumTransmission state of the CDAR itself: GENERATED, SUBMITTED, ERROR, etc.
ppfFlowId/trackingIdstringIdentifiers from the PPF SFTP transmission, when applicable.
senderSiren/recipientSirenstringSIREN of invoice supplier / customer.
ppfAckStatusstringFree-text PPF acknowledgement state, e.g. Pending, Error.
ppfErrorMessagestringPopulated only when the PPF transmission failed.
createdTime/submittedTime/lastCdvReceivedTimedatetimeSnapshot bookkeeping timestamps.

Field behavior

FieldPossible ValuesWhat Determines It
currentCdvStatusDEPOSEE, EMISE, RECUE, MISE_A_DISPOSITION, PRISE_EN_CHARGE, APPROUVEE, APPROUVEE_PARTIELLEMENT, EN_LITIGE, SUSPENDUE, COMPLETEE, REFUSEE, PAIEMENT_TRANSMIS, ENCAISSEE, REJETEE, VISEE, ANNULEEThe status of the most recent CDAR event recorded for this invoice, whichever side produced it. See the status reference in section 25 for what each code means.
invoiceStatusFR_DEPOSITED, FR_PLATFORM_ISSUED, FR_RECEIVED, FR_AVAILABLE, FR_PROCESSING, FR_APPROVED, FR_PARTIALLY_APPROVED, FR_DISPUTED, FR_SUSPENDED, FR_REFUSED, FR_PAYMENT_SENT, FR_COLLECTED, FR_REJECTED, FR_CANCELLEDMirrors currentCdvStatus for every status except COMPLETEE and VISEE, which have no mapped value. Reaching either of those leaves invoiceStatus unchanged from whatever it was before.
sourcePORTAL, ERP, SFTP, PEPPOLStarts out as the channel the invoice itself came in through. Portal UI becomes PORTAL, send-document-async-json becomes ERP. Switches to PEPPOL or SFTP the first time a status is actually delivered to the counterparty over one of those channels.
platformPA, PPFWhich side received the most recent status. When a status is sent to both the counterparty and the tax authority, this always shows PPF. Read it as "did the tax authority see this", not "who received it".
directionOUTBOUND, INBOUNDWhether the most recent event was one you produced, OUTBOUND, or one you received from the counterparty, INBOUND. Reflects only the latest event, so it can flip back and forth over the invoice's life.
lifecycleStatusGENERATED, SUBMITTED, ERROR, REJECTED_BY_601, LOT_RECEIVED, LOT_REJECTEDTracks whether this company's own CDAR has been delivered to the counterparty, not tied to whichever status currentCdvStatus currently shows.
ppfFlowIdfree-form ID stringTracking identifier for the file delivered to the tax authority. Use it to reference which specific submission a status came from. This reflects this company's own last delivery to the tax authority.
ppfAckStatusPending, Ok, Error, Failed, unknownTracks whether the tax authority has confirmed the DEPOSEE submission specifically. Pending means sent, no confirmation yet. Ok means confirmed accepted. Error means confirmed rejected. Failed means the delivery itself broke. unknown means no record found to check against yet.
ppfErrorMessagefree text or emptyPopulated only when a tax-authority submission failed.
createdTimedatetimeWhen this invoice's CDV record was first opened. Set once, never changes again.
submittedTimedatetime or emptyWhen this company's own CDAR was successfully delivered to the counterparty. Stays empty for statuses that only ever go to the tax authority, e.g. DEPOSEE, EMISE.
lastCdvReceivedTimedatetime or emptyThe last time a status arrived from the counterparty. Updates every time one arrives, not a one-time timestamp.

currentCdvStatusinvoiceStatus mapping

When this CDV status firesinvoiceStatus becomesWhen it happens
DEPOSEE (200)FR_DEPOSITEDPeppol AP delivery succeeds, automatic.
EMISE (201)FR_PLATFORM_ISSUEDImmediately after 200, automatic.
RECUE (202)FR_RECEIVEDThe counterparty's platform receives the invoice, automatic.
MISE_A_DISPOSITION (203)FR_AVAILABLEMade available to the buyer, automatic.
PRISE_EN_CHARGE (204)FR_PROCESSINGBuyer calls /cdar/submit to say "I'm reviewing this".
APPROUVEE (205)FR_APPROVEDBuyer approves the invoice.
APPROUVEE_PARTIELLEMENT (206)FR_PARTIALLY_APPROVEDBuyer approves part of the invoice.
EN_LITIGE (207)FR_DISPUTEDBuyer disputes the invoice.
SUSPENDUE (208)FR_SUSPENDEDBuyer suspends processing, e.g. pending more documents.
REFUSEE (210)FR_REFUSEDBuyer fully refuses the invoice. Terminal.
PAIEMENT_TRANSMIS (211)FR_PAYMENT_SENTBuyer reports that payment has been sent.
ENCAISSEE (212)FR_COLLECTEDSeller reports that payment has been collected. Terminal.
REJETEE (213)FR_REJECTEDTechnical or business-rule rejection. Terminal.
ANNULEE (220)FR_CANCELLEDThe platform cancels the invoice when a corrective document is confirmed. Terminal.

COMPLETEE and VISEE are not in this list. They have no mapped invoiceStatus, so firing either one leaves the field unchanged.

Error Responses

StatuserrorTypeCondition
403AUTHORIZATION_FAILEDThe R-Auth user has no role on companyId.
404FR_INVOICE_CDV_NOT_FOUNDNo CDV snapshot exists for this companyId + invoiceId pair.

27. Get CDV Status History GET

Purpose of Use: Returns every CDAR status event recorded for the invoice, oldest first, ordered by receivedAt. This is the audit trail behind the snapshot returned by last-cdv. It includes both statuses this company produced, OUTBOUND, and statuses it received from the counterparty, INBOUND.

Rendering a timeline / audit trail on an invoice detail page, e.g. for the same invoice <INVOICE_NUMBER>, this endpoint returns two ordered events: "<EVENT_TIME> Déposée: submitted to PPF", then "<EVENT_TIME> Émise: platform confirmed the deposit." This is a full array, heavier than last-cdv's single object, so reserve it for detail views rather than list screens.

Endpoint Information

PropertyValue
URL/cdar/history/{invoiceId}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/cdar/history/<INVOICE_ID>?companyId=<COMPANY_ID>' \
--header 'R-Auth: <AUTH_TOKEN>'

Request Parameters

Path Parameters

FieldTypeRequiredDescription
invoiceIdUUIDYesDocnova InvoiceEntity ID.

Query Parameters

FieldTypeRequiredDescription
companyIdUUIDYesCompany viewing the history. Results are scoped to both this ID and invoiceId together.

Responses

200 - Successful Response

Empty array if the invoice exists but has no recorded CDAR events yet. This endpoint does not 404.

Example, seller side, invoice <INVOICE_NUMBER>:

[
{
"id": "<ID>",
"cdarHistoryStatus": "SUBMITTED",
"source": "ERP",
"previousStatus": null,
"newStatus": "DEPOSEE",
"platform": "PPF",
"direction": "OUTBOUND",
"cdarDocumentId": "<CDAR_DOCUMENT_ID>",
"statusCode": "10",
"statusLabel": "Déposée",
"issuerRoleCode": "WK",
"issuerName": "<ISSUER_NAME>",
"reasonCode": null,
"reasonText": null,
"errorMessage": null,
"responseCode": null,
"sftpFileName": "<SFTP_FILE_NAME>",
"cdarIssuedAt": "<CDAR_ISSUED_AT>",
"statusDepositedAt": null,
"receivedAt": "<RECEIVED_AT>",
"sentAt": "<SENT_AT>",
"changedBy": "PA_SFTP_SYSTEM"
},
{
"id": "<ID>",
"cdarHistoryStatus": "GENERATED",
"source": "ERP",
"previousStatus": null,
"newStatus": "EMISE",
"platform": "PPF",
"direction": "OUTBOUND",
"cdarDocumentId": "<CDAR_DOCUMENT_ID>",
"statusCode": null,
"statusLabel": "Émise par la plateforme",
"issuerRoleCode": "WK",
"issuerName": "<ISSUER_NAME>",
"reasonCode": null,
"reasonText": null,
"errorMessage": null,
"responseCode": null,
"sftpFileName": null,
"cdarIssuedAt": "<CDAR_ISSUED_AT>",
"statusDepositedAt": null,
"receivedAt": "<RECEIVED_AT>",
"sentAt": null,
"changedBy": "PA_SFTP_SYSTEM"
}
]

Response Fields per array item

FieldPossible ValuesWhat it means
idUUIDID of this history row. Pass to /cdar/detail to fetch the raw CDAR XML.
cdarHistoryStatusGENERATED, SUBMITTED, RECEIVED, ERROR, REJECTED_BY_601, LOT_RECEIVED, LOT_REJECTEDWhether this specific event was actually delivered anywhere. GENERATED means recorded, not sent yet or ever. SUBMITTED means delivery succeeded. ERROR means delivery was attempted and failed, see errorMessage. RECEIVED is defined for inbound events, but not currently produced by the rows observed. A row created from an inbound CDAR reception shows GENERATED instead. REJECTED_BY_601 means the tax authority later flagged this exact event as invalid. LOT_RECEIVED / LOT_REJECTED is the tax authority's batch-level acknowledgement for it.
sourcePORTAL, ERP, SFTP, PEPPOLA snapshot of the invoice's own source value at the moment this specific event was recorded. It is not the channel this specific CDAR was delivered over, and not necessarily the same across every row of the same invoice's history. Early rows typically show the channel the invoice itself came in through, e.g. ERP for send-document-async-json. But once an earlier event for the same invoice is actually delivered to the counterparty over Peppol or SFTP, later rows can inherit that channel instead. Two rows in the same invoice history can legitimately show different values here.
previousStatusalways nullPresent in the response shape but not currently populated. Do not rely on it to reconstruct what status came before this one. Use array order, oldest first, instead.
newStatussame status list as currentCdvStatus, see the status code reference in section 25The CDV status this event represents.
platformPA, PPFWhich recipient this specific row's CDAR variant targeted. A single status can produce one row per platform, linked internally. For statuses that only ever target the tax authority, expect PPF here even before the row has actually been transmitted.
directionOUTBOUND, INBOUNDOUTBOUND if this company produced the CDAR. INBOUND if it was received from the counterparty.
cdarDocumentIdstringUnique CDAR document identifier, MDT-4. Different for every event, including twin PA/PPF rows for the same status.
statusCodestring or nullThe MDT-88 status code, when this status has one. Some statuses, e.g. EMISE, have no MDT-88 equivalent by design. null is not a data quality problem. On rows created from an inbound CDAR reception, this can instead carry the raw CDV status number, e.g. 202, rather than the MDT-88 code. Do not compare this value across rows for what looks like the same status.
statusLabelFrench label, e.g. "Déposée"Always populated, the French label for newStatus.
issuerRoleCodeWK, SE, BYWK means the platform is issuing on the company's behalf. SE means seller. BY means buyer. Automatic statuses 200 to 203 always show WK, the platform acting generically. Manual statuses submitted via /cdar/submit show the actual calling party's role instead: BY for buyer-initiated statuses, SE for seller-initiated ones.
issuerNamestringDisplay name of the CDAR issuer.
reasonCode/reasonTextstring or nullPopulated for the statuses that carry a reason: 206, 207, 208 and 210. Empty on every other status. reasonText echoes back the reason value sent on the request.
errorMessagestring or nullPopulated only when cdarHistoryStatus = ERROR.
responseCodeinteger or nullOnly ever set for a CDAR delivered to the counterparty over Peppol. Deliveries to the tax authority, PPF, leave this null even when they succeed. Do not treat null here as a failure signal on a platform: PPF row.
sftpFileNamestring or nullThe flux file name, populated only once this specific row has actually been transmitted. Stays null for events that are recorded but never sent.
cdarIssuedAtdatetimeWhen this event was recorded. Never changes afterwards.
statusDepositedAtdatetime or nullThe official deposit time as declared by the counterparty. Populated only on INBOUND rows. Always null on rows this company produced itself.
receivedAtdatetimeDespite the name, this is set at the same moment as cdarIssuedAt for outbound rows. It marks when the row was recorded, not a separate received event. This is also the field the array is ordered by.
sentAtdatetime or nullWhen this row's CDAR was actually transmitted. Stays null until and unless that happens.
changedByfixed value, e.g. PA_SFTP_SYSTEMA fixed system label stamped on every outbound row. Not tied to the invoice's actual source and not a real user or system identity.

Some events are recorded but never actually sent: Not every row in this array was transmitted anywhere. Some statuses are generated and logged purely for the record, with no delivery step at all.

EMISE (201) is a concrete example: on a normal invoice it always shows cdarHistoryStatus: GENERATED, sftpFileName: null and sentAt: null permanently. This does not mean delivery failed. It means this status is never actually submitted to either the counterparty or the tax authority.

Do not read a permanently GENERATED row as a stuck or broken delivery unless you have confirmed the status is expected to go anywhere in the first place.

Known gap: Rows created from an inbound CDAR reception, most commonly the counterparty's automatically-produced RECUE or MISE_A_DISPOSITION events arriving on your side, do not always populate direction or platform.

If you see a history entry with a status but no platform / direction, treat it as informational only, not as proof the counterparty received nothing. Cross-check against last-cdv's currentCdvStatus before assuming a gap in the timeline.

Error Responses

StatuserrorTypeCondition
403AUTHORIZATION_FAILEDThe R-Auth user has no role on companyId.

28. Submit Manual CDV Status POST

Purpose of Use: Produces one of the CDV processing/closing statuses on behalf of the caller's company, persists it, and forwards it to the counterparty and, for two specific statuses, to PPF.

This is what a buyer calls to take charge of, approve, dispute, suspend or refuse an invoice, and what a seller calls to supply documents, mark it collected, or mark it checked.

Endpoint Information

PropertyValue
URL/cdar/submit?statusName={statusName}
MethodPOST
Content-Typeapplication/json
Query ParameterstatusName required, one of the enum names in Allowed statusName values, e.g. EN_LITIGE. The enum name, not the numeric code — APPROUVEE, not 205. Case-sensitive.
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Requests

Buyer disputes an invoice, EN_LITIGE / 207:

curl --location --request POST 'https://api-fr-stage.docnova.ai/cdar/submit?statusName=EN_LITIGE' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <AUTH_TOKEN>' \
--data '{
"invoiceId": "<INVOICE_ID>",
"companyId": "<COMPANY_ID>",
"reasonCode": "TX_TVA_ERR",
"reason": "Incorrect VAT rate applied on line 1",
"requestedActionCode": "NIN",
"requestedAction": "Please issue a corrective invoice"
}'

Buyer suspends an invoice, SUSPENDUE / 208. This is the only status that requires characteristics:

curl --location --request POST 'https://api-fr-stage.docnova.ai/cdar/submit?statusName=SUSPENDUE' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <AUTH_TOKEN>' \
--data '{
"invoiceId": "<INVOICE_ID>",
"companyId": "<COMPANY_ID>",
"reasonCode": "JUSTIF_ABS",
"reason": "Delivery note missing — cannot process until supplied",
"characteristics": [
{ "currencyId": "EUR" }
]
}'

Buyer takes charge, PRISE_EN_CHARGE / 204. No status-specific fields:

curl --location --request POST 'https://api-fr-stage.docnova.ai/cdar/submit?statusName=PRISE_EN_CHARGE' \
--header 'Content-Type: application/json' \
--header 'R-Auth: <AUTH_TOKEN>' \
--data '{
"invoiceId": "<INVOICE_ID>",
"companyId": "<COMPANY_ID>"
}'

Request Parameters

FieldTypeRequiredDescription
invoiceIdUUIDYesDocnova InvoiceEntity ID, scoped to companyId.
companyIdUUIDYesCompany producing this status.
reasonCodestring206, 207, 208, 210Must be a value from that status's list. Validated — see Reason codes below.
reasonstring208, 210 · optional for 206, 207Free-text comment. Mandatory for Suspendue and Refusée: a reason code on its own is rejected.
requestedActionCodestring207 only, optionalClosed list of seven values — see below.
requestedActionstring207 only, optionalHuman-readable requested action.
characteristicsarray208 · optional for 207, 211, 212For 208, at least one entry must carry a non-empty currencyId. See item shape below.

There is no reasonText field on this endpoint. Free-text explanation belongs in reason. Fields sent for a status that does not use them are ignored.

characteristics[] item shape

FieldTypeDescription
idstringReference to which specific part of the original invoice this characteristic describes, e.g. a line, an amount, or a business term. Free text.
typeCodestringA short code identifying what kind of characteristic this is. Observed values: MPA used with PAIEMENT_TRANSMIS, MEN used with ENCAISSEE, DIV / DVA used with EN_LITIGE.
valueChangedIndicatorbooleanWhether this value differs from what was on the original invoice.
namestringA human-readable label for what this characteristic represents.
locationstringWhere in the original invoice this applies, an XPath-style reference.
valueAmountstringThe amount this characteristic carries. Required for ENCAISSEE, the amount collected.
currencyIdstringThe currency of valueAmount. Required for SUSPENDUE on at least one entry.
valueDateTimestringA date/time this characteristic carries, when relevant.
valuePercentstringA percentage this characteristic carries. Required for ENCAISSEE, the VAT rate.

For 208 (Suspendue) no typeCode is required. The only mandatory field is currencyId, and a single { "currencyId": "EUR" } entry satisfies it.

Allowed statusName values

Which values are accepted depends on whether the caller's company is the recipient (buyer, invoice was received) or the sender (seller, invoice was issued) of this specific invoice. This is inferred server-side from the invoice's own document type, not from the request.

If the caller is the recipient, buyer:

statusNameCodeLabelWhat it doesOnce per invoice?Reaches PPF?
PRISE_EN_CHARGE204Prise en chargeBuyer confirms receipt of the invoice and starts reviewing it.NoNo, PA only
APPROUVEE205ApprouvéeBuyer approves the invoice in full.YesNo, PA only
APPROUVEE_PARTIELLEMENT206Approuvée partiellementBuyer approves only part of the invoice. Which part is not carried in the CDAR itself. Resolve the details outside this API.NoNo, PA only
EN_LITIGE207En litigeBuyer disputes the invoice and requests a specific corrective action from the seller, e.g. a corrective invoice.NoNo, PA only
SUSPENDUE208SuspendueBuyer puts the invoice on hold, pending additional documents or information from the seller.NoNo, PA only
REFUSEE210RefuséeBuyer rejects the invoice outright.Yes, TerminalYes, PA + PPF
PAIEMENT_TRANSMIS211Paiement transmisBuyer confirms payment has been sent.NoNo, PA only

If the caller is the sender, seller:

statusNameCodeLabelWhat it doesOnce per invoice?Reaches PPF?
COMPLETEE209ComplétéeSeller supplies the documents or information the buyer requested via a prior SUSPENDUE.NoNo, PA only
ENCAISSEE212EncaisséeSeller confirms payment has been collected.Yes, TerminalYes, PA + PPF
VISEE214ViséeSeller marks the invoice as checked or validated.NoNo, PA only

ANNULEE (220) is not submittable through this endpoint. The platform produces it automatically when a corrective document for the invoice is confirmed. A request with statusName=ANNULEE returns CDAR_MANUEL_TRIGGER_FAILED.

Terminal statuses lock the invoice: once REFUSEE (210), ENCAISSEE (212), REJETEE (213) or ANNULEE (220) has been recorded for an invoice, every subsequent call to this endpoint for that invoice fails with CDAR_TERMINAL_STATUS, including statuses that would otherwise be valid for the caller's role.

Transition rules

Statuses are not independent. Submitting one that cannot follow the invoice's current status returns CDAR_INVALID_TRANSITION: the lifecycle does not advance and nothing is transmitted.

To submitCurrent status must be one of
204 Prise en charge203
205 Approuvée203, 204, 207, 208
206 Approuvée partiellement203, 204, 207, 208
207 En litige203, 204, 208
208 Suspendue203, 204
209 Complétée203, 204, 205, 206, 207, 208, 211
210 Refusée202, 203, 204, 207, 208
211 Paiement transmis205, 206
212 Encaissée203, 204, 205, 206, 207, 208, 211
214 Visée203, 204, 205, 206, 207, 208, 211

The buyer decision group

205, 206, 207, 208 and 210 are alternative decisions on the same invoice. How they interact is the part most integrations get wrong:

AfterStill available
207 En litige205, 206, 210 — not 208
208 Suspendue205, 206, 207, 210 — all of them
205 Approuvéenone of the five; 211 remains
206 Approuvée partiellementnone of the five; 211 remains
210 Refuséenone — terminal

207 and 208 are transitional. A disputed or suspended invoice is meant to be resolved afterwards by approving, partially approving, or refusing it. If your interface disables those options once a dispute is raised, the invoice can never be closed.

205 and 206 are final decisions: after either, the only remaining buyer action is 211.

Status-specific request fields

statusNameFields used from the request body
APPROUVEE_PARTIELLEMENTreasonCode required · reason optional
EN_LITIGEreasonCode required · reason, requestedActionCode, requestedAction, characteristics optional
SUSPENDUEreasonCode and reason required · characteristics required, at least one entry with currencyId
REFUSEEreasonCode and reason required
PAIEMENT_TRANSMIScharacteristics optional, omitted entirely from the CDAR if empty
ENCAISSEEcharacteristics, used to carry collected amount / VAT rate. Every MEN entry needs both valueAmount and valuePercent
All othersNone of the status-specific fields are used

Reason codes

Reason codes are validated. Rule BR-FR-CDV-15/MDT-113 requires a code whenever the status is 206, 207, 208 or 210, and rule BR-FR-CDV-CL-09/MDT-113_<status> then restricts which codes are valid per status.

The lists differ. A code accepted for a dispute is often rejected for a refusal. An invalid value returns 400.

206 — Approuvée partiellement · 13 codes

CodeLabel (FR)Meaning
AUTREAutreOther
CMD_ERRN° de commande/engagement incorrect ou manquantPurchase order number wrong, missing, or already invoiced
SIRET_ERRSIRET erroné ou absentRecipient SIRET wrong or missing
CODE_ROUTAGE_ERRCode routage absent ou erronéRouting code missing or wrong
REF_CT_ABSENTRéférence contractuelle manquanteA contractually required reference is missing
REF_ERRRéférence incorrecteA reference is incorrect
PU_ERRPrix unitaires incorrectsUnit price is not the expected one
REM_ERRRemise erronéeDiscount missing or not as expected
QTE_ERRQuantité facturée incorrecteInvoiced quantity is not as expected
ART_ERRArticle facturé incorrectWrong item invoiced
MODPAI_ERRModalités de paiement incorrectesPayment terms incorrect
QUALITE_ERRQualité d'article livré incorrecteA delivered item is defective
LIVR_INCOMPLivraison incomplète / non effectuéeDelivery incomplete or not made

207 — En litige · 26 codes

The widest list. It contains every code valid for 210, plus thirteen more.

CodeLabel (FR)Meaning
AUTREAutreOther
TX_TVA_ERRTaux de TVA erronéVAT rate is wrong
MONTANTTOTAL_ERRMontant total erronéAn invoice total is wrong
CALCUL_ERRErreur de calcul de la factureCalculation error — line totals or rounding
NON_CONFORMEMention légale manquanteA mandatory legal statement is missing
DOUBLONFacture en doublonDuplicate invoice
DOUBLE_FACTDonnées réglementaires F1 en doublonDuplicate regulatory data
DEST_INCDestinataire inconnuRecipient not found in the directory
DEST_ERRErreur de destinataireWrong recipient
EMMET_INCÉmetteur inconnuSender unknown to the recipient
TRANSAC_INCTransaction inconnueNo matching delivery or service
CONTRAT_TERMContrat terminéContract has ended
COORD_BANC_ERRErreur de coordonnées bancairesBank details are wrong
ADR_ERRAdresse de facturation électronique erronéeElectronic invoicing address wrong or missing
SIRET_ERRSIRET erroné ou absentRecipient SIRET wrong or missing
CODE_ROUTAGE_ERRCode routage absent ou erronéRouting code missing or wrong
CMD_ERRN° de commande/engagement incorrect ou manquantPurchase order number wrong or missing
REF_CT_ABSENTRéférence contractuelle manquanteA contractually required reference is missing
REF_ERRRéférence incorrecteA reference is incorrect
PU_ERRPrix unitaires incorrectsUnit price is not the expected one
REM_ERRRemise erronéeDiscount missing or not as expected
QTE_ERRQuantité facturée incorrecteInvoiced quantity is not as expected
ART_ERRArticle facturé incorrectWrong item invoiced
MODPAI_ERRModalités de paiement incorrectesPayment terms incorrect
QUALITE_ERRQualité d'article livré incorrecteA delivered item is defective
LIVR_INCOMPLivraison incomplète / non effectuéeDelivery incomplete or not made

208 — Suspendue · 7 codes

CodeLabel (FR)Meaning
JUSTIF_ABSJustificatif absent ou insuffisantSupporting documents missing or insufficient
COORD_BANC_ERRErreur de coordonnées bancairesBank details are wrong
CMD_ERRN° de commande/engagement incorrect ou manquantPurchase order number wrong or missing
SIRET_ERRSIRET erroné ou absentRecipient SIRET wrong or missing
CODE_ROUTAGE_ERRCode routage absent ou erronéRouting code missing or wrong
REF_CT_ABSENTRéférence contractuelle manquanteA contractually required reference is missing
REF_ERRRéférence incorrecteA reference is incorrect

210 — Refusée · 13 codes

CodeLabel (FR)Meaning
TX_TVA_ERRTaux de TVA erronéVAT rate is wrong
MONTANTTOTAL_ERRMontant total erronéAn invoice total is wrong
CALCUL_ERRErreur de calcul de la factureCalculation error — line totals or rounding
NON_CONFORMEMention légale manquanteA mandatory legal statement is missing
DOUBLONFacture en doublonDuplicate invoice
DOUBLE_FACTDonnées réglementaires F1 en doublonDuplicate regulatory data
DEST_ERRErreur de destinataireWrong recipient
EMMET_INCÉmetteur inconnuSender unknown to the recipient
TRANSAC_INCTransaction inconnueNo matching delivery or service
CONTRAT_TERMContrat terminéContract has ended
ADR_ERRAdresse de facturation électronique erronéeElectronic invoicing address wrong or missing
CMD_ERRN° de commande/engagement incorrect ou manquantPurchase order number wrong or missing
REF_CT_ABSENTRéférence contractuelle manquanteA contractually required reference is missing

AUTRE is not valid for a refusal. There is no generic "other" option on 210, unlike every other status above. Neither are SIRET_ERR, CODE_ROUTAGE_ERR, COORD_BANC_ERR, REF_ERR, PU_ERR, REM_ERR, QTE_ERR, ART_ERR, MODPAI_ERR, QUALITE_ERR, LIVR_INCOMP or DEST_INC — for a refusal use DEST_ERR.

Building one shared list

Every code valid for 210 is also valid for 207. If your interface offers a single reason list for both statuses, restrict it to the 13 codes of 210 — that set is safe for both. Separate lists are only needed if you want the thirteen extra codes 207 allows.

For a missing mandatory legal statement, use NON_CONFORME: its official label is literally Mention légale manquante, and it is valid for both 207 and 210.

requestedActionCode — 207 only

A closed list of seven values (BR-FR-CDV-CL-10/MDT-121). Any other value returns 400.

CodeMeaning
NOANo action required
NINNew invoice required
CNFCredit note required, full
PINAccepted value — no published label
CNPAccepted value — no published label
CNAAccepted value — no published label
OTHAccepted value — no published label

Responses

200 - Successful Response

The status was accepted, persisted, and delivered.

{
"success": true,
"errorType": null,
"errors": null,
"errorMessage": null
}

200 - Delivery failure

The status is valid and has been recorded, but transmission to the counterparty or PPF failed. The status stands; the delivery is retried. This is the only case where success: false appears.

{
"success": false,
"errorType": "CDAR_SEND_FAILED",
"errors": null,
"errorMessage": "…"
}

400 - Rejected

Everything else — unknown status, wrong role, invalid transition, terminal invoice, duplicate, missing reason, missing characteristic, schematron failure — returns HTTP 400 with a different envelope. There is no success field here, so do not key your error handling on it alone.

{
"errorMessage": "Validation failed!",
"errorType": "VALIDATION_FAILED",
"errorTitle": "BAD_REQUEST",
"errorId": "<ERROR_ID>",
"status": 400,
"validationErrors": [
{
"code": "BR-FR-CDV-CL-09_MDT-113_210",
"field": "…/ProcessConditionCode[1]",
"message": "Le code motif de statut (MDT-113) : \"SIRET_ERR\", n'est pas dans la liste des codes autorisés pour le statut REFUSÉE (210) : \"TX_TVA_ERR\", \"MONTANTTOTAL_ERR\", …"
}
]
}

Read validationErrors[]. It names the rule that failed and, for reason-code errors, lists the codes that would have been accepted. Logging only errorMessage leaves you with "Validation failed!", which tells you nothing.

A failed submission leaves the lifecycle untouched. The invoice keeps its previous status and nothing is transmitted, so you can correct the payload and retry.

Error Responses

errorTypeTrigger
CDAR_UNKNOWN_STATUSstatusName is not a recognized status code name.
CDAR_MANUEL_TRIGGER_FAILEDstatusName is recognized but not allowed for this endpoint at all, e.g. ANNULEE, or not allowed for the caller's role, recipient vs sender, on this invoice.
CDAR_INVALID_TRANSITIONThe status cannot follow the invoice's current status. See Transition rules.
CDAR_TERMINAL_STATUSA terminal status already exists for this invoice.
CDAR_DUPLICATE_STATUSThis status has already been produced for this invoice. Applies to APPROUVEE, REFUSEE and ENCAISSEE.
CDAR_REASON_REQUIREDreasonCode missing for 206, 207, 208 or 210; or reason missing for 208 or 210.
CDAR_SUSPENDUE_CHARACTERISTIC_CURRENCY_REQUIRED208 submitted with no characteristics entry carrying a currencyId.
CDAR_ENCAISSEE_CHARACTERISTIC_MISSING_AMOUNTSA MEN characteristic on 212 is missing valueAmount or valuePercent.
VALIDATION_FAILEDThe XSD or the FNFE schematron rejected the generated document. See validationErrors[].
INVOICE_NOT_FOUNDNo invoice matches invoiceId + companyId.

29. Get CDAR Detail (Raw XML) GET

Purpose of Use: Drills into a single row returned by /cdar/history. It is the same event, but with the extra bookkeeping fields history omits and, when available, the original CDAR XML document that was generated or received for that event.

Use this when you need the actual document, e.g. for your own compliance archive, not just its parsed fields.

Endpoint Information

PropertyValue
URL/cdar/detail/{invoiceCdvHistoryId}
MethodGET
Content-Typeapplication/json
Base URL
Production Environment URLhttps://api-fr.docnova.ai/
AuthorizationR-Auth header (JWT token)

Example Request

curl --location 'https://api-fr-stage.docnova.ai/cdar/detail/<CDV_HISTORY_ID>?companyId=<COMPANY_ID>' \
--header 'R-Auth: <AUTH_TOKEN>'

Request Parameters

Path Parameters

FieldTypeRequiredDescription
invoiceCdvHistoryIdUUIDYesThe id of one item from a /cdar/history response.

Query Parameters

FieldTypeRequiredDescription
companyIdUUIDYesMust match the row's owning company.

Responses

200 - Successful Response

{
"id": "<ID>",
"invoiceNumber": "<INVOICE_NUMBER>",
"invoiceIssueDate": "<INVOICE_ISSUE_DATE>",
"vendeurSiret": "<SUPPLIER_SIRET>",
"cdarId": "<CDAR_ID>",
"cdarDocumentId": "<CDAR_DOCUMENT_ID>",
"cdarDocumentName": null,
"cdarHistoryStatus": "SUBMITTED",
"processConditionCode": "DEPOSEE",
"processCondition": "Déposée",
"newStatus": "DEPOSEE",
"statusCode": "200",
"statusLabel": "Déposée",
"direction": "OUTBOUND",
"platform": "PPF",
"source": "PORTAL",
"issuerRoleCode": "WK",
"issuerGlobalId": "<ISSUER_GLOBAL_ID>",
"issuerName": "<ISSUER_NAME>",
"senderGlobalId": null,
"sftpFileName": null,
"reasonCode": null,
"reasonText": null,
"errorMessage": null,
"responseCode": 200,
"responseMessage": null,
"changedBy": "PA_SFTP_SYSTEM",
"cdarIssuedAt": "<CDAR_ISSUED_AT>",
"statusDepositedAt": "<STATUS_DEPOSITED_AT>",
"receivedAt": "<RECEIVED_AT>",
"sentAt": "<SENT_AT>",
"createdAt": "<CREATED_AT>",
"updatedAt": "<UPDATED_AT>",
"xmlBase64": "<BASE64_ENCODED_CDAR_XML>"
}

Response Fields

FieldTypeDescription
idUUIDSame value as the id used to request this detail.
invoiceNumberstringBusiness invoice number.
invoiceIssueDatestringInvoice issue date as YYYYMMDD, a plain string, not a parsed date.
vendeurSiretstringSupplier SIRET, read from the linked invoice.
cdarIdstringCDAR document unique ID, MDT-4.
cdarDocumentId/cdarDocumentNamestringDocument identifier and, for SFTP-delivered CDARs, its inner file name.
cdarHistoryStatusenumTransmission state of this CDAR: GENERATED, SUBMITTED, RECEIVED, ERROR, REJECTED_BY_601, LOT_RECEIVED, LOT_REJECTED.
processConditionCodeenumSet when this row came from an outbound, this-company-produced CDAR. See the status reference in section 25.
processConditionstringFrench label paired with processConditionCode.
newStatusenumSet on both outbound and inbound rows. The more reliable of the two status fields to key logic off of.
statusCode/statusLabelstringRaw status code and label as carried in the CDAR XML itself.
directionenumOUTBOUND or INBOUND.
platformenumPA or PPF, which recipient this row's variant targeted.
sourceenumOrigin channel of the underlying invoice: PORTAL, ERP, SFTP, PEPPOL, etc.
issuerRoleCode/issuerGlobalId/issuerNamestringWho issued this CDAR: role WK / SE / BY, SIREN or PA code, and display name.
senderGlobalIdstringSending PA's global ID, populated on PPF-targeted variants.
sftpFileNamestringFlux file name, when sent over SFTP.
reasonCode/reasonTextstringPopulated for the statuses that carry a reason: 206, 207, 208 and 210. reasonText echoes back the reason value sent on the request.
errorMessagestringPopulated when cdarHistoryStatus = ERROR.
responseCode/responseMessageinteger / stringResult of the transmission attempt.
changedBystringSystem actor that recorded the row.
cdarIssuedAt/statusDepositedAt/receivedAt/sentAt/createdAt/updatedAtdatetimeFull timestamps set for this event.
xmlBase64stringBase64-encoded raw CDAR XML, fetched from S3. null if no XML has been stored for this row yet.

Error Responses

StatuserrorTypeCondition
403AUTHORIZATION_FAILEDThe R-Auth user has no role on companyId.
404FR_CDAR_HISTORY_NOT_FOUNDNo history row matches invoiceCdvHistoryId + companyId.