eliDocs
API Reference

Error reference

Complete reference of all Beliq API error codes, HTTP statuses, and remediation guidance.

All API errors use the same response shape:

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description of the error",
    "details": {}
  }
}
Field Type Description
code string Stable, machine-readable error code
message string Human-readable explanation
details object? Structured data for the codes that carry it: fields on a schema VALIDATION_ERROR, validationResult on INVALID_INVOICE, allowedProfiles on PROFILE_STANDARD_MISMATCH, creditNoteCapableStandards or typeCodeCapableStandards on DOCUMENT_TYPE_STANDARD_MISMATCH, unmappablePaths on CONVERSION_LOSSY_FAILCLOSED, validationResult on CONVERSION_OUTPUT_INVALID, failedRules on PDFA_VIOLATION, sourceFormat, targetFormat, for three refusals a reason and, after a veraPDF violation in a re-wrapped PDF, failedRules on CONVERSION_UNSUPPORTED_PAIR, tool and exitCode on CONVERSION_TOOL_ERROR, missingTool on CONVERSION_TOOL_UNAVAILABLE. Absent on every other code
incidentId string? Support correlation ID on a 5xx that an endpoint in this reference raises itself; never on a 4xx (see Request ID and incident ID). Quote it together with the x-request-id header when you email hello@beliq.eu

That includes a request the router refuses before it reaches an endpoint: a URL that does not decode, or a path parameter longer than the router accepts, gets a 400 VALIDATION_ERROR.

Error codes

Error codes

Code HTTP Status Meaning Endpoints Remediation
VALIDATION_ERROR 400 / 413 / 415 / 422 Request body is invalid. This code is also the catch-all for client errors that have no more specific code, so read the status to tell them apart: 400 the body failed the schema, the engine refused a value the schema allows, or the URL could not be routed, 413 it exceeded the size limit and was never read, or the engine refused a body within that limit as too large to process, 415 the content type is not accepted on that route, 422 the engine judged the document unprocessable All For a 400 with details.fields, check required fields and types in the generate schema. A 400 without details names its cause in message; on /v1/generate that can be the engine refusing a value the schema allows, and the message then says what it refused. For the others the status is the diagnosis; the message names the specific cause
INVALID_INVOICE 422 Invoice data is structurally valid JSON but fails validation: EN 16931 or CIUS Schematron for UBL/CII, or authority XSD for the national formats (FatturaPA, Facturae, e-SLOG, KSeF FA(3)) /v1/generate Inspect details.validationResult.errors (and for the national formats, structural XSD findings where applicable)
PROFILE_STANDARD_MISMATCH 422 The chosen profile is not allowed for the chosen standard /v1/generate Use a compatible combination; the response details includes standard, profile, and allowedProfiles. See the profile compatibility table.
DOCUMENT_TYPE_STANDARD_MISMATCH 422 documentType: "creditnote" with a standard that does not accept CreditNote payloads, today fatturapa, facturae and ksef (invoices only), or a typeCode with a standard that writes its own document type (fatturapa, facturae, eslog, ksef). /v1/generate For a credit note, inspect details.creditNoteCapableStandards; it lists standards that honour CreditNotes in the deployed engine (facturx, peppol-bis, xrechnung, zugferd, eslog). See the Peppol Credit notes section. For a typeCode, inspect details.typeCodeCapableStandards, or omit the field to get the standard’s own default.
PARSE_FAILED 400 Input file could not be parsed as a valid e-invoice /v1/parse Verify the input is a well-formed UBL 2.1 or CII XML, or a ZUGFeRD / Factur-X hybrid PDF with an embedded CII attachment. FatturaPA and SDI messaggio inputs are not handled by parse; use /v1/validate for those.
AUTHENTICATION_REQUIRED 401 No API key was sent Every endpoint that takes an API key Include Authorization: Bearer <key> or X-API-Key: <key> in the request headers
INVALID_API_KEY 403 The key that was sent is not an active key: it is malformed, does not exist or has been revoked Every endpoint that takes an API key Verify the API key in the dashboard. Generate a new key if it was revoked
QUOTA_EXCEEDED 429 Monthly usage quota exhausted: your plan’s quota for a live key, the sandbox allowance for a test key Every endpoint that spends a unit: /v1/generate, /v1/validate, /v1/parse, /v1/convert, and /v1/send and /v1/receive (preview), which answer TRANSMISSION_DISABLED first while transmission is not enabled For a live key, upgrade your subscription plan in the dashboard, or wait until the window rolls over (Retry-After is the seconds until then; /v1/me reports the same instant as resetsAt). For a test key, no plan upgrade lifts the sandbox allowance: it resets at the start of the next UTC calendar month
RATE_LIMITED 429 Too many requests in the current one-minute burst window. The transmission endpoints (preview) have limits of their own All Respect Retry-After and retry with backoff. Retry-After here is seconds, not minutes
ACCOUNT_THROTTLED 429 The account is temporarily throttled after sustained pressure on its own limits. Unlike RATE_LIMITED, this blocks every /v1 route until it expires All Respect Retry-After, which can be several minutes, much longer than a burst window. Stop retrying in a tight loop: further requests while throttled extend it. Reaching this state means requests were being sent well beyond the plan’s allowance for a sustained period
ENGINE_UNAVAILABLE 503 Beliq could not process the request: the engine was unavailable, the request queued for too long, or too many of your account’s requests were already waiting (see Burst and sustained throughput) /v1/generate, /v1/validate, /v1/parse, /v1/convert Retry after Retry-After. The document’s quota unit is refunded (see Quota refunds), so a retry does not cost you a second document. Safe to retry automatically. If persistent, check the status page and email hello@beliq.eu with the error.incidentId value
DATABASE_UNAVAILABLE 503 Beliq’s database could not serve the request: it did not answer in time, a lock wait or a statement took too long, it had too many connections, or it had no primary or lost the connection for longer than Beliq retries Every endpoint that takes an API key, /v1/me included. Not /v1/rulesets, which reads no database Retry after Retry-After. On /v1/generate, /v1/validate, /v1/parse, /v1/convert and /v1/me a retry is safe, and the Node and Python SDKs retry a 503 for you. A write the request started can still complete after the 503, so on /v1/send retry with the same Idempotency-Key. If the request had spent a quota unit, Beliq tries to refund it at once and says on x-beliq-quota-refunded whether that worked (see Quota refunds). If persistent, check the status page and email hello@beliq.eu with the error.incidentId value
INTERNAL_ERROR 500 Unexpected server error All Retry the request. If persistent, email hello@beliq.eu with the error.incidentId value and the x-request-id response header
NOT_FOUND 404 No route exists at the requested path and method, or the resource the request names does not exist All Check the path and HTTP method against this reference. A POST route called with GET returns this too; for an authenticated caller, or on a public route such as /v1/rulesets, it carries an Allow header listing the methods the path accepts
PDF_TEMPLATE_AUTH_REQUIRED 400 pdfTemplateId was sent without an authenticated organization. Stored PDF templates are org-scoped, so they require an API key (the free, unauthenticated generator can use template: "standard" instead). /v1/generate Send the request with your Authorization: Bearer <key>, or drop pdfTemplateId and use template: "standard" for the built-in layout
PDF_TEMPLATE_NOT_FOUND 404 The referenced pdfTemplateId does not exist in your organization /v1/generate Check the template’s ref in the dashboard under PDF templates
PDF_TEMPLATE_INVALID 422 The stored template definition could not be parsed, or fails the checks the dashboard designer applies on save. The message names the field at fault /v1/generate Open the template in the dashboard designer, fix the field it names and save; if it persists, email hello@beliq.eu with the x-request-id
PDFA_VIOLATION 422 A hybrid PDF was built, veraPDF reported a violation of its PDF/A-3b profile in it, and so the PDF is not returned. The quota unit is refunded (see Quota refunds) /v1/generate The same request fails the same way again, so do not retry it unchanged. Read details.failedRules. With your own template (pdfTemplateId), change the template in the dashboard designer. Without one, nothing in the PDF is yours to change: email hello@beliq.eu with the x-request-id response header
CONVERSION_UNSUPPORTED_PAIR 422 The conversion is not offered: the source format is outside the EN 16931 family, the source PDF carries no embedded invoice XML, the source states no specification identifier, the identifier rewrite is not offered for the source’s profile, a PDF source cannot be re-wrapped for a ZUGFeRD or Factur-X target, or Beliq builds no hybrid PDF for the converted XML’s profile /v1/convert Check the supported pairs, details.reason and, for a PDF source, the re-wrap. National formats (FatturaPA, Facturae, KSeF, SDI messaggio) have no cross-format converter
CONVERSION_OUTPUT_INVALID 422 The converted document failed validation, so it is not returned. The quota unit is kept /v1/convert Inspect details.validationResult.errors; the findings are on the converted document. Send the source to POST /v1/validate to see whether it was valid before the conversion, and see what a conversion does with the content
CONVERSION_LOSSY_FAILCLOSED 422 The source carries fields the target cannot represent, so the conversion was refused rather than performed silently. No body is returned /v1/convert Read details.unmappablePaths. For a France CTC Flux 2 code on a UBL target, opt in with ?dropFranceCtcOverlay=true; for a synthesised Peppol endpoint pair there is no opt-in, so use POST /v1/generate. See lossy conversions
CONVERSION_TOOL_UNAVAILABLE 503 A converter the engine needs for this pair is not deployed. Operational, and not expected in production /v1/convert Retry after Retry-After. The quota unit is refunded (see Quota refunds). If it persists, email hello@beliq.eu with the error.incidentId
CONVERSION_TOOL_ERROR 500 A converter failed on this document or returned a document that could not be used, or the validation of the converted document could not finish. It is not a verdict on the document /v1/convert The message names the cause. A converter fails the same way on the same bytes. The quota unit is refunded. Email hello@beliq.eu with the error.incidentId
Transmission errors (preview)

Transmission errors (preview)

Code HTTP Status Meaning Remediation
TRANSMISSION_DISABLED 503 Transmission is not enabled on this deployment, so every transmission endpoint refuses the request. Build and validate the file and deliver it through your own channel. Subscribe for the launch date.
TRANSMISSION_NO_PROVIDER 503 Transmission is enabled, but no provider is currently available for the target network in your key’s mode, so the document would queue with no path forward. If the response carries Retry-After, the provider failed recently and Beliq is checking whether it is back. After that many seconds a retry can be accepted as the first document of that check. It can also be refused again, with a new Retry-After, while the check is still running or after it failed. Without Retry-After, the provider is unavailable until Beliq changes something on its side, so an automatic retry meets the same refusal. The one exception is the sandbox test invoice (POST /v1/participants/sandbox/test-invoice), which never sends Retry-After with this code, so its refusal can also be one that a later retry gets past. If it persists, check the status page and email hello@beliq.eu with the x-request-id response header.
IDEMPOTENCY_KEY_REUSED 409 An Idempotency-Key was reused with a different request body. Use a fresh key for a different document, or resend the identical body to get the existing transmission back.
INVALID_IDEMPOTENCY_KEY 400 The Idempotency-Key header is longer than 255 characters or contains something other than printable ASCII. Shorten the key and keep it to printable ASCII. A UUID is the usual choice. Rejected before any quota is spent.
SENDER_NOT_REGISTERED 403 The sender identifier is not a registered, active participant of your organization, so you may not send as it. Register the identifier and complete the ownership check before sending as it. The message says whether there is no registration at all or one that is not active yet.
CONTENT_ALREADY_SENT 409 This exact document was already sent to this recipient and that transmission can still arrive, so nothing was queued. details.transmissionId names it. Poll the existing transmission. To make retries unambiguous, send an Idempotency-Key. A resend is accepted once the earlier transmission reaches failed, or rejected on a network where a rejection does not burn the invoice number (see FRANCE_INVOICE_NUMBER_BURNED).
SENDER_COUNTRY_MISSING 409 The participant registration you are sending as records no country. Every Peppol envelope carries the sending entity’s country, so the registration cannot send until it is set. Email hello@beliq.eu to complete the registration.
RECIPIENT_NOT_ROUTABLE 400 The recipient identifier is not in a form the Peppol Network can address. A Peppol identifier is a four-digit scheme code and a value, for example 0088:5790000435975.
DOCUMENT_PARTY_MISMATCH 400 The document’s own identifier for the sender or the recipient names a different party than the request does. On Peppol that is the electronic address; on Italy SdI it is the VAT number of each party the platform could send the document as. details says which role and gives both identifiers, and the message names the element that disagrees. Make the document and the request agree. On Peppol an EndpointID the invoice carries must be the participant you are sending as, and the one you are sending to; a document with none passes this check. POST /v1/send validates the document it builds, and POST /v1/transmissions validates nothing outside a France lane: it queues what you give it. On SdI it is CedentePrestatore/DatiAnagrafici/IdFiscaleIVA, and more: the transmission partner’s documentation says a self-invoice is sent as its buyer, without saying which documents count as one. So the buyer’s CessionarioCommittente/DatiAnagrafici/IdFiscaleIVA must name the sender too when any TipoDocumento is other than TD01 to TD06, TD24 or TD25, or when SoggettoEmittente is CC; with SoggettoEmittente TZ, the VAT in TerzoIntermediarioOSoggettoEmittente must. A document whose parties Beliq cannot read at all is refused the same way, with details.inDocument null: no XML parser runs on it, so any shape two conformant parsers could read differently is refused rather than guessed, and so is a document holding a NUL character or an element name outside ASCII.
FRENCH_DOMESTIC_FLOW 409 Sender and recipient are both French, so this is a regulated domestic flow under the French B2B reform and must reach the network through a plateforme agréée rather than over Peppol. details gives both canonical identifiers. Not a document defect: the invoice may be perfectly valid. Send it through a plateforme agréée of your own. The partner PA lane of managed delivery is in build, so there is no French lane to enable yet. A French sender can still reach a non-French recipient over Peppol.
FRANCE_CTC_BLOCKING_FINDINGS 422 The document trips one or more BR-FR-CTC Flux 2 rules. A plateforme agréée refuses a document carrying any of them whatever severity the rule pack assigns, so Beliq refuses before the send spends the invoice number. details.ruleIds lists them. Note that valid on POST /v1/validate reports the severity the rule pack assigns: the Flux 2 pack in force flags every one of these rules fatal, and an earlier version flagged most of them as warnings, so a validation that ran the earlier version can report valid: true for the same document. franceCtcBlockingRuleIds on the validation result is the field that answers for transmission. Correct what the listed rules point at and send again. Validate first with POST /v1/validate and check that franceCtcApplied is true and franceCtcBlockingRuleIds is absent.
FRANCE_CTC_NOT_JUDGED 422 The document was not judged against the French CTC rules, so Beliq holds no verdict it can stand behind for a plateforme agréée. Almost always this is a missing BT-23 cadre de facturation, which is also what keeps BR-FR-08, the rule that would have reported it, from running. On POST /v1/transmissions there is a second cause: the BR-FR-CTC Flux 2 pack ran and gave no verdict, because its run failed, timed out or produced a report over the size limit. (On POST /v1/send such a run fails the composed document’s validation first, as INVALID_INVOICE.) Add BT-23 from the closed cadre list, or declare the EXTENDED-CTC-FR profile in BT-24. See France. If BT-23 already carries a code from that list, the pack did not finish. Nothing was queued: a failed or timed-out run can pass when you send again, while a report over the size limit repeats for the same document. Email hello@beliq.eu if it repeats.
FRANCE_INVOICE_NUMBER_BURNED 409 A plateforme agréée already rejected this exact document. A French invoice number is unique on (number, supplier SIREN, invoice year) and a rejected invoice must be reissued under a new number, so Beliq refuses the resend rather than queue a second document under a spent one. details.transmissionId names the rejected transmission. Issue a corrected invoice under a new number and send that. Do not retry the same bytes: the platform’s own uniqueness check does not stop the reuse, which is why this one is on Beliq’s side.
UNSUPPORTED_SYNTAX 400 Only UBL and CII documents can be sent over Peppol. Convert the document first: see POST /v1/convert.
MISSING_CUSTOMIZATION_ID 400 The document carries no CustomizationID, so its Peppol document type identifier cannot be derived and no receiving Access Point can be looked up. Add the CustomizationID for the profile you are sending, for example urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0.
MISSING_PROCESS_ID 400 The document carries no ProfileID (UBL) or business process identifier (CII), so its Peppol process identifier cannot be derived. Add it, for example urn:fdc:peppol.eu:2017:poacc:billing:01:1.0.
MALFORMED_DOCUMENT 400 The document is not well-formed XML, or it declares a DOCTYPE. Fix the XML. A DOCTYPE is refused outright: no valid e-invoice declares one.
EMPTY_DOCUMENT 400 The document body is empty. Send the invoice XML in the request body.
INSUFFICIENT_ROLE 403 The API key or member calling POST /v1/participants/sandbox or POST /v1/participants/sandbox/test-invoice does not hold a role that may write integration resources. Call it as an owner, admin or developer. A test identifier spends a registration in a partner account, which is why a viewer or a billing member cannot issue one.
ENROLLMENT_MODE_UNSUPPORTED 409 The provider serving that network obtains a customer’s authorization in a way Beliq has no self-service flow for, so there is nothing a corrected request would reach. Not a retry: waiting does not clear it. Email hello@beliq.eu to register on that network.
ENROLLMENT_REFUSED 422 Beliq’s own checks passed and the delivery partner refused the registration anyway. The partner’s own wording is deliberately not relayed: the refusal Beliq most expects, an identifier another account already holds, is indistinguishable on the wire from any other, so repeating it would read as a diagnosis Beliq cannot make. Retry once; if it persists, email hello@beliq.eu with the x-request-id response header.
INBOX_UNKNOWN_PROVIDER 404 An inbound network callback referenced a provider that is not registered. Provider-side authentication error, not reachable with an API key.
INBOX_VERIFICATION_FAILED 401 An inbound network callback or document failed signature verification. Provider-side authentication error, not reachable with an API key.
INBOX_SIGNATURE_EXPIRED 401 An inbound network callback carried a valid signature whose timestamp fell outside the accepted freshness window, so it is refused as a replay. Provider-side authentication error, not reachable with an API key.
HTTP status code summary

HTTP status code summary

Status Meaning
200 Success
400 Bad request: invalid JSON, missing required fields, or unsupported format combination
401 Unauthorized: no API key was sent
403 Forbidden: the key that was sent is malformed, does not exist or has been revoked, or you may not send as the sender identifier (transmission, preview)
404 Not found: no route exists at the requested path and method, or a referenced resource (e.g. a pdfTemplateId) does not exist in your organization
409 Conflict: an Idempotency-Key was reused with a different body, or the same document was already sent to that recipient (transmission, preview)
413 Payload too large: the request body exceeds the endpoint’s size limit and is not read, or the engine refused a body within that limit as too large to process
415 Unsupported media type: the Content-Type is not one this route reads. /v1/validate, /v1/parse and /v1/convert take application/xml, text/xml, application/octet-stream or application/pdf; on those three, a JSON object or array sent as application/json gets a 400 instead, and text/plain is read as UTF-8 text (each route’s 415 row says more); the free public demo is narrower still and takes XML only
422 Unprocessable entity: input is syntactically valid but fails business rules or parsing
429 Too many requests: quota exceeded or rate limited
500 Internal server error
503 Service unavailable: the engine or Beliq’s database is temporarily unavailable, or transmission is not enabled
Request size limits

Request size limits

Each endpoint caps the size of the request body. The cap is enforced before the body is read, so an oversize request is refused without being parsed or validated, and it never spends a quota unit.

Endpoint Limit
POST /v1/validate 1 MiB
POST /v1/parse 1 MiB
POST /v1/generate 1 MiB
POST /v1/convert 1 MiB
POST /v1/send (preview) 1 MiB
POST /v1/receive (preview) 1 MiB
POST /v1/transmissions (preview) 5 MiB
POST /v1/inbox/:providerId (preview) 5 MiB

Exceeding the limit returns 413 with code VALIDATION_ERROR:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request body exceeds the size limit of 1 MiB for this endpoint. The body was not read, so this is not a validation failure. Send a smaller document."
  }
}

A body within the limit can still be too large for the engine to process. On /v1/generate, /v1/validate, /v1/parse and /v1/convert that is also a 413 with code VALIDATION_ERROR, whose message says the request is within this endpoint’s body size limit but too large to process; the body was read, and a live key’s quota unit is refunded (see the next section). On /v1/send and /v1/receive (preview) the same refusal is a 400 VALIDATION_ERROR that keeps its unit.

The code is the coarse class tag shared by every 4xx an endpoint answers that is not one of the specific codes above; the 413 status is the discriminator. Read the status, not the code, to tell an oversize body from a schema failure.

Quota refunds on a Beliq-side failure

Quota refunds on a Beliq-side failure

When a request fails for a reason on our side rather than in your document, the quota unit that request spent goes back. That covers every ENGINE_UNAVAILABLE (503), and the conversion-tool failures on /v1/convert (CONVERSION_TOOL_UNAVAILABLE, CONVERSION_TOOL_ERROR). It also covers a body the engine refused as too large on /v1/generate, /v1/validate, /v1/parse and /v1/convert (a 413, see Request size limits), and two answers of POST /v1/generate for a PDF that was not delivered: a 500 INTERNAL_ERROR when the PDF could not be produced, and a 422 PDFA_VIOLATION, which is about the PDF page and not about your invoice data. It does not cover any other 4xx that names something in your document: that is an answer you asked for, and it keeps its unit. A CONVERSION_OUTPUT_INVALID (422) on /v1/convert keeps its unit as well, whatever made the converted document fail: Beliq validates the output and not the source, so it cannot tell a source that was already invalid from one a converter changed. POST /v1/convert says more.

A DATABASE_UNAVAILABLE (503) is a failure on our side too. If the request had spent a unit, Beliq tries the refund at once. It does the same when the charge itself was cut off and may have gone through. While the database is down that refund usually cannot be applied. Most often the database fails the request before any unit is spent, because the key check comes first: then nothing was charged and there is nothing to refund.

Every response that refunds, or should have, says so on the x-beliq-quota-refunded header:

Header Meaning
true The unit went back. A retry costs you nothing.
false The unit was not returned: the cap below applied, or the refund could not be applied, which is the usual outcome on a DATABASE_UNAVAILABLE.
absent No live unit was at stake (a successful call, a document error, a DATABASE_UNAVAILABLE that came before any unit was spent, or a test-key request, which meters against the sandbox allowance instead).

Refunds are unconditional for the failures where nothing was computed: an unreachable engine, a shed request, a missing conversion tool, a body the engine refused as too large. Where a failure did consume engine compute (a timeout, a fault raised part-way through processing, or a PDF that was built and then not delivered) refunds are capped at 50 per organization per clock hour. The cap exists so a deliberately expensive document cannot be run repeatedly at no cost; normal traffic through a real incident stays well under it. A DATABASE_UNAVAILABLE refund is not capped. If you see x-beliq-quota-refunded: false on volume you consider legitimate, or on any DATABASE_UNAVAILABLE, email hello@beliq.eu with the error.incidentId, or with the x-request-id response header when the answer carries none, and we will reconcile it.

VALIDATION_ERROR details

VALIDATION_ERROR details

A VALIDATION_ERROR raised by JSON schema validation carries details.fields, one entry per rejected constraint. This is the 400 on POST /v1/generate for a body that fails the schema, and on POST /v1/validate, /v1/parse and /v1/convert for a query string that fails it. A body that passes the schema can still be refused by the engine, for a rule the generate page names, such as a buyer taxId on Factur-X basic: that 400 carries no details, and its message says what was refused. The 400 for a URL the router cannot route carries no details either. The other statuses that share the code (413, 415, and any other 4xx with no more specific code) reject before or outside the schema and carry no details at all.

Field Type Description
path string? Where the constraint failed. A JSON Pointer into the request body (/invoice/lines/0/unitPrice), or into the query string on the three query routes (/format), except for a property missing at the top level, where it is the bare property name (standard). An undeclared property is named by its own pointer, /invoice/foo, or /foo at the top level. Absent when the failure is at the root of the body and names no property, such as a body that is not a JSON object
message string The constraint in words, relative to path (must have required property 'number', must be number)
keyword string The JSON Schema keyword that rejected it (required, type, const, anyOf, minimum)

A missing nested property reports the parent object as path and names the child in message, so { "standard": "xrechnung", "output": "xml", "invoice": { "issueDate": "2026-04-13" } } answers:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "body/invoice must have required property 'number'",
    "details": {
      "fields": [
        {
          "path": "/invoice",
          "message": "must have required property 'number'",
          "keyword": "required"
        }
      ]
    }
  }
}

One bad value can produce several entries. A standard outside the accepted set is checked against each allowed value in turn, so it yields one const entry per candidate plus a closing anyOf entry, all of them on the same path. Read fields as the list of constraints that failed, not as a list of distinct problems, and key your own error reporting on path.

INVALID_INVOICE details

INVALID_INVOICE details

INVALID_INVOICE includes a full validationResult in details, matching the validation result from /v1/validate:

{
  "success": false,
  "error": {
    "code": "INVALID_INVOICE",
    "message": "Invoice validation failed with 1 error",
    "details": {
      "validationResult": {
        "valid": false,
        "format": "cii",
        "schematronVersion": "1.3.16",
        "ciusVersion": "XRechnung-2.6.0",
        "errors": [
          {
            "ruleId": "BR-DE-15",
            "severity": "error",
            "location": "/rsm:CrossIndustryInvoice",
            "message": "An XRechnung invoice must contain a buyer reference (BT-10)."
          }
        ],
        "warnings": []
      }
    }
  }
}
PROFILE_STANDARD_MISMATCH details

PROFILE_STANDARD_MISMATCH details

PROFILE_STANDARD_MISMATCH includes the rejected combination so you can correct the request:

{
  "success": false,
  "error": {
    "code": "PROFILE_STANDARD_MISMATCH",
    "message": "Profile 'extended' is not allowed for standard 'peppol-bis'.",
    "details": {
      "standard": "peppol-bis",
      "profile": "extended",
      "allowedProfiles": ["peppol"]
    }
  }
}
DOCUMENT_TYPE_STANDARD_MISMATCH details

DOCUMENT_TYPE_STANDARD_MISMATCH details

DOCUMENT_TYPE_STANDARD_MISMATCH is returned when documentType: "creditnote" is sent for a standard that only supports invoices, notably fatturapa, facturae and ksef. The four EN 16931 hybrid/XML routes peppol-bis, facturx, xrechnung, and zugferd accept CreditNotes, as does the national eslog route (document type code 381 on the same e-SLOG message). Inspect creditNoteCapableStandards in error details; it mirrors the deployed engine capability set.

{
  "success": false,
  "error": {
    "code": "DOCUMENT_TYPE_STANDARD_MISMATCH",
    "message": "documentType='creditnote' is not supported for standard 'fatturapa'. Accepted for CreditNote payloads: ['eslog', 'facturx', 'peppol-bis', 'xrechnung', 'zugferd'].",
    "details": {
      "standard": "fatturapa",
      "documentType": "creditnote",
      "creditNoteCapableStandards": ["eslog", "facturx", "peppol-bis", "xrechnung", "zugferd"]
    }
  }
}

The same code answers a typeCode (BT-3) sent with a standard whose builder writes its own document type: fatturapa, facturae, eslog and ksef. Beliq refuses rather than build the document with the standard’s default code in place of yours, which would send a corrected invoice out as a commercial one. Here details carries typeCode and typeCodeCapableStandards instead of the credit note keys, so read whichever pair is present.

{
  "success": false,
  "error": {
    "code": "DOCUMENT_TYPE_STANDARD_MISMATCH",
    "message": "typeCode='384' is not supported for standard 'fatturapa', whose builder writes its own document type. Accepted for typeCode: ['facturx', 'peppol-bis', 'xrechnung', 'zugferd'].",
    "details": {
      "standard": "fatturapa",
      "typeCode": "384",
      "typeCodeCapableStandards": ["facturx", "peppol-bis", "xrechnung", "zugferd"]
    }
  }
}
PDFA_VIOLATION details

PDFA_VIOLATION details

POST /v1/generate builds a ZUGFeRD or Factur-X PDF and then runs veraPDF 1.30.3 on the finished file (the PDF/A check on a hybrid PDF). When veraPDF reports a violation of its PDF/A-3b profile, the PDF is not returned and the answer is 422 PDFA_VIOLATION. details.failedRules lists the rules veraPDF reported as failed, at most 20 of them. Each entry holds these keys, under the names and with the values veraPDF’s own report gives them:

Key Type Description
specification string The specification the rule belongs to, as veraPDF names it (ISO 19005-3:2012)
clause string The clause of that specification (6.2.11.4.1)
testNumber integer veraPDF’s number of the test inside the clause
description string veraPDF’s text for the rule
failedChecks integer How many checks of the rule veraPDF counted as failed in the file
{
  "success": false,
  "error": {
    "code": "PDFA_VIOLATION",
    "message": "veraPDF reported a violation of its PDF/A-3b profile in the generated PDF, so the PDF was not returned.",
    "details": {
      "failedRules": [
        {
          "specification": "ISO 19005-3:2012",
          "clause": "6.2.11.4.1",
          "testNumber": 1,
          "description": "The font programs for all fonts used for rendering within a conforming file shall be embedded within that file, as defined in ISO 32000-1:2008, 9.9",
          "failedChecks": 3
        }
      ]
    }
  }
}

The list is veraPDF’s: Beliq adds no rule and rewrites no text. veraPDF is run with a limit on the failed checks it collects for one file, so failedChecks has an upper bound and the list may not hold every rule the file breaks. It keeps of each rule only what veraPDF’s report holds under these five names with these types, so an entry can lack a key and the list can be empty. The answer carries no incidentId.

PDF template errors

PDF template errors

These are returned only when a pdfTemplateId is referenced on POST /v1/generate. Stored templates are designed in the dashboard and are scoped to your organization, so they require an authenticated request.

Code When Fix
PDF_TEMPLATE_AUTH_REQUIRED pdfTemplateId sent on an unauthenticated request Use your API key, or switch to template: "standard"
PDF_TEMPLATE_NOT_FOUND The ref is not a template in your organization Verify the ref in the dashboard
PDF_TEMPLATE_INVALID The stored definition is corrupt or fails the designer’s checks, so it cannot be rendered Fix the named field in the designer and save
{
  "success": false,
  "error": {
    "code": "PDF_TEMPLATE_NOT_FOUND",
    "message": "PDF template k3d-9mp was not found."
  }
}
Request ID and incident ID

Request ID and incident ID

Every API response includes an x-request-id header (UUID). Quote it to hello@beliq.eu for faster troubleshooting.

x-request-id: 7f3d2a1b-4e5c-6d7f-8a9b-0c1d2e3f4a5b

A 5xx that an endpoint in this reference raises itself additionally carries an error.incidentId in the response body. It links the response directly to the captured error event on our side, so quoting it in a support request is the fastest path to a diagnosis:

{
  "success": false,
  "error": {
    "code": "ENGINE_UNAVAILABLE",
    "message": "The e-invoice processing service is temporarily unavailable. Please try again shortly.",
    "incidentId": "V7mKp2XwQd"
  }
}

Every DATABASE_UNAVAILABLE carries one too, whichever endpoint answers it, GET /v1/me included.

The 503s that refuse a feature that is switched off or has no provider, TRANSMISSION_DISABLED and TRANSMISSION_NO_PROVIDER, carry none: quote the x-request-id header for those.