{
  "openapi": "3.0.3",
  "info": {
    "title": "Valinvo API",
    "version": "1.0.0-beta",
    "description": "Valinvo turns one JSON invoice (based on the EN 16931 semantic model) into an XRechnung 3.0.2 (UBL or CII), Peppol BIS Billing 3.0.21 or ZUGFeRD 2.5.2 / Factur-X 1.09.2 (EN 16931 profile; also with the French rules for the French reform, beta) e-invoice, and validates existing e-invoices against the official rule sets. Status: beta.\n\n**Terms.** The API is for businesses only and is subject to the Terms of Use and the Data Processing Agreement. Without an API key, accept them by sending `X-Accept-Terms: 1.0` (the current version) with each request; requests without it get `428 terms_not_accepted`. Every `/v1/` response links the terms in a `Link: <…/terms>; rel=\"terms-of-service\"` header. The trial without a key is for testing: use sample data, not real invoices with other people's personal data.\n\n**Limits.** Without a key: 2 created invoices per day per IP address, one request at a time, 60 `/v1/invoices` and 20 `/v1/validate` requests per minute. Invoice JSON up to 2 MB and 2,000 lines; documents to validate up to 20 MB and 75,000 XML elements.\n\n**Money.** Amounts, quantities and VAT rates are JSON strings (`\"19.99\"`), never numbers.\n\n**Errors.** Every error is a JSON `ApiError` with a stable `code`; invoice problems list the JSON path, the official rule and the EN 16931 business term. Unknown paths get 404 with `not_found`.",
    "termsOfService": "https://valinvo.bmk-hub.com/terms",
    "contact": {
      "name": "Valinvo (BMK HUB)",
      "url": "https://valinvo.bmk-hub.com/contact",
      "email": "hello@bmk-hub.com"
    }
  },
  "externalDocs": {
    "description": "Quickstart with curl examples",
    "url": "https://valinvo.bmk-hub.com/quickstart"
  },
  "servers": [
    { "url": "https://valinvo.bmk-hub.com" }
  ],
  "tags": [
    { "name": "invoices", "description": "Create e-invoices from JSON." },
    { "name": "validation", "description": "Validate existing e-invoices." },
    { "name": "formats", "description": "Supported formats and versions." }
  ],
  "paths": {
    "/v1/formats": {
      "get": {
        "tags": ["formats"],
        "operationId": "listFormats",
        "summary": "List supported formats",
        "description": "Every format with its pinned version and status. `beta` formats can be created; `planned` ones not yet. Needs no API key and no terms header.",
        "security": [],
        "responses": {
          "200": {
            "description": "The formats.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FormatsResponse" }
              }
            }
          }
        }
      }
    },
    "/v1/invoices": {
      "post": {
        "tags": ["invoices"],
        "operationId": "createInvoice",
        "summary": "Create an e-invoice from JSON",
        "description": "Checks the invoice against the EN 16931 rules and the rules of the chosen format, calculates line totals, VAT and totals, generates the document and validates it against the official rule set before returning it. An invoice that fails official validation is never returned (`422`).\n\nThe response is the XML file. Send `Accept: application/json` to get the document and the full validation report in one JSON object instead.",
        "security": [{ "apiKey": [] }, { "acceptTerms": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateInvoiceRequest" },
              "example": {
                "format": "peppol-bis-ubl",
                "invoice": {
                  "number": "F-2026-0815",
                  "type": "invoice",
                  "issueDate": "2026-10-19",
                  "dueDate": "2026-11-18",
                  "currency": "EUR",
                  "buyerReference": "PO-BE-2231",
                  "notes": ["Thank you for your business."],
                  "seller": {
                    "name": "Voorbeeld Software BV",
                    "vatId": "BE0456789034",
                    "legalRegistrationId": { "id": "0456789034", "scheme": "0208" },
                    "electronicAddress": { "scheme": "0208", "value": "0456789034" },
                    "address": { "line1": "Kunstlaan 10", "city": "Brussel", "postalCode": "1000", "countryCode": "BE" },
                    "contact": { "name": "Sofie Peeters", "email": "billing@voorbeeld-software.be" }
                  },
                  "buyer": {
                    "name": "Exemple Services SRL",
                    "vatId": "BE0765432146",
                    "electronicAddress": { "scheme": "0208", "value": "0765432146" },
                    "address": { "line1": "Rue de la Loi 200", "city": "Bruxelles", "postalCode": "1040", "countryCode": "BE" }
                  },
                  "payment": {
                    "meansCode": "30",
                    "iban": "BE68539007547034",
                    "remittanceInformation": "+++081/2026/08155+++",
                    "terms": "Payable within 30 days."
                  },
                  "lines": [
                    {
                      "id": "1",
                      "name": "Invoicing software subscription, October 2026",
                      "quantity": "1",
                      "unitCode": "C62",
                      "unitPrice": "49.00",
                      "vat": { "category": "S", "rate": "21" }
                    },
                    {
                      "id": "2",
                      "name": "Implementation consulting",
                      "quantity": "3",
                      "unitCode": "HUR",
                      "unitPrice": "95.00",
                      "vat": { "category": "S", "rate": "21" }
                    }
                  ],
                  "totals": { "lineTotal": "334.00", "vatTotal": "70.14", "amountDue": "404.14" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The e-invoice. It passed the official validation; warnings, if any, are counted in `X-Validation-Warnings`.",
            "headers": {
              "X-Validation-Status": { "description": "Always `valid` here.", "schema": { "type": "string", "enum": ["valid"] } },
              "X-Validation-Warnings": { "description": "Number of warnings from the official rules.", "schema": { "type": "integer" } },
              "X-Rule-Set": { "description": "The rule set applied, e.g. `peppol-bis-3.0.21-ubl-invoice`.", "schema": { "type": "string" } },
              "X-Trial-Limit": { "$ref": "#/components/headers/X-Trial-Limit" },
              "X-Trial-Remaining": { "$ref": "#/components/headers/X-Trial-Remaining" },
              "Content-Disposition": { "description": "Attachment named after the invoice number (file response only, `.xml` or `.pdf`).", "schema": { "type": "string" } }
            },
            "content": {
              "application/xml": {
                "schema": { "type": "string", "format": "binary" }
              },
              "application/pdf": {
                "schema": { "type": "string", "format": "binary" }
              },
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GeneratedInvoiceResponse" }
              }
            }
          },
          "400": {
            "description": "The request or the invoice is invalid. Codes: `invalid_json`, `invalid_request` (envelope), `unknown_format`, `invalid_invoice` (with every problem at once in `problems`), `bad_request`.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiError" },
                "example": {
                  "code": "invalid_invoice",
                  "message": "The invoice has 1 problem. Fix it and try again.",
                  "problems": [
                    {
                      "path": "invoice.buyerReference",
                      "message": "Peppol requires buyerReference or orderReference.",
                      "rule": "PEPPOL-EN16931-R003",
                      "businessTerm": "BT-10"
                    }
                  ]
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/InvalidApiKey" },
          "413": {
            "description": "`payload_too_large`: the JSON body is larger than 2 MB.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
          },
          "422": {
            "description": "`generated_invoice_invalid`: the generated invoice did not pass the official validation; `validation.errors` says why. Usually a field required by a national rule is missing.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
          },
          "428": { "$ref": "#/components/responses/TermsNotAccepted" },
          "429": {
            "description": "`trial_limit_reached` (today's free invoices are used up), `one_request_at_a_time` (without a key) or `rate_limited`.",
            "headers": {
              "X-Trial-Limit": { "$ref": "#/components/headers/X-Trial-Limit" },
              "X-Trial-Remaining": { "$ref": "#/components/headers/X-Trial-Remaining" }
            },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
          },
          "500": { "$ref": "#/components/responses/InternalError" },
          "503": { "$ref": "#/components/responses/Busy" }
        }
      }
    },
    "/v1/validate": {
      "post": {
        "tags": ["validation"],
        "operationId": "validateInvoice",
        "summary": "Validate an e-invoice",
        "description": "Validates an e-invoice against the official rules (XML schema and Schematron). Send the XML, or a ZUGFeRD / Factur-X PDF: then the invoice XML embedded in the PDF (`factur-x.xml`, `zugferd-invoice.xml` or `xrechnung.xml`) is checked, plus the PDF itself against PDF/A-3 (veraPDF; rule IDs like `PDF/A-3 6.2.11.4.1-1`) and its XMP metadata against the XML (profile and attachment name; rule IDs `ZF-XMP-…`). The `ruleSet` then names both, e.g. `zugferd-2.5.2-en16931+pdf-a-3b`. The rule set is detected from the document: XRechnung 3.0 (UBL Invoice, UBL CreditNote, CII), Peppol BIS Billing 3.0 (UBL Invoice, UBL CreditNote) and ZUGFeRD 2.x / Factur-X in CII with the profiles MINIMUM, BASIC WL, BASIC, EN 16931 and EXTENDED (checked against the ZUGFeRD 2.5.2 rules). An invalid invoice is a normal `200` result with `valid: false` and the list of errors.",
        "security": [{ "apiKey": [] }, { "acceptTerms": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/xml": {
              "schema": { "type": "string", "format": "binary" }
            },
            "application/pdf": {
              "schema": { "type": "string", "format": "binary" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The validation report.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ValidationReport" },
                "example": { "ruleSet": "peppol-bis-3.0.21-ubl-invoice", "valid": true, "errors": [], "warnings": [] }
              }
            }
          },
          "400": {
            "description": "`invalid_xml` (not well-formed), `unsupported_document` (not an invoice or credit note in a supported format), `invalid_pdf` (unreadable or password-protected PDF), `no_embedded_invoice` (a PDF without a `factur-x.xml`, `zugferd-invoice.xml` or `xrechnung.xml` attachment) or `bad_request`.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
          },
          "401": { "$ref": "#/components/responses/InvalidApiKey" },
          "413": {
            "description": "`payload_too_large` (larger than 20 MB) or `document_too_large` (more than 75,000 XML elements, about 3,000 invoice lines, or an embedded invoice XML larger than 20 MB).",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
          },
          "428": { "$ref": "#/components/responses/TermsNotAccepted" },
          "429": {
            "description": "`one_request_at_a_time` (without a key) or `rate_limited`.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
          },
          "500": { "$ref": "#/components/responses/InternalError" },
          "503": { "$ref": "#/components/responses/Busy" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Beta API key, sent as `Authorization: Bearer <key>`. Removes the daily trial limit. Write to hello@bmk-hub.com for one."
      },
      "acceptTerms": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Accept-Terms",
        "description": "Without an API key: the version of the Terms of Use you accept, currently `1.0`."
      }
    },
    "headers": {
      "X-Trial-Limit": {
        "description": "Without an API key: free invoices per day.",
        "schema": { "type": "integer" }
      },
      "X-Trial-Remaining": {
        "description": "Without an API key: free invoices left today.",
        "schema": { "type": "integer" }
      }
    },
    "responses": {
      "InvalidApiKey": {
        "description": "`invalid_api_key`: the `Authorization` header is not a valid `Bearer` key.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      },
      "TermsNotAccepted": {
        "description": "`terms_not_accepted`: without an API key, send `X-Accept-Terms: 1.0`.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      },
      "InternalError": {
        "description": "`internal_error`: something went wrong on our side.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      },
      "Busy": {
        "description": "`busy`: the server is busy; try again after `Retry-After` seconds.",
        "headers": { "Retry-After": { "schema": { "type": "integer" } } },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      }
    },
    "schemas": {
      "Decimal": {
        "type": "string",
        "pattern": "^-?\\d+(\\.\\d+)?$",
        "description": "Money, quantity or rate as a JSON string in plain decimal notation, e.g. `\"19.99\"`. No exponent, thousands separator or leading `+`.",
        "example": "19.99"
      },
      "IsoDate": {
        "type": "string",
        "format": "date",
        "description": "Calendar date `YYYY-MM-DD`.",
        "example": "2026-10-19"
      },
      "CreateInvoiceRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["format", "invoice"],
        "properties": {
          "format": { "type": "string", "enum": ["xrechnung-ubl", "xrechnung-cii", "peppol-bis-ubl", "zugferd-en16931", "factur-x-fr", "cii-fr", "ubl-fr"], "description": "Format ID from `GET /v1/formats`. `zugferd-en16931` returns a PDF/A-3 with the CII XML embedded (ZUGFeRD 2.5.2 / Factur-X 1.09.2, EN 16931 profile)." },
          "invoice": { "$ref": "#/components/schemas/Invoice" }
        }
      },
      "Invoice": {
        "type": "object",
        "additionalProperties": false,
        "description": "The canonical invoice. Every field maps to an EN 16931 business term (BT) or group (BG). Unknown fields are rejected.",
        "required": ["number", "issueDate", "currency", "seller", "buyer", "lines"],
        "properties": {
          "number": { "type": "string", "description": "BT-1 Invoice number." },
          "type": { "$ref": "#/components/schemas/InvoiceType" },
          "issueDate": { "$ref": "#/components/schemas/IsoDate" },
          "dueDate": { "$ref": "#/components/schemas/IsoDate" },
          "taxPointDate": { "$ref": "#/components/schemas/IsoDate" },
          "currency": { "type": "string", "description": "BT-5 Invoice currency, ISO 4217, e.g. `EUR`.", "example": "EUR" },
          "buyerReference": { "type": "string", "description": "BT-10 Buyer reference; the Leitweg-ID for German public buyers." },
          "orderReference": { "type": "string", "description": "BT-13 Purchase order reference." },
          "contractReference": { "type": "string", "description": "BT-12 Contract reference." },
          "precedingInvoice": { "$ref": "#/components/schemas/InvoiceReference" },
          "notes": { "type": "array", "items": { "type": "string" }, "description": "BT-22 Invoice notes." },
          "codedNotes": { "type": "array", "items": { "$ref": "#/components/schemas/CodedNote" }, "description": "BG-1 notes with a subject code (BT-21 + BT-22). French invoices need PMT, PMD and AAB." },
          "billingFrame": { "type": "string", "description": "BT-23 for formats that let you set it (`factur-x-fr`): the French cadre de facturation B1 (goods), S1 (services), M1 (mixed), B2/S2/M2 (the same, already paid). Other formats reject it." },
          "delivery": { "$ref": "#/components/schemas/Delivery" },
          "billingPeriod": { "$ref": "#/components/schemas/Period" },
          "seller": { "$ref": "#/components/schemas/Party" },
          "buyer": { "$ref": "#/components/schemas/Party" },
          "payment": { "$ref": "#/components/schemas/Payment" },
          "lines": { "type": "array", "minItems": 1, "maxItems": 2000, "items": { "$ref": "#/components/schemas/InvoiceLine" }, "description": "BG-25 Invoice lines." },
          "allowances": { "type": "array", "items": { "$ref": "#/components/schemas/DocumentAllowanceCharge" }, "description": "BG-20 Document level allowances." },
          "charges": { "type": "array", "items": { "$ref": "#/components/schemas/DocumentAllowanceCharge" }, "description": "BG-21 Document level charges." },
          "vatExemptions": { "type": "array", "items": { "$ref": "#/components/schemas/VatExemption" }, "description": "BT-120 / BT-121, one entry per exempt VAT category used." },
          "prepaidAmount": { "$ref": "#/components/schemas/Decimal" },
          "taxCurrency": { "$ref": "#/components/schemas/TaxCurrency" },
          "totals": { "$ref": "#/components/schemas/Totals" }
        }
      },
      "InvoiceType": {
        "type": "string",
        "enum": ["invoice", "credit_note", "prepayment_invoice"],
        "default": "invoice",
        "description": "BT-3: `invoice` (380), `credit_note` (381) or `prepayment_invoice` (386, down payment; French formats only so far)."
      },
      "TaxCurrency": {
        "type": "object",
        "additionalProperties": false,
        "description": "BT-6 + BT-111: the VAT total in the VAT accounting currency, as your accounting converted it (we never choose an exchange rate). France requires EUR when the invoice currency isn't EUR.",
        "required": ["code", "vatTotal"],
        "properties": {
          "code": { "type": "string", "description": "BT-6 ISO 4217", "example": "EUR" },
          "vatTotal": { "$ref": "#/components/schemas/Decimal" }
        }
      },
      "CodedNote": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-1 An invoice note with its subject code.",
        "required": ["code", "text"],
        "properties": {
          "code": { "type": "string", "description": "BT-21 UNTDID 4451 subject code, e.g. PMT, PMD, AAB, REG.", "example": "PMT" },
          "text": { "type": "string", "description": "BT-22" }
        }
      },
      "InvoiceReference": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-3 Preceding invoice reference.",
        "required": ["number"],
        "properties": {
          "number": { "type": "string", "description": "BT-25" },
          "issueDate": { "$ref": "#/components/schemas/IsoDate" }
        }
      },
      "Delivery": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-13 Delivery information.",
        "properties": {
          "date": { "$ref": "#/components/schemas/IsoDate" }
        }
      },
      "Period": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-14 invoicing period or BG-26 line period.",
        "properties": {
          "start": { "$ref": "#/components/schemas/IsoDate" },
          "end": { "$ref": "#/components/schemas/IsoDate" }
        }
      },
      "Party": {
        "type": "object",
        "additionalProperties": false,
        "description": "Seller (BG-4) or buyer (BG-7).",
        "required": ["name", "address"],
        "properties": {
          "name": { "type": "string", "description": "BT-27 / BT-44" },
          "tradingName": { "type": "string", "description": "BT-28 / BT-45" },
          "legalRegistrationId": { "$ref": "#/components/schemas/Identifier" },
          "vatId": { "type": "string", "description": "BT-31 / BT-48 VAT identifier with country prefix." },
          "taxRegistrationId": { "type": "string", "description": "BT-32, seller only." },
          "additionalLegalInfo": { "type": "string", "description": "BT-33, seller only, e.g. legal form and share capital." },
          "electronicAddress": { "$ref": "#/components/schemas/ElectronicAddress" },
          "address": { "$ref": "#/components/schemas/Address" },
          "contact": { "$ref": "#/components/schemas/Contact" }
        }
      },
      "Identifier": {
        "type": "object",
        "additionalProperties": false,
        "description": "BT-30 / BT-47 Legal registration identifier.",
        "required": ["id"],
        "properties": {
          "id": { "type": "string" },
          "scheme": { "type": "string", "description": "ISO 6523 ICD, e.g. `0208`." }
        }
      },
      "ElectronicAddress": {
        "type": "object",
        "additionalProperties": false,
        "description": "BT-34 / BT-49 Electronic address. XRechnung accepts email (`EM`); Peppol needs a Peppol scheme.",
        "required": ["scheme", "value"],
        "properties": {
          "scheme": { "type": "string", "description": "EAS code, e.g. `EM` (email), `0208` (BE enterprise number), `9930` (DE VAT)." },
          "value": { "type": "string" }
        }
      },
      "Address": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-5 / BG-8 Postal address.",
        "required": ["countryCode"],
        "properties": {
          "line1": { "type": "string", "description": "BT-35 / BT-50" },
          "line2": { "type": "string", "description": "BT-36 / BT-51" },
          "line3": { "type": "string", "description": "BT-162 / BT-163" },
          "city": { "type": "string", "description": "BT-37 / BT-52" },
          "postalCode": { "type": "string", "description": "BT-38 / BT-53" },
          "region": { "type": "string", "description": "BT-39 / BT-54" },
          "countryCode": { "type": "string", "description": "BT-40 / BT-55, ISO 3166-1 alpha-2.", "example": "DE" }
        }
      },
      "Contact": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-6 / BG-9 Contact.",
        "properties": {
          "name": { "type": "string", "description": "BT-41 / BT-56" },
          "phone": { "type": "string", "description": "BT-42 / BT-57" },
          "email": { "type": "string", "description": "BT-43 / BT-58" }
        }
      },
      "Payment": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-16 Payment instructions and BT-20 payment terms.",
        "required": ["meansCode"],
        "properties": {
          "meansCode": { "type": "string", "description": "BT-81, UNTDID 4461, e.g. `58` SEPA credit transfer." },
          "meansText": { "type": "string", "description": "BT-82" },
          "remittanceInformation": { "type": "string", "description": "BT-83" },
          "iban": { "type": "string", "description": "BT-84" },
          "accountName": { "type": "string", "description": "BT-85" },
          "bic": { "type": "string", "description": "BT-86" },
          "terms": { "type": "string", "description": "BT-20 Payment terms." }
        }
      },
      "InvoiceLine": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-25 Invoice line. Line totals are calculated by us.",
        "required": ["id", "name", "quantity", "unitCode", "unitPrice", "vat"],
        "properties": {
          "id": { "type": "string", "description": "BT-126" },
          "name": { "type": "string", "description": "BT-153 Item name." },
          "description": { "type": "string", "description": "BT-154" },
          "sellerItemId": { "type": "string", "description": "BT-155" },
          "note": { "type": "string", "description": "BT-127" },
          "quantity": { "$ref": "#/components/schemas/Decimal" },
          "unitCode": { "type": "string", "description": "BT-130, UN/ECE Rec 20, e.g. `C62` piece, `HUR` hour." },
          "unitPrice": { "$ref": "#/components/schemas/Decimal" },
          "priceBaseQuantity": { "$ref": "#/components/schemas/Decimal" },
          "vat": { "$ref": "#/components/schemas/VatInfo" },
          "allowances": { "type": "array", "items": { "$ref": "#/components/schemas/LineAllowanceCharge" }, "description": "BG-27" },
          "charges": { "type": "array", "items": { "$ref": "#/components/schemas/LineAllowanceCharge" }, "description": "BG-28" },
          "period": { "$ref": "#/components/schemas/Period" }
        }
      },
      "VatInfo": {
        "type": "object",
        "additionalProperties": false,
        "required": ["category"],
        "properties": {
          "category": { "$ref": "#/components/schemas/VatCategory" },
          "rate": { "$ref": "#/components/schemas/Decimal" }
        }
      },
      "VatCategory": {
        "type": "string",
        "enum": ["S", "Z", "E", "AE", "K", "G", "O", "L", "M"],
        "description": "UNTDID 5305: `S` standard, `Z` zero rated, `E` exempt, `AE` reverse charge, `K` intra-community supply, `G` export outside the EU, `O` not subject to VAT, `L` Canary Islands IGIC, `M` Ceuta and Melilla IPSI."
      },
      "LineAllowanceCharge": {
        "type": "object",
        "additionalProperties": false,
        "required": ["amount"],
        "properties": {
          "amount": { "$ref": "#/components/schemas/Decimal" },
          "reason": { "type": "string", "description": "BT-139 / BT-144" },
          "reasonCode": { "type": "string", "description": "BT-140 / BT-145" }
        }
      },
      "DocumentAllowanceCharge": {
        "type": "object",
        "additionalProperties": false,
        "required": ["amount", "vat"],
        "properties": {
          "amount": { "$ref": "#/components/schemas/Decimal" },
          "reason": { "type": "string", "description": "BT-97 / BT-104" },
          "reasonCode": { "type": "string", "description": "BT-98 / BT-105" },
          "vat": { "$ref": "#/components/schemas/VatInfo" }
        }
      },
      "VatExemption": {
        "type": "object",
        "additionalProperties": false,
        "required": ["category"],
        "properties": {
          "category": { "$ref": "#/components/schemas/VatCategory" },
          "reason": { "type": "string", "description": "BT-120" },
          "reasonCode": { "type": "string", "description": "BT-121, VATEX code." }
        }
      },
      "Totals": {
        "type": "object",
        "additionalProperties": false,
        "description": "BG-22, optional. We calculate the totals; every value you send must match our calculation.",
        "properties": {
          "lineTotal": { "$ref": "#/components/schemas/Decimal" },
          "allowanceTotal": { "$ref": "#/components/schemas/Decimal" },
          "chargeTotal": { "$ref": "#/components/schemas/Decimal" },
          "taxExclusive": { "$ref": "#/components/schemas/Decimal" },
          "vatTotal": { "$ref": "#/components/schemas/Decimal" },
          "taxInclusive": { "$ref": "#/components/schemas/Decimal" },
          "amountDue": { "$ref": "#/components/schemas/Decimal" }
        }
      },
      "FormatsResponse": {
        "type": "object",
        "required": ["formats"],
        "properties": {
          "formats": { "type": "array", "items": { "$ref": "#/components/schemas/FormatInfo" } }
        }
      },
      "FormatInfo": {
        "type": "object",
        "required": ["id", "name", "version", "syntax", "mediaType", "status"],
        "properties": {
          "id": { "type": "string", "example": "peppol-bis-ubl" },
          "name": { "type": "string", "example": "Peppol BIS Billing" },
          "version": { "type": "string", "example": "3.0.21" },
          "syntax": { "type": "string", "example": "UBL 2.1" },
          "mediaType": { "type": "string", "example": "application/xml" },
          "status": { "$ref": "#/components/schemas/FormatStatus" }
        }
      },
      "FormatStatus": {
        "type": "string",
        "enum": ["planned", "beta", "available"]
      },
      "GeneratedInvoiceResponse": {
        "type": "object",
        "required": ["format", "contentType", "encoding", "document", "validation"],
        "properties": {
          "format": { "type": "string", "example": "peppol-bis-ubl" },
          "contentType": { "type": "string", "example": "application/xml" },
          "encoding": { "type": "string", "enum": ["utf-8", "base64"], "description": "`utf-8` for XML text, `base64` for binary documents such as PDF." },
          "document": { "type": "string", "description": "The e-invoice." },
          "validation": { "$ref": "#/components/schemas/ValidationReport" }
        }
      },
      "ValidationReport": {
        "type": "object",
        "required": ["ruleSet", "valid", "errors", "warnings"],
        "properties": {
          "ruleSet": { "type": "string", "description": "The rules applied, e.g. `xrechnung-3.0.2-ubl-invoice`." },
          "valid": { "type": "boolean", "description": "True when there are no errors; warnings don't make an invoice invalid." },
          "errors": { "type": "array", "items": { "$ref": "#/components/schemas/ValidationIssue" } },
          "warnings": { "type": "array", "items": { "$ref": "#/components/schemas/ValidationIssue" } }
        }
      },
      "ValidationIssue": {
        "type": "object",
        "required": ["message"],
        "properties": {
          "rule": { "type": "string", "description": "Official rule ID, e.g. `BR-DE-15`; absent for XML schema errors." },
          "message": { "type": "string", "description": "The rule's message as published with the official rules." },
          "location": { "type": "string", "description": "XPath of the offending element for rule errors. XML schema errors carry no line number yet (only the document name)." }
        }
      },
      "Problem": {
        "type": "object",
        "required": ["path", "message"],
        "properties": {
          "path": { "type": "string", "description": "JSON path in the request body, e.g. `invoice.lines[0].vat.rate`.", "example": "invoice.lines[0].vat.rate" },
          "message": { "type": "string" },
          "rule": { "type": "string", "description": "EN 16931 or national business rule, e.g. `BR-S-05`, when one applies." },
          "businessTerm": { "type": "string", "description": "EN 16931 business term, e.g. `BT-152`, when one applies." }
        }
      },
      "ApiError": {
        "type": "object",
        "required": ["code", "message"],
        "properties": {
          "code": { "type": "string", "description": "Stable machine-readable error code, e.g. `invalid_invoice`.", "example": "invalid_invoice" },
          "message": { "type": "string", "description": "What went wrong and how to fix it, in English." },
          "problems": { "type": "array", "items": { "$ref": "#/components/schemas/Problem" }, "description": "For `invalid_invoice` and other input errors: every problem at once." },
          "validation": { "$ref": "#/components/schemas/ValidationReport" }
        }
      }
    }
  }
}
