{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/api-evangelist/normapi-com/main/json-schema/normapi-com-invoice-request-schema.json",
  "title": "InvoiceRequest",
  "x-generated": "2026-10-26",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/normapi-com-generation-api-openapi.yml#/components/schemas/InvoiceRequest",
  "type": "object",
  "required": [
    "invoiceNumber",
    "issueDate",
    "currency",
    "seller",
    "buyer",
    "payment",
    "lines"
  ],
  "properties": {
    "invoiceNumber": {
      "type": "string"
    },
    "issueDate": {
      "type": "string",
      "format": "date"
    },
    "typeCode": {
      "type": "string",
      "pattern": "^[0-9]{3}$",
      "default": "380",
      "description": "BT-3, the document type (UNTDID 1001). XRechnung lists 326 partial\ninvoice, 380 commercial invoice, 381 credit note, 384 corrected\ninvoice, 389 self-billed invoice, 875 partial construction invoice,\n876 partial final construction invoice and 877 final construction\ninvoice; any other code draws the BR-DE-17 warning. A 381 is\ngenerated as a UBL CreditNote, where the due date moves into the\npayment means.\n"
    },
    "precedingInvoices": {
      "type": "array",
      "description": "BG-3, the invoices this one corrects, credits or settles. BR-DE-26\nexpects one on a 384. UBL carries any number; CII — and so\nZUGFeRD — has room for one, and a second fails the CII schema\n(422).\n",
      "items": {
        "$ref": "#/$defs/PrecedingInvoice"
      }
    },
    "dueDate": {
      "type": "string",
      "format": "date",
      "description": "BT-9. XRechnung wants this or paymentTerms on a payable invoice."
    },
    "deliveryDate": {
      "type": "string",
      "format": "date",
      "description": "BT-72. Omitting it and `invoicePeriod` draws an advisory from the\nrule set.\n"
    },
    "deliverTo": {
      "$ref": "#/$defs/DeliverTo"
    },
    "invoicePeriod": {
      "$ref": "#/$defs/Period",
      "description": "BG-14, the period a monthly or yearly invoice covers — instead of\n`deliveryDate`, or beside it.\n"
    },
    "currency": {
      "type": "string"
    },
    "buyerReference": {
      "type": "string",
      "maxLength": 200,
      "description": "BT-10. For public-sector invoices this is the Leitweg-ID. Mandatory\nin every XRechnung (BR-DE-15), optional with `profile=en16931`.\n"
    },
    "orderReference": {
      "type": "string",
      "maxLength": 100,
      "description": "BT-13, the buyer's purchase order number."
    },
    "contractReference": {
      "type": "string",
      "maxLength": 100,
      "description": "BT-12."
    },
    "projectReference": {
      "type": "string",
      "maxLength": 100,
      "description": "BT-11."
    },
    "despatchAdviceReference": {
      "type": "string",
      "maxLength": 100,
      "description": "BT-16, the delivery note (Lieferschein) the goods came with."
    },
    "attachments": {
      "type": "array",
      "maxItems": 20,
      "description": "BG-24, the documents that support the invoice — a timesheet, a\ndelivery note, photos of the work — inside it or by link. Their\nfiles may hold 3 MB together (4 MB as base64), so the invoice that\ncarries them stays within the 5 MB the validator accepts; a JSON\nbody over 6 MB is refused with 413. In CII, and so in ZUGFeRD, more\nthan one file or more than one description draws the warnings\nCII-SR-476 and CII-SR-475, a known defect of those CEN rules; the\ninvoice is accepted.\n",
      "items": {
        "$ref": "#/$defs/Attachment"
      }
    },
    "note": {
      "type": "string",
      "maxLength": 1000,
      "description": "BT-22."
    },
    "seller": {
      "$ref": "#/$defs/Party"
    },
    "buyer": {
      "$ref": "#/$defs/Party"
    },
    "payment": {
      "$ref": "#/$defs/Payment"
    },
    "paymentTerms": {
      "type": "string"
    },
    "allowances": {
      "type": "array",
      "description": "BG-20, allowances on the whole document.",
      "items": {
        "$ref": "#/$defs/AllowanceCharge"
      }
    },
    "charges": {
      "type": "array",
      "description": "BG-21, charges on the whole document — freight, packaging.",
      "items": {
        "$ref": "#/$defs/AllowanceCharge"
      }
    },
    "prepaidAmount": {
      "type": "number",
      "description": "BT-113, already paid — the advances a final invoice (877) settles.\nThe amount due (BT-115) is the gross total less this. Two decimals.\n"
    },
    "lines": {
      "type": "array",
      "minItems": 1,
      "items": {
        "$ref": "#/$defs/Line"
      }
    }
  },
  "$defs": {
    "Address": {
      "type": "object",
      "description": "A postal address: the seller's (BG-5), the buyer's (BG-8) or the\ndelivery's (BG-15). City and postcode are mandatory in XRechnung for\nall three (BR-DE-3/4, BR-DE-8/9, BR-DE-10/11).\n",
      "required": [
        "city",
        "postcode",
        "country"
      ],
      "properties": {
        "street": {
          "type": "string",
          "description": "BT-35 / BT-50 / BT-75."
        },
        "city": {
          "type": "string",
          "description": "BT-37 / BT-52 / BT-77."
        },
        "postcode": {
          "type": "string",
          "description": "BT-38 / BT-53 / BT-78."
        },
        "country": {
          "type": "string",
          "description": "BT-40 / BT-55 / BT-80, ISO 3166-1 alpha-2."
        }
      }
    },
    "AllowanceCharge": {
      "type": "object",
      "description": "A document-level allowance (BG-20, BT-92 to BT-98) or charge (BG-21,\nBT-99 to BT-105) — which one is decided by the list it stands in.\nGive `amount` or `percent`, exactly one. With `percent` the amount is\ncomputed: base × percent / 100, rounded half-up to the cent. It moves\nthe taxable amount of its own VAT category and rate.\n",
      "required": [
        "vatCategory"
      ],
      "properties": {
        "amount": {
          "type": "number",
          "description": "BT-92 / BT-99, two decimals."
        },
        "percent": {
          "type": "number",
          "description": "BT-94 / BT-101."
        },
        "baseAmount": {
          "type": "number",
          "description": "BT-93 / BT-100, what the percentage is taken of. Without it: the\nline nets of the lines in the same VAT category and rate — and if\nthere are none, the request is a 400. Only with `percent`: beside\na plain `amount` the rule set refuses it (PEPPOL-EN16931-R042).\n"
        },
        "reason": {
          "type": "string",
          "description": "BT-97 / BT-104. This or `reasonCode` is required (BR-33, BR-38)."
        },
        "reasonCode": {
          "type": "string",
          "description": "BT-98 (UNTDID 5189, e.g. 95 discount) / BT-105 (UNTDID 7161, e.g. FC freight)."
        },
        "vatCategory": {
          "type": "string",
          "description": "BT-95 / BT-102."
        },
        "vatRate": {
          "type": "number",
          "description": "BT-96 / BT-103."
        },
        "vatExemptionReason": {
          "type": "string",
          "description": "BT-120 for the VAT group this falls into, as on a line."
        }
      }
    },
    "Attachment": {
      "type": "object",
      "description": "One supporting document (BG-24): a file inside the invoice\n(`content` with `filename` and `mimeCode`), a link (`url`), or a\nreference alone. Which types are permitted is the rule set's verdict\n(BR-CL-24: PDF, PNG, JPEG, CSV, XLSX, ODS), as is a filename used\ntwice (BR-DE-22) — both come back as a 422. A file that is not what\nits `mimeCode` says, as far as its first bytes tell, is a 400. In a\nZUGFeRD PDF the files travel in the embedded XML, and the invoice page\nlists them by name.\n",
      "properties": {
        "id": {
          "type": "string",
          "maxLength": 200,
          "description": "BT-122, the document's own number or name; the filename when absent (BR-52)."
        },
        "description": {
          "type": "string",
          "maxLength": 500,
          "description": "BT-123."
        },
        "filename": {
          "type": "string",
          "maxLength": 200,
          "description": "BT-125-2, unique within the invoice (BR-DE-22)."
        },
        "mimeCode": {
          "type": "string",
          "maxLength": 100,
          "description": "BT-125-1, one of the six types BR-CL-24 permits."
        },
        "content": {
          "type": "string",
          "format": "byte",
          "description": "BT-125, the file as base64. Comes with `filename` and `mimeCode`."
        },
        "url": {
          "type": "string",
          "maxLength": 2000,
          "pattern": "^https?://\\S+$",
          "description": "BT-124, where the buyer can fetch the document."
        }
      }
    },
    "Card": {
      "type": "object",
      "description": "BG-18, with payment means 48, 54 or 55.",
      "required": [
        "number"
      ],
      "properties": {
        "number": {
          "type": "string",
          "description": "BT-87, the masked card number. More than 10 digits is a 400: at\nmost the first 6 and the last 4 may appear on an invoice. BR-51\ncounts characters, not digits — over 10 is rejected in CII and\nwarned about in UBL — so send the digits without mask characters.\n"
        },
        "holder": {
          "type": "string",
          "description": "BT-88, the cardholder."
        },
        "network": {
          "type": "string",
          "description": "The card network; UBL requires one and gets NA when absent."
        }
      }
    },
    "DeliverTo": {
      "type": "object",
      "description": "BG-13 apart from its date (`deliveryDate`, BT-72): where the supply\nwent, when not simply to the buyer. Every part is optional, and an\nempty one is not written. An intra-community supply (VAT category K)\nis refused without the country the goods went to (BR-IC-12), so it\nneeds at least `address`.\n",
      "properties": {
        "name": {
          "type": "string",
          "description": "BT-70, who received the goods — a branch, a warehouse, a site."
        },
        "locationId": {
          "type": "string",
          "description": "BT-71, an identifier of the place, e.g. its GLN."
        },
        "locationIdScheme": {
          "type": "string",
          "pattern": "^[0-9]{4}$",
          "description": "BT-71-1, the ISO 6523 ICD of `locationId`: 0088 for a GLN. Without\none the identifier is written as the seller's own.\n"
        },
        "address": {
          "$ref": "#/$defs/Address"
        }
      }
    },
    "DirectDebit": {
      "type": "object",
      "description": "BG-19, with payment means 59. Optional in the request, all three\nrequired by the rule set: the creditor identifier and the debited\naccount by BR-DE-30 and BR-DE-31, the mandate reference by\nPEPPOL-EN16931-R061. Leave out the payee IBAN — the money is\ncollected, not transferred (BR-DE-25-b).\n",
      "properties": {
        "mandateReference": {
          "type": "string",
          "description": "BT-89."
        },
        "creditorId": {
          "type": "string",
          "description": "BT-90, the SEPA creditor identifier (Gläubiger-ID)."
        },
        "debitedAccount": {
          "type": "string",
          "description": "BT-91, the buyer's IBAN the amount is collected from."
        }
      }
    },
    "Line": {
      "type": "object",
      "required": [
        "name",
        "quantity",
        "unit",
        "unitPrice",
        "vatCategory"
      ],
      "properties": {
        "id": {
          "type": "string",
          "description": "BT-126; assigned 1..n when absent."
        },
        "name": {
          "type": "string",
          "description": "BT-153."
        },
        "description": {
          "type": "string",
          "description": "BT-154."
        },
        "quantity": {
          "type": "number"
        },
        "unit": {
          "type": "string"
        },
        "unitPrice": {
          "type": "number",
          "description": "BT-146, the net price — per `baseQuantity` units when one is given."
        },
        "vatCategory": {
          "type": "string"
        },
        "vatRate": {
          "type": "number",
          "description": "BT-152, percent; required for category S."
        },
        "vatExemptionReason": {
          "type": "string",
          "description": "BT-120; the rule set wants it for the exempt-family categories."
        },
        "allowances": {
          "type": "array",
          "description": "BG-27; the line net (BT-131) is quantity × unit price ÷ base quantity, less these.",
          "items": {
            "$ref": "#/$defs/LineAllowanceCharge"
          }
        },
        "charges": {
          "type": "array",
          "description": "BG-28; the line net (BT-131) is quantity × unit price ÷ base quantity, plus these.",
          "items": {
            "$ref": "#/$defs/LineAllowanceCharge"
          }
        },
        "period": {
          "$ref": "#/$defs/Period",
          "description": "BG-26, the period this line covers — a month of a subscription."
        },
        "orderLineReference": {
          "type": "string",
          "maxLength": 50,
          "description": "BT-132, the line of the buyer's purchase order this one bills."
        },
        "note": {
          "type": "string",
          "maxLength": 1000,
          "description": "BT-127, free text on this line alone."
        },
        "sellerItemId": {
          "type": "string",
          "maxLength": 100,
          "description": "BT-155, the seller's article number."
        },
        "buyerItemId": {
          "type": "string",
          "maxLength": 100,
          "description": "BT-156, the buyer's own number for the article."
        },
        "standardItemId": {
          "type": "string",
          "maxLength": 100,
          "description": "BT-157, an identifier under a registered scheme — the GTIN (EAN) on the packaging."
        },
        "standardItemIdScheme": {
          "type": "string",
          "pattern": "^[0-9]{4}$",
          "description": "BT-157-1, the ISO 6523 ICD of `standardItemId`; `0160` (GTIN) when absent."
        },
        "listPrice": {
          "type": "number",
          "description": "BT-148, the price before the item's price discount, at least\n`unitPrice`. The discount (BT-147) is `listPrice − unitPrice`, so it\nis never sent separately.\n"
        },
        "baseQuantity": {
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "BT-149, how many units `unitPrice` and `listPrice` are for — 100 for\nscrews priced per hundred; 1 when absent. The line net is then\nquantity × unit price ÷ base quantity.\n"
        }
      }
    },
    "LineAllowanceCharge": {
      "type": "object",
      "description": "A line allowance (BG-27, BT-136 to BT-140) or charge (BG-28, BT-141\nto BT-145). Give `amount` or `percent`, exactly one. It carries no VAT\nof its own: it changes the line net (BT-131), which stays in the\nline's VAT category.\n",
      "properties": {
        "amount": {
          "type": "number",
          "description": "BT-136 / BT-141, two decimals."
        },
        "percent": {
          "type": "number",
          "description": "BT-138 / BT-143."
        },
        "baseAmount": {
          "type": "number",
          "description": "BT-137 / BT-142. Without it: the line's quantity × unit price,\nrounded to the cent. Only with `percent` (PEPPOL-EN16931-R042).\n"
        },
        "reason": {
          "type": "string",
          "description": "BT-139 / BT-144. This or `reasonCode` is required (BR-42, BR-44)."
        },
        "reasonCode": {
          "type": "string",
          "description": "BT-140 (UNTDID 5189) / BT-145 (UNTDID 7161)."
        }
      }
    },
    "Party": {
      "type": "object",
      "required": [
        "name",
        "address"
      ],
      "properties": {
        "name": {
          "type": "string",
          "description": "BT-27 / BT-44, the legal name."
        },
        "identifier": {
          "type": "string",
          "description": "BT-29 / BT-46. A seller without a VAT id repeats its tax number here:\nBT-32 alone satisfies BR-DE-16 but not BR-CO-26.\n"
        },
        "vatId": {
          "type": "string",
          "description": "BT-31 / BT-48."
        },
        "taxNumber": {
          "type": "string",
          "description": "BT-32, the German Steuernummer."
        },
        "electronicAddress": {
          "type": "string",
          "description": "BT-34 / BT-49, an email address unless the scheme says otherwise.\nXRechnung requires it on both sides (PEPPOL-EN16931-R020 and\nR010); EN 16931 does not.\n"
        },
        "electronicAddressScheme": {
          "type": "string"
        },
        "address": {
          "$ref": "#/$defs/Address"
        },
        "contact": {
          "type": "object",
          "description": "BG-6. XRechnung requires it on the seller with all three parts\n(BR-DE-2, BR-DE-5 to 7), and a missing contact is the most common\nmapping error there. With `profile=en16931` it is optional, and\nany part may stand alone.\n",
          "properties": {
            "name": {
              "type": "string",
              "maxLength": 200,
              "description": "BT-41."
            },
            "phone": {
              "type": "string",
              "maxLength": 50,
              "description": "BT-42."
            },
            "email": {
              "type": "string",
              "maxLength": 254,
              "description": "BT-43."
            }
          }
        },
        "tradingName": {
          "type": "string",
          "maxLength": 200,
          "description": "BT-28 / BT-45, the name the party trades under beside its legal\none. On the ZUGFeRD page it heads the seller block, and the legal\nname opens the address line.\n"
        },
        "registrationId": {
          "type": "string",
          "maxLength": 100,
          "description": "BT-30 / BT-47, the register entry. Like `identifier` and `vatId`\nit identifies a seller for BR-CO-26.\n"
        },
        "registrationIdScheme": {
          "type": "string",
          "pattern": "^[0-9]{4}$",
          "description": "BT-30-1 / BT-47-1, the ISO 6523 ICD of `registrationId`. German\nregister numbers have none; a French SIREN is 0002.\n"
        },
        "legalInformation": {
          "type": "string",
          "maxLength": 1000,
          "description": "BT-33, the seller's only — on the buyer it is a 400. What company\nlaw wants on business letters beyond the name and the register\nnumber: the seat, the register court, the managing directors\n(§ 35a GmbHG, § 80 AktG, § 37a HGB). The ZUGFeRD page prints it\nwith the register number.\n"
        }
      }
    },
    "Payment": {
      "type": "object",
      "description": "BG-16, and the group its code calls for: the payee account (BG-17)\nfor a transfer, `card` (BG-18) for a card payment, `directDebit`\n(BG-19) for a SEPA direct debit. Which group may stand beside which\ncode is the rule set's verdict (BR-DE-23 to BR-DE-25), returned as\nfindings — a payee IBAN beside a direct debit is a 422, not a 400.\n",
      "required": [
        "meansCode"
      ],
      "properties": {
        "meansCode": {
          "type": "string",
          "pattern": "^([0-9]{1,3}|ZZZ)$",
          "description": "BT-81, UNTDID 4461: 58 SEPA credit transfer, 30 credit transfer,\n59 SEPA direct debit, 48/54/55 card, 10 cash, ZZZ mutually defined.\n"
        },
        "meansText": {
          "type": "string",
          "description": "BT-82, the payment means in words."
        },
        "iban": {
          "type": "string",
          "description": "BT-84, the payee account."
        },
        "accountName": {
          "type": "string",
          "description": "BT-85, the payee account holder."
        },
        "bic": {
          "type": "string",
          "pattern": "^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$",
          "description": "BT-86, the payee's bank."
        },
        "reference": {
          "type": "string",
          "description": "BT-83, what the payer should quote."
        },
        "card": {
          "$ref": "#/$defs/Card"
        },
        "directDebit": {
          "$ref": "#/$defs/DirectDebit"
        }
      }
    },
    "Period": {
      "type": "object",
      "description": "A period, the invoice's (BG-14) or a line's (BG-26). Either end may\nstand alone; the rule set wants one of them (BR-CO-19, BR-CO-20) and\nthe end not before the start (BR-29, BR-30). An empty period is not\nwritten.\n",
      "properties": {
        "startDate": {
          "type": "string",
          "format": "date",
          "description": "BT-73 / BT-134."
        },
        "endDate": {
          "type": "string",
          "format": "date",
          "description": "BT-74 / BT-135."
        }
      }
    },
    "PrecedingInvoice": {
      "type": "object",
      "required": [
        "number"
      ],
      "properties": {
        "number": {
          "type": "string",
          "description": "BT-25."
        },
        "issueDate": {
          "type": "string",
          "format": "date",
          "description": "BT-26, needed when the number alone is not unique."
        }
      }
    }
  }
}