Send invoice (async)
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
| Property | Value |
|---|---|
| URL | POST /invoice/send-document-async-json |
| Method | POST |
| R-Auth | R-Auth: {company-jwt} |
| Base URL | Stage Environment https://api-stage.docnova.ai/ Production Environment https://api.docnova.ai/ |
Example Request
curl --location '{{baseUrl}}/invoice/send-document-async-json' \
--header 'Content-Type: application/json' \
--header 'R-Auth: {{companyJwt}}' \
--data-raw '{
"apiKey": "{{companyApiKey}}",
"businessType": "B2B",
"mailTemplateId": "string",
"method": "via peppol",
"receiverEmails": [],
"senderEmail": "string",
"ublDto": { ... }
}'
Request body
{
"apiKey": "{{companyApiKey}}",
"businessType": "B2B",
"mailTemplateId": "string",
"method": "via peppol",
"receiverEmails": [],
"senderEmail": "string",
"ublDto": {}
}
The request body contains the top-level wrapper with authentication and the ublDto invoice object.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Yes | Company API key. |
| businessType | string | No | Business type of the transaction (e.g. B2B). If not provided, the value on the invoice is kept. |
| mailTemplateId | string | No | ID of the email template used for delivery notifications. |
| method | string | No | Delivery method of the invoice. Allowed values: via peppol, via email. If not provided, the invoice is sent through each channel whose conditions are met. |
| receiverEmails | array | No | Email addresses the invoice is delivered to. Required when method is via email and must contain at least one address. Otherwise the RECEIVER_EMAILS_REQUIRED_FOR_EMAIL_METHOD error is returned. |
| senderEmail | string | No | Email address shown as the sender of the notification email. |
| ublDto | object | Yes | UBL invoice object. type and invoiceTypeCode.value are required inside it. Otherwise the NULL_DATA_OBJECT error is returned. See the full schema in the sections below. |
Full example
curl --location 'https://api-stage.docnova.ai/invoice/send-document-async-json' \
-H 'accept: */*' \
-H 'R-Auth: {{jwt_token}}' \
-H 'Content-Type: application/json' \
-d '{ "apiKey": "{{your_api_key}}",
"businessType": "B2B",
"mailTemplateId": "string",
"method": "via peppol",
"receiverEmails": [ "example@melasoft.com" ],
"senderEmail": "string",
"ublDto": {
"Type": "PEPPOL_BIS",
"IsPeppolParticipant": true,
"CompanyId": "{{company_uuid}}",
"ProfileType": "EN16931",
"CustomizationID": { "Value": "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0" },
"ProfileID": { "Value": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0" },
"ID": { "Value": "INV-2025-001" },
"IssueDate": { "Value": "2025-12-08" },
"DueDate": { "Value": "2025-12-05" },
"InvoiceTypeCode": { "Value": "380" },
"Note": [{ "Value": "Thank you for the good cooperation." }],
"DocumentCurrencyCode": { "Value": "EUR" },
"BuyerReference": { "Value": "buyer-ref-001" },
"OrderReference": { "ID": { "Value": "PO-12345" }, "SalesOrderID": { "Value": "SO-67890" } },
"AccountingSupplierParty": {
"Party": {
"EndpointID": { "Value": "DE123456789", "schemeID": "9930" },
"PartyName": [{ "Name": { "Value": "Supplier Company GmbH" } }],
"PostalAddress": { "StreetName": { "Value": "Musterstraße 12" }, "CityName": { "Value": "Berlin" }, "PostalZone": { "Value": "10115" }, "Country": { "IdentificationCode": { "Value": "DE" } } },
"PartyTaxScheme": [{ "CompanyID": { "Value": "DE123456789" }, "TaxScheme": { "ID": { "Value": "VAT" } } }],
"PartyLegalEntity": [{ "RegistrationName": { "Value": "Supplier Company GmbH" }, "CompanyID": { "Value": "DE123456789" } }],
"Contact": { "Name": { "Value": "Contact Name" }, "Telephone": { "Value": "+49 170 1234567" }, "ElectronicMail": { "Value": "user@example.com" } }
}
},
"AccountingCustomerParty": {
"Party": {
"EndpointID": { "Value": "DE987654321", "schemeID": "9930" },
"PartyName": [{ "Name": { "Value": "Buyer Company GmbH" } }],
"PostalAddress": { "StreetName": { "Value": "Kaufstraße 5" }, "CityName": { "Value": "Hamburg" }, "PostalZone": { "Value": "20095" }, "Country": { "IdentificationCode": { "Value": "DE" } } },
"PartyTaxScheme": [{ "CompanyID": { "Value": "DE987654321" }, "TaxScheme": { "ID": { "Value": "VAT" } } }],
"PartyLegalEntity": [{ "RegistrationName": { "Value": "Buyer Company GmbH" }, "CompanyID": { "Value": "DE987654321" } }],
"Contact": { "Name": { "Value": "Buyer Contact" }, "Telephone": { "Value": "+49 170 1234567" }, "ElectronicMail": { "Value": "user@example.com" } }
}
},
"Delivery": [{
"ActualDeliveryDate": { "Value": "2025-12-13" },
"DeliveryLocation": { "Address": { "StreetName": { "Value": "Delivery Street 5" }, "CityName": { "Value": "Berlin" }, "PostalZone": { "Value": "10115" }, "Country": { "IdentificationCode": { "Value": "DE" } } } },
"DeliveryParty": { "PartyName": [{ "Name": { "Value": "Delivery Recipient" } }] }
}],
"PaymentMeans": [{
"PaymentMeansCode": { "name": "SEPA credit transfer", "Value": "58" },
"PayeeFinancialAccount": { "ID": { "Value": "DE89370400440532013000" }, "Name": { "Value": "Account Holder Name" } }
}],
"PaymentTerms": [{ "Note": [{ "Value": "Please remit until 05.12.2025" }] }],
"TaxTotal": [{
"TaxAmount": { "currencyID": "EUR", "Value": 210 },
"TaxSubtotal": [{
"TaxableAmount": { "currencyID": "EUR", "Value": 2100 },
"TaxAmount": { "currencyID": "EUR", "Value": 210 },
"TaxCategory": { "ID": { "Value": "S" }, "Percent": { "Value": 10 }, "TaxScheme": { "ID": { "Value": "VAT" } } }
}]
}],
"LegalMonetaryTotal": {
"LineExtensionAmount": { "currencyID": "EUR", "Value": 2100 },
"TaxExclusiveAmount": { "currencyID": "EUR", "Value": 2100 },
"TaxInclusiveAmount": { "currencyID": "EUR", "Value": 2310 },
"AllowanceTotalAmount": { "currencyID": "EUR", "Value": 0 },
"ChargeTotalAmount": { "currencyID": "EUR", "Value": 0 },
"PrepaidAmount": { "currencyID": "EUR", "Value": 0 },
"PayableAmount": { "currencyID": "EUR", "Value": 2310 }
},
"InvoiceLine": [{
"ID": { "Value": "1" },
"InvoicedQuantity": { "unitCode": "MTQ", "Value": 20 },
"LineExtensionAmount": { "currencyID": "EUR", "Value": 2100 },
"Item": {
"Name": { "Value": "Product 1" },
"SellersItemIdentification": { "ID": { "Value": "01" } },
"ClassifiedTaxCategory": [{ "ID": { "Value": "S" }, "Percent": { "Value": 10 }, "TaxScheme": { "ID": { "Value": "VAT" } } }]
},
"Price": { "PriceAmount": { "currencyID": "EUR", "Value": 105 }, "BaseQuantity": { "Value": 1 } }
}]
}
}'
ublDto — Document Object
| Field Name | Type | Required | Description |
|---|---|---|---|
| ublDto.Type | string (enum) | Mandatory | Document/data type. E.g.: PEPPOL_BIS, XRECHNUNG, ZUGFERD. See Parameter Values Reference table for full list. Omitting it returns NULL_DATA_OBJECT (verified on stage — also stated in Request fields above). |
| ublDto.IsPeppolParticipant | boolean | Optional | Indicates whether the recipient is registered on the Peppol network. If true, the document is routed via Peppol. Confirmed optional on stage (no error when omitted). |
| ublDto.CompanyId | string (UUID) | Conditional | UUID of the sending company. Required if apiKey is not provided. |
| ublDto.ProfileType | string (enum) | Optional | ZUGFeRD / Factur-X profile type. Default: EN16931. Confirmed optional on stage. |
| ublDto.CustomizationID.Value | string | Mandatory | Invoice customization identifier (urn value). Omitting it fails with "An Invoice shall have a Specification identifier" (rule BR-01) and "Specification identifier MUST begin with the value 'urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0'..." (PEPPOL-EN16931-R004) — verified on stage. |
| ublDto.ProfileID.Value | string | Mandatory | Business process identifier (e.g. urn:fdc:peppol.eu:2017:poacc:billing:01:1.0). Not previously documented — found missing from this table during a full field audit. Omitting it fails with "Business process MUST be provided" and "Business process MUST have an approved identifier" (rules PEPPOL-EN16931-R001, PEPPOL-EN16931-R007) — verified on stage. |
| ublDto.ID.Value | string | Mandatory | Invoice number / unique document identifier. Omitting it fails with "An Invoice shall have an Invoice number" (rule BR-02) — verified on stage. |
| ublDto.IssueDate.Value | string (ISO 8601) | Mandatory | Invoice issue date. Format: YYYY-MM-DD. Omitting it fails with "An Invoice shall have an Invoice issue date" (rule BR-03) — verified on stage. |
| ublDto.DueDate.Value | string (ISO 8601) | Optional | Invoice due date. Format: YYYY-MM-DD. Confirmed optional on stage. |
| ublDto.InvoiceTypeCode.Value | string | Mandatory | UN/CEFACT invoice type code. E.g.: 380 = Commercial Invoice, 381 = Credit Note, 384 = Corrected Invoice. Omitting it returns NULL_DATA_OBJECT (verified on stage — also stated in Request fields above; the previous "Optional" label here contradicted that). |
| ublDto.Note[].Value | string | Optional | Free-text note attached to the invoice. Confirmed optional on stage. |
| ublDto.DocumentCurrencyCode.Value | string | Mandatory | Invoice currency code (ISO 4217). E.g.: EUR, USD, GBP. Omitting it fails with "An Invoice shall have an Invoice currency code" (rule BR-05) plus a cascade of currencyID-consistency errors (PEPPOL-EN16931-R051) — verified on stage. |
| ublDto.BuyerReference.Value | string | Mandatory (unless OrderReference.ID is set) | Buyer reference number (Buyer Reference / Leitweg-ID). Verified on stage: a PEPPOL_BIS document with neither BuyerReference nor OrderReference.ID is rejected with "A buyer reference or purchase order reference MUST be provided" (rule PEPPOL-EN16931-R003). |
| ublDto.OrderReference.ID.Value | string | Optional | Purchase order number. Satisfies PEPPOL-EN16931-R003 in place of BuyerReference (see above). |
| ublDto.OrderReference.SalesOrderID.Value | string | Optional | Sales order number. Confirmed optional on stage (tested with BuyerReference present). |
| ublDto.AccountingSupplierParty | object | Conditional | Supplier / seller information. Structurally optional in the request schema, but required for the invoice to pass PEPPOL BIS Billing 3.0 validation — see the mandatory sub-fields below, all confirmed against the stage environment (same pattern as AccountingCustomerParty). The Party object contains EndpointID, PartyName, PostalAddress, PartyTaxScheme, PartyLegalEntity, and Contact sub-objects. |
| ublDto.AccountingSupplierParty.Party.EndpointID.Value / .schemeID | string | Mandatory when ublDto.Type is PEPPOL_BIS | Supplier's Peppol Endpoint ID and scheme. Omitting it fails with "Seller electronic address MUST be provided" (rule PEPPOL-EN16931-R020, the seller-side counterpart of the buyer's R010 below) — verified on stage. |
| ublDto.AccountingSupplierParty.Party.PartyLegalEntity[].RegistrationName.Value | string | Mandatory | Supplier (seller) name. Omitting both this and PartyName[].Name fails with "An Invoice shall contain the Seller name" (rule BR-06) — verified on stage. |
| ublDto.AccountingSupplierParty.Party.PostalAddress | object | Mandatory | Supplier postal address. Omitting it entirely fails with "An Invoice shall contain the Seller postal address" (rule BR-08) — verified on stage. |
| ublDto.AccountingSupplierParty.Party.PostalAddress.Country.IdentificationCode.Value | string | Mandatory | Supplier country code, ISO 3166-1 alpha-2. Omitting it (while PostalAddress is present) fails with "The Seller postal address shall contain a Seller country code" (rule BR-09) — verified on stage. |
| ublDto.AccountingSupplierParty.Party.PartyTaxScheme[].CompanyID.Value | string | Mandatory for standard-rated lines | Supplier VAT identifier. Required whenever any invoice line uses a VAT category that needs a registered identifier (e.g. "Standard rated") — omitting it fails with rule BR-S-02 ("...shall contain the Seller VAT Identifier, the Seller tax registration identifier and/or the Seller tax representative VAT identifier"); Germany additionally enforces this via DE-R-016 — verified on stage. |
| ublDto.AccountingSupplierParty.Party.Contact | object | Conditional | Supplier contact details. Confirmed optional in general on stage, but mandatory when both supplier and customer are in Germany (rule DE-R-002, "the group SELLER CONTACT shall be provided"). |
| ublDto.AccountingCustomerParty | object | Conditional | Customer / buyer information. Structurally optional in the request schema (no field inside it is enforced by the API itself), but required for the invoice to pass PEPPOL BIS Billing 3.0 validation — see the mandatory sub-fields below, all confirmed against the stage environment. The Party object contains EndpointID, PartyName, PostalAddress, PartyTaxScheme, PartyLegalEntity, and Contact sub-objects. |
| ublDto.AccountingCustomerParty.Party.PartyLegalEntity[].RegistrationName.Value | string | Mandatory | Buyer name. Omitting both this and PartyName[].Name fails with "An Invoice shall contain the Buyer name" (rule BR-07, verified on stage). |
| ublDto.AccountingCustomerParty.Party.PostalAddress | object | Mandatory | Buyer postal address. Omitting it entirely fails with "An Invoice shall contain the Buyer postal address" (rule BR-10, verified on stage). |
| ublDto.AccountingCustomerParty.Party.PostalAddress.Country.IdentificationCode.Value | string | Mandatory | Buyer country code, ISO 3166-1 alpha-2. If PostalAddress is present without a country code, the document fails with "The Buyer postal address shall contain a Buyer country code" (rule BR-11, verified on stage). |
| ublDto.AccountingCustomerParty.Party.EndpointID.Value / .schemeID | string | Mandatory when ublDto.Type is PEPPOL_BIS | Buyer's Peppol Endpoint ID and scheme. Verified on stage: missing when Type is PEPPOL_BIS fails with "Buyer electronic address MUST be provided" (rule PEPPOL-EN16931-R010) — this fired even with IsPeppolParticipant: false and no method, so it is tied to the document type/profile, not to the chosen delivery channel. |
| ublDto.Delivery[].ActualDeliveryDate.Value | string (ISO 8601) | Optional | Actual delivery date. Format: YYYY-MM-DD. Confirmed optional on stage. |
| ublDto.Delivery[].DeliveryLocation.Address | object | Optional | Delivery address. Contains StreetName, CityName, PostalZone, and Country sub-fields. Confirmed optional on stage, including the whole Delivery array. |
| ublDto.TaxTotal | array | Mandatory | VAT breakdown. Omitting it entirely fails with rules BR-CO-15, BR-CO-18, BR-S-01 ("An Invoice shall at least have one VAT breakdown group") and PEPPOL's "only one tax total with tax subtotals MUST be provided" (PEPPOL-EN16931-R053) — verified on stage. |
| ublDto.TaxTotal[].TaxAmount.Value | number | Mandatory | Total tax amount. Omitting it breaks the invoice total consistency checks (rules BR-CO-14, BR-CO-15) — verified on stage. |
| ublDto.TaxTotal[].TaxAmount.currencyID | string | Mandatory | Currency code for the tax amount (ISO 4217). Omitting it fails BR-CL-03, PEPPOL-EN16931-R051 and PEPPOL-EN16931-CL007 — verified on stage. |
| ublDto.TaxTotal[].TaxSubtotal[].TaxableAmount.Value | number | Mandatory | Taxable base amount. Omitting it fails "Each VAT breakdown shall have a VAT category taxable amount" (rule BR-45) plus downstream calculation rules (BR-CO-17, BR-S-08, BR-S-09) — verified on stage. |
| ublDto.TaxTotal[].TaxSubtotal[].TaxCategory.ID.Value | string | Mandatory | Tax category code. E.g.: S = Standard, Z = Zero Rated, E = Exempt, AE = Reverse Charge. Omitting it fails rules BR-47, BR-S-01 — verified on stage. |
| ublDto.TaxTotal[].TaxSubtotal[].TaxCategory.Percent.Value | number | Mandatory (unless the invoice is not subject to VAT) | Tax rate percentage. E.g.: 19, 7, 10. Omitting it fails "Each VAT breakdown shall have a VAT category rate" (rule BR-48) plus BR-CO-17, BR-S-09; Germany additionally enforces this via DE-R-014 — verified on stage. |
| ublDto.LegalMonetaryTotal | object | Mandatory | Monetary totals. Omitting it fails the total-consistency rule BR-CO-15 — verified on stage. |
| ublDto.LegalMonetaryTotal.LineExtensionAmount.Value | number | Mandatory | Sum of invoice line net amounts (excluding tax). Omitting it fails rules BR-12, BR-CO-10, BR-CO-13 — verified on stage. |
| ublDto.LegalMonetaryTotal.TaxExclusiveAmount.Value | number | Mandatory | Total amount excluding VAT. Omitting it fails rules BR-13, BR-CO-13, BR-CO-15 — verified on stage. |
| ublDto.LegalMonetaryTotal.TaxInclusiveAmount.Value | number | Mandatory | Total amount including VAT. Omitting it fails rules BR-14, BR-CO-15, BR-CO-16 — verified on stage. |
| ublDto.LegalMonetaryTotal.PayableAmount.Value | number | Mandatory | Net payable amount. Omitting it fails "An Invoice shall have the Amount due for payment" (rule BR-15) plus BR-CO-16 — verified on stage. |
| ublDto.PaymentMeans | array | Conditional | Payment instructions. Not required by core EN16931 / PEPPOL BIS — confirmed optional on stage for an NL↔NL pair outside the DE/NL conditions below. Several country rule sets require it unconditionally or conditionally: Germany requires it when both supplier and customer are German (DE-R-001); the Netherlands requires the supplier to always provide it (NL-R-007) — both verified on stage. Check the applicable company's country rules. |
| ublDto.PaymentMeans[].PaymentMeansCode.Value | string | Mandatory once PaymentMeans is present | Payment method code. E.g.: 58 = SEPA Credit Transfer, 30 = Credit Transfer, 49 = Direct Debit. If a PaymentMeans entry is sent, omitting its code fails "A Payment instruction shall specify the Payment means type code" (rule BR-49) — verified on stage. |
| ublDto.PaymentMeans[].PayeeFinancialAccount.ID.Value | string | Mandatory for credit-transfer codes | Payee bank account IBAN number. Required when PaymentMeansCode denotes a (SEPA/local/non-SEPA) credit transfer — omitting it fails rules BR-50, BR-61 — verified on stage. |
| ublDto.PaymentMeans[].PayeeFinancialAccount.Name.Value | string | Optional | Bank account holder name. Confirmed optional on stage (no error when omitted, account ID present). |
| ublDto.PaymentTerms[].Note[].Value | string | Optional | Free-text description of payment terms. Confirmed optional on stage, including the whole PaymentTerms array. |
| ublDto.InvoiceLine | array | Mandatory | Invoice line items — at least one is required. Omitting the array entirely fails "An Invoice shall have at least one Invoice line" (rule BR-16) plus the VAT-breakdown consistency rules that depend on it (BR-S-01, BR-S-08, BR-CO-10) — verified on stage. |
| ublDto.InvoiceLine[].ID.Value | string | Mandatory | Invoice line sequence number. Omitting it fails "Each Invoice line shall have an Invoice line identifier" (rule BR-21) — verified on stage. |
| ublDto.InvoiceLine[].InvoicedQuantity.Value | number | Mandatory | Invoiced quantity. Omitting it fails rules BR-22, BR-23 — verified on stage. |
| ublDto.InvoiceLine[].InvoicedQuantity.unitCode | string | Mandatory | Unit of measure code (UN/ECE Rec. 20). E.g.: MTQ = Cubic Metre, C62 = Each, KGM = Kilogram. Omitting it fails "An Invoice line shall have an Invoiced quantity unit of measure code" (rule BR-23) — verified on stage. |
| ublDto.InvoiceLine[].LineExtensionAmount.Value | number | Mandatory | Invoice line net amount (excluding tax). Omitting it fails rules BR-24, BR-CO-10, BR-S-08 and the line-amount formula check (PEPPOL-EN16931-R120) — verified on stage. |
| ublDto.InvoiceLine[].Item.Name.Value | string | Mandatory | Product / service name. Omitting it fails "Each Invoice line shall contain the Item name" (rule BR-25) — verified on stage. |
| ublDto.InvoiceLine[].Item.SellersItemIdentification.ID.Value | string | Optional | Seller's item/product code. Confirmed optional on stage. |
| ublDto.InvoiceLine[].Price.PriceAmount.Value | number | Mandatory | Unit price. Omitting it fails rules BR-26, BR-27 and the line-amount formula check (PEPPOL-EN16931-R120) — verified on stage. |
| ublDto.InvoiceLine[].Price.BaseQuantity.Value | number | Optional | Base quantity the price applies to. Typically 1. Confirmed optional on stage. |
| receiverEmails | array (string) | Optional | Recipient email addresses for sending the invoice via email after processing. Mandatory when method is via email — confirmed on stage: omitting it then returns "receiverEmails is required and must contain at least one email address when method is 'via email'". |
| mailTemplateId | string | Optional | Custom mail template ID to be used for email delivery. |
| businessType | string (enum) | Optional | Business model type: B2B, B2C, or B2G. |
The API's request schema itself enforces almost nothing — in practice only type and invoiceTypeCode.value cause an immediate NULL_DATA_OBJECT rejection. Everything else, including fields marked "Mandatory" above, is enforced by a second, separate validation pass (PEPPOL BIS Billing 3.0 / EN16931 business rules, plus country-specific rules) that runs after submission — a 200 response only means the document was accepted for processing, not that it is valid. Always check GET /invoice/document-status/{trackingId} for the final errors array.
The Required column above reflects this second pass, confirmed field-by-field against the stage environment (every row was individually omitted from an otherwise-valid invoice and the resulting errors array recorded) — not just inferred from the EN16931 spec text. Country-specific rule sets can add further requirements beyond this table (confirmed for Germany and the Netherlands here; not exhaustively tested for every supported country) — when in doubt for a specific country pair, submit a test invoice on stage and check document-status.
200 — Succesfull Response
{
"trackingId": "uuid",
"status": "PENDING",
"message": "Document process started successfully"
}
ERROR
{
"trackingId": "uuid",
"status": "FAILED",
"errors": ["[BR-CO-15]..."],
"errorType": "VALIDATION_ERROR"
}
A 200 OK only means the document was accepted, not delivered. Always check the final status with GET /invoice/document-status/{trackingId}.
Response fields
| Field | Type | Description |
|---|---|---|
| trackingId | UUID | Use this to poll GET /invoice/document-status/{trackingId} for processing updates. |
| status | string | Initial status — always "PENDING" on acceptance. |
| message | string | Human-readable message confirming the document was queued. |
Use the trackingId to check delivery status via Document status.