{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/beel-es/json-schema/beel-es-recurring-invoice-response-schema.json",
  "title": "RecurringInvoiceResponse",
  "x-generated": "2026-10-30",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/beel-es-openapi.json#/components/schemas/RecurringInvoiceResponse",
  "type": "object",
  "required": [
    "custom_fields"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "frequency": {
      "type": "string",
      "enum": [
        "MONTHLY",
        "QUARTERLY",
        "YEARLY"
      ],
      "description": "Billing cadence of the template: `MONTHLY` every month, `QUARTERLY` every 3 months, `YEARLY` every 12 months. The day it falls on is\n`day_of_month`, the same anchor for all three. Set it when you create the template;\na template created without it is `MONTHLY`.\n\nThe cadence governs the step from the first invoice onwards, not where that first one\nlands: the first occurrence is the first `day_of_month` on or after `start_date`, found\none month at a time. A yearly template starting 15 February with `day_of_month` 10 first\ninvoices on 10 March, then every 10 March after that.\n"
    },
    "day_of_month": {
      "type": "integer",
      "description": "Day of the month the invoices are issued, as it was requested: this is the anchor of\nthe schedule, not the day the last invoice happened to land on. A month that does not\nhave that day falls back to its last day, so `next_generation` can show a different\nday than this one — a template on `31` generates on 28 February (29 in a leap year)\nand on 30 April.\n\nThe adjustment never sticks and the schedule does not drift: every generation is\nrecalculated from this value, never from the date it was adjusted to\n(31 Jan → 28 Feb → 31 Mar).\n"
    },
    "start_date": {
      "type": "string",
      "format": "date"
    },
    "end_date": {
      "type": [
        "string",
        "null"
      ],
      "format": "date"
    },
    "next_generation": {
      "type": [
        "string",
        "null"
      ],
      "format": "date",
      "description": "Date the next invoice is generated — the one this template is actually going to honour.\n`null`, always present and never omitted, when there is none.\n\nThere is none in two cases, and only in those two:\n\n- the template is `COMPLETED`: the date left on it is the one that ran past its end and\n  triggered the closure, not a generation still to come;\n- the template is `PAUSED` and its date is strictly in the past: resuming does not go\n  back to it — it reschedules from today onwards, so that date will never be invoiced.\n\nAn `ACTIVE` template always carries its date, **including a date already in the past**:\nthat is the occurrence about to be generated, and it is your only notice that\nan invoice is on its way.\n\nA `PAUSED` template whose date is still ahead — today counts as ahead — carries it too:\nit is exactly the date resuming would keep.\n\nThe stored schedule is never rewritten by any of this. `next_generation` is what gets\npublished, not what gets kept: resuming a long-paused template still reschedules from\nits own anchor, as it always did.\n"
    },
    "draft_in_advance": {
      "type": "boolean",
      "description": "Whether this template prepares a draft for review before emitting. The review window is\nfixed at 5 days: `true` creates the draft 5 days ahead, `false` goes straight to the\nemission. Either way the invoice is emitted on the scheduled `day_of_month` — what\nchanges is only whether there is a draft to look at first. Generating manually\n(`POST .../generate`) a period whose scheduled date is today or earlier emits the\ninvoice on the spot: its review window has already passed.\n"
    },
    "status": {
      "allOf": [
        {
          "$ref": "#/$defs/RecurringInvoiceStatus"
        }
      ]
    },
    "is_failing": {
      "type": "boolean",
      "description": "Whether this template is failing right now — from the FIRST failed unattended run, not\nthe third. The warning email only goes out on every 3rd consecutive retryable failure,\nso `next_generation` not moving used to be the only clue before that; this field\nsurfaces the same signal from the very first one.\n\n`true` when either an unattended run has failed at least once and the retry streak has\nnot been cleared by a successful generation yet (even while `status` is still `ACTIVE`,\nbefore any email fires), or `status` is `PAUSED` with `pause.reason =\nGENERATION_FAILURE`. Derived on every read from data already stored — it is not a new\ncolumn and nothing else changes because of it.\n"
    },
    "pause": {
      "$ref": "#/$defs/RecurringInvoicePause"
    },
    "completion": {
      "$ref": "#/$defs/RecurringInvoiceCompletion"
    },
    "series_id": {
      "type": "string",
      "format": "uuid"
    },
    "series_code": {
      "type": "string"
    },
    "invoice_type": {
      "$ref": "#/$defs/RecurringInvoiceType"
    },
    "customer_id": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "recipient_fiscal_name": {
      "type": [
        "string",
        "null"
      ]
    },
    "recipient_nif": {
      "type": [
        "string",
        "null"
      ],
      "description": "Spanish Tax ID of the recipient. Mutually exclusive with `recipient_alternative_id`:\na recipient is identified by exactly one of the two, never both, and `null` when the\nother one carries the identifier (or when there is no recipient identified at all).\n"
    },
    "recipient_alternative_id": {
      "allOf": [
        {
          "$ref": "#/$defs/AlternativeIdentifier"
        },
        {
          "description": "Alternative identifier of the recipient (NIF-IVA, passport, etc.), same shape as\nthe customer's own `alternative_id`. Mutually exclusive with `recipient_nif`:\n`null` when the recipient carries a Spanish `recipient_nif` instead, or when there\nis no recipient identified at all.\n"
        }
      ]
    },
    "lines": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/InvoiceLineTemplateResponse"
      }
    },
    "amount": {
      "type": [
        "number",
        "null"
      ],
      "description": "What the customer will be asked to transfer on the next invoice this template\ngenerates: taxable base + VAT + equivalence surcharge − IRPF withholding +\ndisbursements (`suplidos`). It is NOT the taxable base and NOT the total with VAT:\nthe withholding is already subtracted.\n\nThe same number the next occurrence publishes as `total_to_pay`, to the cent: both\ncome from the template's own lines through the same line pipeline the real generation\nuses. It is computed on the fly and stored nowhere, so it always reflects the lines\nthe template carries right now — and it is not sortable or filterable for that reason.\n\n`null` when the template's lines cannot be priced (no lines, or lines the engine\nrejects). The rest of the template is still returned.\n"
    },
    "payment_method": {
      "type": [
        "string",
        "null"
      ]
    },
    "payment_iban": {
      "type": [
        "string",
        "null"
      ],
      "description": "Full IBAN of the template's own payment method, mirrored from what was sent when it\nwas set. `null` when the template has no payment method.\n"
    },
    "payment_swift": {
      "type": [
        "string",
        "null"
      ],
      "description": "SWIFT/BIC code of the template's own payment method. `null` when the template has no\npayment method, or when it has one without a SWIFT code.\n"
    },
    "payment_term_days": {
      "type": [
        "integer",
        "null"
      ],
      "description": "Payment term, in days, of the template's own payment method. `null` when the template\nhas no payment method, or when it has one without a declared term.\n\nEach generated invoice is due on its issue date plus this term. When it is `null`, the\ncompany's default `payment_term_days` (tax configuration) applies, or 30 days if the\ncompany has none.\n"
    },
    "notes": {
      "type": [
        "string",
        "null"
      ]
    },
    "custom_fields": {
      "type": "array",
      "maxItems": 20,
      "description": "The company's custom fields saved on this template, each with the label and value it was\nsaved with; an empty array when it carries none.\n\nEvery invoice the template generates copies them. The generated invoice saves each field\nwith the label it has at that moment; a field archived after the template was saved stays\nlisted here, but the invoices generated from then on are created without it and the\ntemplate keeps generating: it is not paused for that reason. They are informational: they\nare not part of the VeriFactu record sent to the AEAT and do not enter its hash.\n",
      "items": {
        "$ref": "#/$defs/InvoiceCustomField"
      }
    },
    "send_automatically": {
      "type": "boolean"
    },
    "email_configuration": {
      "$ref": "#/$defs/RecurringEmailConfigResponse"
    },
    "generated_invoices": {
      "type": "integer"
    },
    "max_invoices": {
      "type": [
        "integer",
        "null"
      ],
      "description": "Total number of invoices agreed for this template, or absent when the recurrence is not\ncapped by number. It is the TOTAL agreed, not what is left: \"remaining\" is\n`max_invoices - generated_invoices`, a derived reading with no field of its own — two\ncounters of the same fact drift, and the day they do nobody knows which one is true.\n\nWhat counts against it are invoices GENERATED, not calendar turns: a skip does not spend\ncap because it produces no invoice, and a `generate now` does because it produces a real\nfiscal invoice. When the last one is generated the template is closed in the act, with\n`completion.reason = MAX_INVOICES_REACHED`.\n"
    },
    "last_generated_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "last_generated_scheduled_date": {
      "type": [
        "string",
        "null"
      ],
      "format": "date",
      "description": "Calendar date of the latest period this template has already invoiced: the highest\n`scheduled_date` in its generation history. `null` when it has never generated an invoice.\n\nIt is NOT the date of `last_generated_at`. That field is the instant the most recent\ninvoice was created; this one is the calendar slot that invoice (or an earlier one) was\nissued for. They diverge on purpose: a `generate now` creates today an invoice for a future\nslot, and a re-anchored schedule can generate a slot out of order, so the latest invoice\ncreated is not necessarily the one with the latest slot.\n\nSkipping a period does not move it: a skip produces no invoice, so it consumes no slot.\n\nDeleting a generated invoice does not move it either, with one exception: deleting the\ndraft of the latest generation releases that slot (the period becomes available to generate\nagain, and `generated_invoices` goes down by one), so this date moves back to the previous\ngenerated slot, or to `null` if there is none.\n"
    },
    "source_invoice_id": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    }
  },
  "$defs": {
    "AlternativeIdentifier": {
      "type": [
        "object",
        "null"
      ],
      "required": [
        "type",
        "number"
      ],
      "description": "Alternative identifier for customers without Spanish Tax ID.\n\n### VeriFactu rules (checked when you send it, `422` on violation)\n- `country_code` is required, except for `PASSPORT` (03) and `NOT_REGISTERED` (07), the two\n  types AEAT accepts with `ES`: omitted, `ES` applies. Missing for any other type, the\n  identifier is rejected with `ALTERNATIVE_ID_COUNTRY_REQUIRED`, and `error.details` names\n  the field where it was sent: `alternative_id.country_code` on a customer,\n  `recipient.alternative_id.country_code` on an invoice recipient. Same code in both.\n- If `country_code = ES`, then `type` **must** be `PASSPORT` (03) or `NOT_REGISTERED` (07)\n  (`ALTERNATIVE_ID_SPAIN_INVALID_TYPE`).\n- If `type = NOT_REGISTERED` (07), then `country_code` **must** be `ES`\n  (`ALTERNATIVE_ID_REQUIRES_SPAIN`), and `number` **must** be a Spanish DNI or NIE: a\n  Spanish company is always registered (`RECIPIENT_UNREGISTERED_ID_MUST_BE_DNI_OR_NIE`).\n  That DNI or NIE must not be one the AEAT census identifies: if it is, the identifier is\n  rejected with `ALTERNATIVE_ID_ACTUALLY_IN_CENSUS` and has to be sent as `nif`. A customer\n  is checked when it is saved; an invoice recipient, when the invoice is issued with\n  VeriFactu. If the census does not answer, the identifier is not rejected.\n- If `type = NIF_IVA` (02), `country_code` **must** be an EU member state other than Spain\n  (`ALTERNATIVE_ID_VAT_REQUIRES_EU_COUNTRY`), and `number` **must** have that country's\n  EU VAT number structure as AEAT defines it: the country prefix (`EL` for Greece) followed\n  by the national number, e.g. `FR40303265045`, `DE123456789`, `EL094014201`\n  (`ALTERNATIVE_ID_VAT_INVALID_FORMAT`). Lowercase letters are accepted and stored in\n  uppercase. A customer from outside the EU is identified with another type, such as\n  `OTHER_DOCUMENT` or `COUNTRY_ID`.\n\nA `number` that is blank once trimmed is rejected with `ALTERNATIVE_ID_INVALID`.\n\nWell-formed is not the same as registered: an EU VAT number that is not in the VIES\ncensus is still rejected by VeriFactu after the invoice is issued.\n\nAn identifier returned in a response is the one stored. A customer saved before a rule\nexisted keeps its identifier and can still be read; issuing an invoice to it with an\nidentifier that breaks these rules is rejected with the same code, before a number is used.\n\n### Matrix of allowed combinations\n| `type`                 | `country_code = ES` | `country_code ≠ ES` |\n|------------------------|:-------------------:|:-------------------:|\n| `NIF_IVA` (02)         | ✗                   | EU member states only |\n| `PASSPORT` (03)        | ✓                   | ✓                   |\n| `COUNTRY_ID` (04)      | ✗                   | ✓                   |\n| `RESIDENCE_CERTIFICATE` (05) | ✗             | ✓                   |\n| `OTHER_DOCUMENT` (06)  | ✗                   | ✓                   |\n| `NOT_REGISTERED` (07)  | ✓                   | ✗                   |\n",
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "NIF_IVA",
            "PASSPORT",
            "COUNTRY_ID",
            "RESIDENCE_CERTIFICATE",
            "OTHER_DOCUMENT",
            "NOT_REGISTERED",
            "02",
            "03",
            "04",
            "05",
            "06",
            "07"
          ],
          "description": "Identifier type. Use descriptive names:\n- **NIF_IVA**: EU VAT number (intra-community) — *only for an EU member state other than Spain, with that country's VAT number structure*\n- **PASSPORT**: Passport — *allowed for any country*\n- **COUNTRY_ID**: Country of residence ID — *not allowed when `country_code = ES`*\n- **RESIDENCE_CERTIFICATE**: Residence certificate — *not allowed when `country_code = ES`*\n- **OTHER_DOCUMENT**: Other supporting document — *not allowed when `country_code = ES`*\n- **NOT_REGISTERED**: Not registered in AEAT — *requires `country_code = ES`*\n\n**⚠️ DEPRECATED numeric codes** (will be removed in v2):\n02, 03, 04, 05, 06, 07 — use the descriptive names above instead.\n"
        },
        "number": {
          "type": "string",
          "minLength": 1,
          "maxLength": 20,
          "description": "Identifier number. For `NIF_IVA`, the full EU VAT number with its country prefix\n(e.g. `FR40303265045`); see the VeriFactu rules on the parent schema.\n"
        },
        "country_code": {
          "type": "string",
          "pattern": "^[A-Z]{2}$",
          "minLength": 2,
          "maxLength": 2,
          "description": "ISO 3166-1 alpha-2 code of the country that issued the document. Required except for\n`PASSPORT` and `NOT_REGISTERED`, where omitting it means `ES`. Constrains the allowed\n`type` values; see the VeriFactu rules on the parent schema.\n"
        }
      }
    },
    "CustomFieldKey": {
      "type": "string",
      "minLength": 1,
      "maxLength": 64,
      "pattern": "^[a-z0-9_]{1,64}$",
      "description": "Identifier of the custom field within the company, chosen when the field is created: lowercase letters, digits and `_`, up to 64 characters. It never changes. BeeL. gives it no meaning of its own."
    },
    "ExemptionReason": {
      "type": "string",
      "enum": [
        "EXENTA_ART_20",
        "EXENTA_ART_21",
        "EXENTA_ART_22",
        "EXENTA_ART_24",
        "EXENTA_ART_25",
        "EXENTA_ART_26",
        "EXENTA_ART_140",
        "NO_SUJETA_ART_7_9",
        "NO_SUJETA_LOCALIZACION",
        "ISP_ART_84_2_A",
        "ISP_ART_84_2_B",
        "ISP_ART_84_2_C",
        "ISP_ART_84_2_D",
        "ISP_ART_84_2_E",
        "ISP_ART_84_2_F",
        "ISP_ART_84_2_G",
        "REGIMEN_ART_129",
        "REGIMEN_ART_135",
        "REGIMEN_ART_141",
        "REGIMEN_ART_154",
        "REGIMEN_ART_163_DECIES",
        "OTRO"
      ],
      "description": "Tax exemption reason code per the Spanish VAT Law (Ley 37/1992, LIVA), with the\nVeriFactu code each one is reported as.\n\n- `EXENTA_ART_20`: exempt, art. 20 (domestic operations such as medical, educational,\n  cultural and financial services, or housing rentals). E1.\n- `EXENTA_ART_21`: exempt, art. 21 (exports of goods). E2.\n- `EXENTA_ART_22`: exempt, art. 22 (operations treated as exports). E3.\n- `EXENTA_ART_24`: exempt, art. 24 (free zones, warehouses and customs regimes). E4.\n- `EXENTA_ART_25`: exempt, art. 25 (intra-community supplies of goods). E5.\n- `EXENTA_ART_26`: exempt, art. 26 (intra-community acquisitions of goods). It exempts the\n  buyer's acquisition, not a supply the seller invoices, so an invoice line that carries it\n  is rejected with `EXEMPTION_NOT_FOR_ISSUED_INVOICE`; a supply to another Member State is\n  `EXENTA_ART_25`.\n- `NO_SUJETA_ART_7_9`: not subject under art. 7 (such as the transfer of a business as\n  a going concern, art. 7.1º). N1.\n- `NO_SUJETA_LOCALIZACION`: not subject by the place-of-supply rules (intra-community\n  or non-EU services, arts. 69 and 70). N2.\n- `ISP_ART_84_2_A` … `ISP_ART_84_2_F`: reverse charge (the invoice states «inversión del\n  sujeto pasivo»), art. 84.Uno.2.º letters a) (supplier not established in Spain), b) (unwrought\n  or semi-finished gold), c) (scrap, waste and recovery materials, plastic, paper, cardboard, glass and textile waste, and semi-finished non-ferrous metal products), d) (greenhouse gas emission\n  allowances), e) (certain real estate supplies: in insolvency proceedings, with the exemption\n  waived, or enforcing a security) and f) (construction or renovation works). S2.\n- `ISP_ART_84_2_G`: reverse charge of letter g) (silver, platinum, palladium, mobile phones,\n  consoles, laptops and tablets). The law requires these supplies to be invoiced in a special\n  series, so an invoice line that carries it is rejected with\n  `REVERSE_CHARGE_CASE_NOT_SUPPORTED`.\n- `EXENTA_ART_140`: investment gold exemption, art. 140 bis (usually with `regime_key`\n  `04`). E6.\n- `REGIMEN_ART_129` (agriculture,\n  livestock and fishing, arts. 124 to 134 bis), `REGIMEN_ART_135` (second-hand goods,\n  art and antiques), `REGIMEN_ART_141` (travel agencies), `REGIMEN_ART_154` (equivalence\n  surcharge) and `REGIMEN_ART_163_DECIES` (cash basis, arts. 163 decies to 163\n  sexiesdecies): operations of special regimes, which VeriFactu identifies by the regime\n  key rather than by an exemption code. An\n  invoice line that carries one is rejected with `EXEMPTION_REGIME_NOT_SUPPORTED_IN_VERIFACTU`;\n  declare the regime with `regime_key` instead.\n- `OTRO`: any other provision. Requires the text in `exemption_reason_text`. E6.\n"
    },
    "InvoiceCustomField": {
      "type": "object",
      "description": "A custom field as it was saved on an invoice or on a recurring invoice template: a copy of the field label and of the value at that moment. Renaming or archiving the field or its options later does not change it.",
      "required": [
        "key",
        "label",
        "value"
      ],
      "properties": {
        "key": {
          "$ref": "#/$defs/CustomFieldKey"
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "description": "Label of the field when the invoice was saved."
        },
        "value": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "description": "Text stored on the invoice. It is the text the `custom_fields` filter of the invoice list compares."
        }
      }
    },
    "InvoiceLineTemplateResponse": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "order": {
          "type": "integer"
        },
        "description": {
          "type": "string"
        },
        "quantity": {
          "type": "number"
        },
        "unit": {
          "type": [
            "string",
            "null"
          ]
        },
        "unit_price": {
          "type": "number",
          "description": "Unit price of the template line. In both total-declared modes\n(`pricing_mode` other than `UNIT_PRICE`) this value is **derived and\ninformational** (`total / quantity`, 4 decimals): re-multiplying it does not\nreproduce the declared total on large quantities.\n"
        },
        "pricing_mode": {
          "$ref": "#/$defs/PricingMode"
        },
        "total_excluding_tax": {
          "type": "number",
          "description": "Declared line total excluding taxes. Only present on lines with\n`pricing_mode = TOTAL_EXCLUDING_TAX`. It never includes taxes nor subtracts\nIRPF withholding.\n"
        },
        "total_including_tax": {
          "type": "number",
          "description": "Declared line total including taxes (taxable base + VAT + equivalence\nsurcharge; IRPF withholding is never subtracted). Only present on lines with\n`pricing_mode = TOTAL_INCLUDING_TAX`. Every invoice this template generates\nreproduces it exactly.\n"
        },
        "discount_percentage": {
          "type": [
            "number",
            "null"
          ]
        },
        "tax_type": {
          "type": "string"
        },
        "vat_rate": {
          "type": "number"
        },
        "regime_key": {
          "type": "string"
        },
        "equivalence_surcharge_rate": {
          "type": [
            "number",
            "null"
          ]
        },
        "irpf_rate": {
          "type": [
            "number",
            "null"
          ]
        },
        "exemption_reason": {
          "$ref": "#/$defs/ExemptionReason",
          "nullable": true
        },
        "exemption_reason_text": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 500,
          "description": "Custom exemption text. Only used when exemption_reason is OTRO."
        }
      }
    },
    "PricingMode": {
      "type": "string",
      "description": "How the line amount was entered.\n\n- `UNIT_PRICE`: classic mode — the amount is derived from `unit_price`\n  (`quantity × unit_price × (1 − discount / 100)`).\n- `TOTAL_EXCLUDING_TAX`: total-declared mode — `total_excluding_tax` is the exact\n  taxable base and `unit_price` is derived and informational\n  (`total / quantity`, 4 decimals).\n- `TOTAL_INCLUDING_TAX`: tax-inclusive total-declared mode —\n  `total_including_tax` is what the customer paid (taxable base + VAT +\n  equivalence surcharge) and the engine works the breakdown backwards so the\n  rounded amounts add up to the declared total exactly.\n\nIn both total-declared modes re-multiplying the derived `unit_price` does NOT\nreproduce the declared total on large quantities (1.00 € ÷ 300 units → 0.0033 ×\n300 = 0.99), which is precisely why the declared total is the source of truth.\n",
      "enum": [
        "UNIT_PRICE",
        "TOTAL_EXCLUDING_TAX",
        "TOTAL_INCLUDING_TAX"
      ]
    },
    "RecurringEmailConfigResponse": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "recipients": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "cc": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "subject": {
          "type": [
            "string",
            "null"
          ]
        },
        "message": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "RecurringInvoiceCompletion": {
      "type": [
        "object",
        "null"
      ],
      "description": "Why this schedule ended. Present while `status` is `COMPLETED`; absent otherwise, and also\nabsent for schedules completed before this was recorded — that cause is not known and is not\ninvented.\n\n`COMPLETED` covers facts that are not interchangeable: the owner ended it, the calendar ran\nout, or the agreed number of invoices did. It stays a **single** terminal status and `status` keeps its three values: no business rule\nbranches on the cause, and a new status value would break every exhaustive `switch`. New causes\nland in `reason`, so treat it as an open set.\n",
      "properties": {
        "reason": {
          "type": "string",
          "enum": [
            "USER",
            "END_DATE_REACHED",
            "MAX_INVOICES_REACHED"
          ],
          "description": "`USER` — someone completed it (`PUT .../status` to `COMPLETED`).\n`END_DATE_REACHED` — the next occurrence landed past `end_date`, so there was nothing left\nto generate. This includes automatic generation and the common close of generating, skipping\nand resuming.\n`MAX_INVOICES_REACHED` — the `max_invoices` cap ran out: the last agreed invoice was\ngenerated (or the cap was moved down to the number already generated). When a template\nexhausts its cap and its `end_date` on the very same turn this is the cause reported: the\ncap is the fact that just happened, the date is the calendar consequence that follows.\n"
        },
        "at": {
          "type": "string",
          "format": "date-time",
          "description": "Instant the schedule was closed."
        }
      }
    },
    "RecurringInvoicePause": {
      "type": [
        "object",
        "null"
      ],
      "description": "Why this schedule is paused. Present while `status` is `PAUSED`; absent otherwise, and also\nabsent for schedules paused before this was recorded.\n\n`PAUSED` covers three facts that are not interchangeable: someone paused it, a plan downgrade\npaused it, or an unattended generation failed with something waiting will not fix. A transient\nfailure (network, timeout, tax authority downtime) does NOT pause the schedule — the next run\nretries it.\n",
      "properties": {
        "reason": {
          "$ref": "#/$defs/RecurringInvoicePauseReason"
        },
        "since": {
          "type": "string",
          "format": "date-time"
        },
        "blocker": {
          "type": "string",
          "description": "What blocked the emission, using the same codes the emission error returns (the `blockers[]`\nof a 422 `EMISSION_NOT_READY`). Only for `GENERATION_FAILURE`, and it may be absent when the\npermanent failure was not a readiness one. Resuming is rejected while this blocker is still\nin effect.\n"
        }
      }
    },
    "RecurringInvoicePauseReason": {
      "type": "string",
      "description": "Who stopped the schedule. `USER` a person did, from the API or the dashboard; `DOWNGRADE` the\naccount lost the recurring-invoices feature; `GENERATION_FAILURE` an unattended run failed with\nsomething waiting will not fix — that one carries a `blocker`.\n",
      "enum": [
        "USER",
        "DOWNGRADE",
        "GENERATION_FAILURE"
      ]
    },
    "RecurringInvoiceStatus": {
      "type": "string",
      "description": "Lifecycle state of a recurring invoice schedule.\n\n- `ACTIVE`: invoices are generated on schedule.\n- `PAUSED`: automatic generation is stopped and the schedule is kept; `pause` says who\n  stopped it. It can be resumed.\n- `COMPLETED`: the schedule has ended for good and generates nothing more; `completion`\n  says why. Terminal: it cannot be resumed or paused.\n",
      "enum": [
        "ACTIVE",
        "PAUSED",
        "COMPLETED"
      ]
    },
    "RecurringInvoiceType": {
      "type": "string",
      "enum": [
        "STANDARD",
        "SIMPLIFIED"
      ],
      "description": "Type of the invoices a recurring template generates: `STANDARD` for an identified recipient,\n`SIMPLIFIED` for a recipient that is not identified.\n"
    }
  }
}