{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://temlavo.com/schemas/invoice.v1.json",
  "title": "Temlavo invoice.v1 data schema",
  "description": "Public structural and wire schema for the invoice object under document.data. The executable API contract remains authoritative for runtime refinements.",
  "type": "object",
  "properties": {
    "vendor": { "$ref": "#/$defs/InvoiceParty" },
    "customer": { "$ref": "#/$defs/InvoiceParty" },
    "invoice": { "$ref": "#/$defs/InvoiceHeader" },
    "line_items": {
      "maxItems": 500,
      "type": "array",
      "items": { "$ref": "#/$defs/LineItem" }
    },
    "line_items_status": { "$ref": "#/$defs/LineItemsStatus" },
    "totals": { "$ref": "#/$defs/InvoiceTotals" },
    "taxes": { "type": "array", "items": { "$ref": "#/$defs/TaxComponent" } }
  },
  "required": [
    "vendor",
    "customer",
    "invoice",
    "line_items",
    "line_items_status",
    "totals",
    "taxes"
  ],
  "additionalProperties": false,
  "if": {
    "properties": { "line_items_status": { "const": "unavailable" } },
    "required": ["line_items_status"]
  },
  "then": {
    "properties": { "line_items": { "type": "array", "maxItems": 0 } }
  },
  "$defs": {
    "InvoiceParty": {
      "type": "object",
      "properties": {
        "name": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "tax_id": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "address": {
          "anyOf": [{ "$ref": "#/$defs/Address" }, { "type": "null" }]
        }
      },
      "required": ["name", "tax_id", "address"],
      "additionalProperties": false
    },
    "Address": {
      "type": "object",
      "properties": {
        "line1": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "line2": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "city": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "region": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "postal_code": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "country_code": {
          "anyOf": [{ "$ref": "#/$defs/CountryCode" }, { "type": "null" }]
        }
      },
      "required": [
        "line1",
        "line2",
        "city",
        "region",
        "postal_code",
        "country_code"
      ],
      "additionalProperties": false
    },
    "CountryCode": { "type": "string", "pattern": "^[A-Z]{2}$" },
    "InvoiceHeader": {
      "type": "object",
      "properties": {
        "number": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "issue_date": {
          "anyOf": [{ "$ref": "#/$defs/InvoiceDate" }, { "type": "null" }]
        },
        "due_date": {
          "anyOf": [{ "$ref": "#/$defs/InvoiceDate" }, { "type": "null" }]
        },
        "purchase_order_number": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "currency": {
          "anyOf": [{ "$ref": "#/$defs/CurrencyCode" }, { "type": "null" }]
        },
        "payment_terms": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        }
      },
      "required": [
        "number",
        "issue_date",
        "due_date",
        "purchase_order_number",
        "currency",
        "payment_terms"
      ],
      "additionalProperties": false
    },
    "InvoiceDate": {
      "type": "string",
      "format": "date",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
    },
    "CurrencyCode": {
      "type": "string",
      "enum": [
        "ADP",
        "AED",
        "AFA",
        "AFN",
        "ALK",
        "ALL",
        "AMD",
        "ANG",
        "AOA",
        "AOK",
        "AON",
        "AOR",
        "ARA",
        "ARP",
        "ARS",
        "ARY",
        "ATS",
        "AUD",
        "AWG",
        "AYM",
        "AZM",
        "AZN",
        "BAD",
        "BAM",
        "BBD",
        "BDT",
        "BEC",
        "BEF",
        "BEL",
        "BGJ",
        "BGK",
        "BGL",
        "BGN",
        "BHD",
        "BIF",
        "BMD",
        "BND",
        "BOB",
        "BOP",
        "BOV",
        "BRB",
        "BRC",
        "BRE",
        "BRL",
        "BRN",
        "BRR",
        "BSD",
        "BTN",
        "BUK",
        "BWP",
        "BYB",
        "BYN",
        "BYR",
        "BZD",
        "CAD",
        "CDF",
        "CHC",
        "CHE",
        "CHF",
        "CHW",
        "CLF",
        "CLP",
        "CNY",
        "COP",
        "COU",
        "CRC",
        "CSD",
        "CSJ",
        "CSK",
        "CUC",
        "CUP",
        "CVE",
        "CYP",
        "CZK",
        "DDM",
        "DEM",
        "DJF",
        "DKK",
        "DOP",
        "DZD",
        "ECS",
        "ECV",
        "EEK",
        "EGP",
        "ERN",
        "ESA",
        "ESB",
        "ESP",
        "ETB",
        "EUR",
        "FIM",
        "FJD",
        "FKP",
        "FRF",
        "GBP",
        "GEK",
        "GEL",
        "GHC",
        "GHP",
        "GHS",
        "GIP",
        "GMD",
        "GNE",
        "GNF",
        "GNS",
        "GQE",
        "GRD",
        "GTQ",
        "GWE",
        "GWP",
        "GYD",
        "HKD",
        "HNL",
        "HRD",
        "HRK",
        "HTG",
        "HUF",
        "IDR",
        "IEP",
        "ILP",
        "ILR",
        "ILS",
        "INR",
        "IQD",
        "IRR",
        "ISJ",
        "ISK",
        "ITL",
        "JMD",
        "JOD",
        "JPY",
        "KES",
        "KGS",
        "KHR",
        "KMF",
        "KPW",
        "KRW",
        "KWD",
        "KYD",
        "KZT",
        "LAJ",
        "LAK",
        "LBP",
        "LKR",
        "LRD",
        "LSL",
        "LSM",
        "LTL",
        "LTT",
        "LUC",
        "LUF",
        "LUL",
        "LVL",
        "LVR",
        "LYD",
        "MAD",
        "MDL",
        "MGA",
        "MGF",
        "MKD",
        "MLF",
        "MMK",
        "MNT",
        "MOP",
        "MRO",
        "MRU",
        "MTL",
        "MTP",
        "MUR",
        "MVQ",
        "MVR",
        "MWK",
        "MXN",
        "MXP",
        "MXV",
        "MYR",
        "MZE",
        "MZM",
        "MZN",
        "NAD",
        "NGN",
        "NIC",
        "NIO",
        "NLG",
        "NOK",
        "NPR",
        "NZD",
        "OMR",
        "PAB",
        "PEH",
        "PEI",
        "PEN",
        "PES",
        "PGK",
        "PHP",
        "PKR",
        "PLN",
        "PLZ",
        "PTE",
        "PYG",
        "QAR",
        "RHD",
        "ROK",
        "ROL",
        "RON",
        "RSD",
        "RUB",
        "RUR",
        "RWF",
        "SAR",
        "SBD",
        "SCR",
        "SDD",
        "SDG",
        "SDP",
        "SEK",
        "SGD",
        "SHP",
        "SIT",
        "SKK",
        "SLE",
        "SLL",
        "SOS",
        "SRD",
        "SRG",
        "SSP",
        "STD",
        "STN",
        "SUR",
        "SVC",
        "SYP",
        "SZL",
        "THB",
        "TJR",
        "TJS",
        "TMM",
        "TMT",
        "TND",
        "TOP",
        "TPE",
        "TRL",
        "TRY",
        "TTD",
        "TWD",
        "TZS",
        "UAH",
        "UAK",
        "UGS",
        "UGW",
        "UGX",
        "USD",
        "USN",
        "USS",
        "UYI",
        "UYN",
        "UYP",
        "UYU",
        "UYW",
        "UZS",
        "VEB",
        "VED",
        "VEF",
        "VES",
        "VNC",
        "VND",
        "VUV",
        "WST",
        "XAD",
        "XAF",
        "XAG",
        "XAU",
        "XBA",
        "XBB",
        "XBC",
        "XBD",
        "XCD",
        "XCG",
        "XDR",
        "XEU",
        "XFO",
        "XFU",
        "XOF",
        "XPD",
        "XPF",
        "XPT",
        "XRE",
        "XSU",
        "XTS",
        "XUA",
        "XXX",
        "YDD",
        "YER",
        "YUD",
        "YUM",
        "YUN",
        "ZAL",
        "ZAR",
        "ZMK",
        "ZMW",
        "ZRN",
        "ZRZ",
        "ZWC",
        "ZWD",
        "ZWG",
        "ZWL",
        "ZWN",
        "ZWR"
      ]
    },
    "LineItem": {
      "type": "object",
      "properties": {
        "description": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "product_code": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "quantity": {
          "anyOf": [
            { "$ref": "#/$defs/SignedDecimalString" },
            { "type": "null" }
          ]
        },
        "unit_of_measure": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "unit_price": {
          "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }]
        },
        "discount": {
          "anyOf": [{ "$ref": "#/$defs/NonNegativeMoney" }, { "type": "null" }]
        },
        "tax": { "anyOf": [{ "$ref": "#/$defs/LineTax" }, { "type": "null" }] },
        "line_total": {
          "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }]
        }
      },
      "required": [
        "description",
        "product_code",
        "quantity",
        "unit_of_measure",
        "unit_price",
        "discount",
        "tax",
        "line_total"
      ],
      "additionalProperties": false
    },
    "SignedDecimalString": {
      "type": "string",
      "pattern": "^[+-]?\\d+(?:\\.\\d+)?$"
    },
    "Money": {
      "type": "object",
      "properties": {
        "amount": { "$ref": "#/$defs/SignedDecimalString" },
        "currency": { "$ref": "#/$defs/CurrencyCode" }
      },
      "required": ["amount", "currency"],
      "additionalProperties": false
    },
    "NonNegativeMoney": {
      "type": "object",
      "properties": {
        "amount": { "$ref": "#/$defs/NonNegativeDecimalString" },
        "currency": { "$ref": "#/$defs/CurrencyCode" }
      },
      "required": ["amount", "currency"],
      "additionalProperties": false
    },
    "NonNegativeDecimalString": {
      "type": "string",
      "pattern": "^\\+?\\d+(?:\\.\\d+)?$"
    },
    "LineTax": {
      "type": "object",
      "properties": {
        "label": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "rate": {
          "anyOf": [
            { "$ref": "#/$defs/NonNegativeDecimalString" },
            { "type": "null" }
          ]
        },
        "amount": { "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }] }
      },
      "required": ["label", "rate", "amount"],
      "additionalProperties": false
    },
    "LineItemsStatus": {
      "type": "string",
      "enum": ["complete", "partial", "unavailable"],
      "description": "AI assessment of line-item extraction. Complete is not independent proof that every source item was captured."
    },
    "InvoiceTotals": {
      "type": "object",
      "properties": {
        "subtotal": {
          "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }]
        },
        "discount": {
          "anyOf": [{ "$ref": "#/$defs/NonNegativeMoney" }, { "type": "null" }]
        },
        "shipping": {
          "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }]
        },
        "other_charges": {
          "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }]
        },
        "tax": { "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }] },
        "total": { "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }] },
        "amount_due": {
          "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }]
        }
      },
      "required": [
        "subtotal",
        "discount",
        "shipping",
        "other_charges",
        "tax",
        "total",
        "amount_due"
      ],
      "additionalProperties": false
    },
    "TaxComponent": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": ["sales_tax", "vat", "gst", "other", "unknown"]
        },
        "label": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        },
        "rate": {
          "anyOf": [
            { "$ref": "#/$defs/NonNegativeDecimalString" },
            { "type": "null" }
          ]
        },
        "taxable_amount": {
          "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }]
        },
        "amount": {
          "anyOf": [{ "$ref": "#/$defs/Money" }, { "type": "null" }]
        },
        "jurisdiction": {
          "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }]
        }
      },
      "required": [
        "type",
        "label",
        "rate",
        "taxable_amount",
        "amount",
        "jurisdiction"
      ],
      "additionalProperties": false
    }
  }
}
