Skip to main content
Glama
beel-es

BeeL MCP server

Official
by beel-es

beel_patch_recurring_invoice

Patch only chosen fields on a recurring invoice template, keeping omitted values, lines, schedule, and payment data unchanged.

Instructions

Updates only the fields present in the body, leaving every other field of the recurring invoice template as it is.

  • Omitted vs null: an omitted field keeps its current value; a field sent as null is cleared, and only where the request schema documents the field as nullable.

  • lines: replaced as a whole, not patched line by line. The recipient survives the change, and an empty array is rejected.

  • payment_method: replaced as a whole together with payment_iban, payment_swift and payment_term_days — send them in the same request or they are dropped.

  • Schedule: frequency, day_of_month and start_date stay put unless you send them; sending a new value for any of the three moves the next generation — resending the ones already in effect changes nothing. Changing frequency recalculates it on the new grid and discards a pending skip. start_date is only editable while the template has not generated any invoice yet.

Endpoint: PATCH /v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}

⚠️ Read before calling:

  • Fiscal rules, domains simplified, taxes: beel_rules_list with domain, or resource beel://guardrails/.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bodyYes
company_idYesUnique identifier (UUID) of the company the operation acts on — its identifier, not its NIF. It is the only source of context: the account that owns it is derived from it, and the `BeeL-Active-Company` header plays no part. A company you do not reach answers `403`, and so does a company that does not exist, so the existence of a company in another account is never disclosed.
recurring_invoice_idYesUnique identifier (UUID) of the recurring invoice template, as returned when it is created or listed. A template of another company answers `404` with `RECURRING_NOT_FOUND`, exactly like one that does not exist.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed29 schema fields changedv0.9.0
    • addedInput schema / $defs / Email
      Added value: +{
      +  "description": "Email address (minimum valid email is 5 chars, e.g. a@b.co)",
      +  "format": "email",
      +  "maxLength": 255,
      +  "minLength": 5,
      +  "type": "string"
      +}
    • changedInput schema / $defs / ExemptionReason / description
      Previous value: -"Tax exemption reason code per Spanish VAT Law (Ley 37/1992 LIVA).\nVeriFactu mapping: EXENTA_ART_20→E1, EXENTA_ART_21→E2, EXENTA_ART_22→E3,\nEXENTA_ART_24→E4, EXENTA_ART_25→E5, rest→E6. ISP→S2, NO_SUJETA→N1/N2.\nWhen OTRO, a custom text must be provided in exemption_reason_text.\n"New value: +"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"
    • changedInput schema / $defs / ExemptionReason / enum
      Previous value: -[
      -  "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_E",
      -  "ISP_ART_84_2_F",
      -  "REGIMEN_ART_129",
      -  "REGIMEN_ART_135",
      -  "REGIMEN_ART_141",
      -  "REGIMEN_ART_154",
      -  "REGIMEN_ART_163_DECIES",
      -  "OTRO"
      -]New value: +[
      +  "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"
      +]
    • changedInput schema / $defs / PatchRecurringInvoiceRequest / properties / day_of_month / description
      Previous value: -"Day of the month the invoice is issued. Moves the next generation."New value: +"Day of the month the invoices are issued. Moves the next generation immediately, on an\n`ACTIVE` template and on a `PAUSED` one alike: the response to this very call already\ncarries the new `next_generation`. On a paused template the new day rules from the edit,\nnot from the day you resume — resuming keeps the date this call left, so editing the day\nof a paused schedule is never ignored for a round.\n\nA month that does not have that day falls back to its last day: a template on `31`\nissues on 28 February (29 in a leap year) and on 30 April. So `31` is how you ask for\nthe last day of the month it generates in — there is no separate flag for it, and the\naccepted range stays 1–31.\n\nThe adjustment does not stick and the schedule does not drift: every generation is\nrecalculated from the `day_of_month` you sent, never from the date it was adjusted\nto (31 Jan → 28 Feb → 31 Mar).\n"
    • addedInput schema / $defs / PatchRecurringInvoiceRequest / properties / draft_in_advance
      Added value: +{
      +  "description": "Whether the template prepares a draft for review before emitting. The window is fixed at\n5 days and both options emit on the scheduled day. Omitted, the current value is kept.\n",
      +  "type": "boolean"
      +}
    • changedInput schema / $defs / PatchRecurringInvoiceRequest / properties / frequency / description
      Previous value: -"Generation cadence. Only `MONTHLY` is supported today; the field exists in the\nrequest so an unsupported cadence is rejected instead of being silently ignored.\n"New value: +"Generation cadence: `MONTHLY` every month, `QUARTERLY` every 3 months, `YEARLY` every 12 months. Omitted, the current one is kept — it is\nnever reset to `MONTHLY`.\n\n**Changing it reschedules the template.** The next generation is recalculated on the new\ngrid — the `day_of_month` dates anchored at `start_date`, one every cadence — so it can\nland months later than the one you saw before the call. **If the template has already\nissued invoices, the landing respects that**: it is never a period that was already\nbilled, and never before today either — the first point of the new grid strictly after\nthe last invoiced one. It also **discards a pending skip**: the skipped period only\nexisted as a point of the old grid, and that grid is gone. Send the same cadence and\nnothing is rescheduled.\n"
    • changedInput schema / $defs / PatchRecurringInvoiceRequest / properties / frequency / enum
      Previous value: -[
      -  "MONTHLY"
      -]New value: +[
      +  "MONTHLY",
      +  "QUARTERLY",
      +  "YEARLY"
      +]
    • addedInput schema / $defs / PatchRecurringInvoiceRequest / properties / invoice_type
      Added value: +{
      +  "allOf": [
      +    {
      +      "$ref": "#/$defs/RecurringInvoiceType"
      +    }
      +  ],
      +  "description": "Type of the invoices the template generates. Omitted, the current type is kept; it cannot be cleared.\nA change is judged on the resulting template, with the rules of the new type: its series\nmust accept it (`SERIES_INCOMPATIBLE_DOC_TYPE` otherwise), a `SIMPLIFIED` template\ncannot keep an identified recipient (`SIMPLIFIED_INVOICE_FORBIDS_IDENTIFIED_RECIPIENT`)\nnor lines a simplified invoice does not admit. Send the new `series_id`, and\n`customer_id: null` when moving to `SIMPLIFIED`, in the same call.\n"
      +}
    • addedInput schema / $defs / PatchRecurringInvoiceRequest / properties / max_invoices
      Added value: +{
      +  "description": "Total number of invoices this template will generate before ending on its own, between\n2 and 600. Send `null` to stop capping the recurrence by number.\n\nEditing it MOVES THE GOAL, it does not add turns: above the invoices already generated the\ntemplate stays active; exactly equal ends it in this very call (with\n`completion.reason = MAX_INVOICES_REACHED`); below it the call is rejected — issued invoices\nare fiscal facts, and someone typing a lower number is asking to stop now, which is what\nending the recurrence is for.\n\nA recurrence ends in ONE way, and the conflict is judged on the RESULTING state, not on the\nbody: sending `max_invoices` to a template that already has an `end_date` is rejected with\n`RECURRING_END_MODE_CONFLICT` even though the body only mentions one of them. Switching mode\nis a single call that says both things — the new field with a value and the old one as\n`null`. Nothing is cleared silently.\n",
      +  "type": [
      +    "integer",
      +    "null"
      +  ]
      +}
    • addedInput schema / $defs / PatchRecurringInvoiceRequest / properties / name / minLength
      Added value: +1
    • addedInput schema / $defs / PatchRecurringInvoiceRequest / properties / name / pattern
      Added value: +"^\\S.*$"
    • changedInput schema / $defs / PatchRecurringInvoiceRequest / properties / payment_method / anyOf
      Previous value: -[
      -  {
      -    "allOf": [
      -      {
      -        "$ref": "#/$defs/PaymentMethod"
      -      }
      -    ],
      -    "description": "Payment method. Replaced as a whole together with `payment_iban`,\n`payment_swift` and `payment_term_days`: send them in the same request or they\nare dropped. Send `null` to state that no payment method applies.\n"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "allOf": [
      +      {
      +        "$ref": "#/$defs/PaymentMethod"
      +      }
      +    ],
      +    "description": "Payment method. Replaced as a whole together with `payment_iban`,\n`payment_swift` and `payment_term_days`: send them in the same request or they\nare dropped. Send `null` to state that no payment method applies.\n\n`payment_iban`, `payment_swift` and `payment_term_days` are detail of this\nmethod, not standalone fields: sending any of them without a `payment_method`\nthat is present, non-null and different from `NONE` is rejected with `422`\n(`PAYMENT_DETAILS_REQUIRE_METHOD`).\n"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / $defs / PatchRecurringInvoiceRequest / properties / preview_days / description
      Previous value: -"Days before emission date to create a draft for review. 0 means immediate emission."New value: +"**Deprecated.** Superseded by `draft_in_advance`. Any value greater than `0` means the\nsame as `draft_in_advance: true`, and `0` the same as `false`. When both are sent,\n`draft_in_advance` wins. It will be removed in a future version.\n"
    • changedInput schema / $defs / PatchRecurringInvoiceRequest / properties / start_date / description
      Previous value: -"First issue date. Only editable while the template has not generated any invoice yet.\nA past date is accepted and stored as sent, but it never anchors generation in the\npast: `next_generation` moves to the first upcoming `day_of_month`.\n"New value: +"First issue date. Only **changeable** while the template has not generated any invoice\nyet: once it has issued, a *different* date is rejected with a 422\n`RECURRING_START_DATE_NOT_EDITABLE`. Sending the value it already has is a no-op and\nsucceeds, so a read-modify-write cycle never has to strip the field out of the body.\n\nA past date is accepted and stored as sent, but it never anchors generation in the\npast: `next_generation` becomes the next date of the template's own calendar that is\nstill ahead — the grid of `day_of_month` dates anchored at `start_date`, one every\n`frequency` — which on a quarterly or yearly template can be months from now.\n"
    • removedInput schema / $defs / PatchRecurringInvoiceRequest / properties / verifactu_enabled
      Removed value: -{
      -  "type": "boolean"
      -}
    • changedInput schema / $defs / PaymentMethod / description
      Previous value: -"Payment method for invoices and recurring invoices.\nNONE means no payment information will be shown.\n"New value: +"Payment method shown on invoices and recurring invoices.\n\n- `NONE`: no payment information is shown.\n- `BANK_TRANSFER`: bank transfer to the IBAN of the payment details; the only method\n  that requires an IBAN.\n- `CARD`: card payment.\n- `CASH`: cash payment.\n- `CHECK`: payment by cheque.\n- `DIRECT_DEBIT`: direct debit from the customer's bank account.\n- `BIZUM`: payment through Bizum.\n- `OTHER`: any other method.\n"
    • addedInput schema / $defs / RecurringEmailConfigRequest / properties / cc / items / $ref
      Added value: +"#/$defs/Email"
    • removedInput schema / $defs / RecurringEmailConfigRequest / properties / cc / items / type
      Removed value: -"string"
    • addedInput schema / $defs / RecurringEmailConfigRequest / properties / recipients / items / $ref
      Added value: +"#/$defs/Email"
    • removedInput schema / $defs / RecurringEmailConfigRequest / properties / recipients / items / type
      Removed value: -"string"
    • addedInput schema / $defs / RecurringInvoiceType
      Added value: +{
      +  "description": "Type of the invoices a recurring template generates: `STANDARD` for an identified recipient,\n`SIMPLIFIED` for a recipient that is not identified.\n",
      +  "enum": [
      +    "STANDARD",
      +    "SIMPLIFIED"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / $defs / RecurringLineRequest / description
      Previous value: -"Recurring-invoice line. Unlike invoice lines (which nest tax data under a `main_tax` object),\nrecurring lines use flat tax fields: `vat_rate`, `tax_type`, `regime_key`,\n`equivalence_surcharge_rate` and `irpf_rate`. Do not send a `main_tax` object here.\n"New value: +"Recurring-invoice line. Unlike invoice lines (which nest tax data under a `main_tax` object),\nrecurring lines use flat tax fields: `vat_rate`, `tax_type`, `regime_key`,\n`equivalence_surcharge_rate` and `irpf_rate`. Do not send a `main_tax` object here.\n\n**Line amount**: send **exactly one** of `unit_price`, `total_excluding_tax` or\n`total_including_tax` — same contract as an invoice line. Sending none, or more than\none, is rejected with `LINE_UNIT_PRICE_XOR_DECLARED_TOTAL`; a declared total together\nwith an explicit `discount_percentage` is rejected with\n`LINE_DECLARED_TOTAL_FORBIDS_DISCOUNT` (the discount, if any, already lives inside\nthe total).\n\nThe mode is what the template promises, and it is re-applied on **every** generation:\na line declared as `total_including_tax: 1.00` over 300 units invoices 1,00 € on every\ngeneration, not 300 × 0,0033 = 0,99 €. Because `PATCH` replaces the lines as a whole,\nresending a line with a different amount field switches its mode.\n"
    • addedInput schema / $defs / RecurringLineRequest / properties / quantity / multipleOf
      Added value: +0.0001
    • addedInput schema / $defs / RecurringLineRequest / properties / total_excluding_tax
      Added value: +{
      +  "description": "Declared line total excluding taxes: this amount IS the taxable base, exactly,\nwith no recalculation. The stored `unit_price` becomes derived and informational\n(`total / quantity`, 4 decimals). Mutually exclusive with `unit_price` and\n`total_including_tax`.\n\nNegative totals are NOT accepted, for the same reason `unit_price` does not accept\nnegative prices: a template only issues `STANDARD` or `SIMPLIFIED` invoices, and only\na corrective invoice — created through its own endpoint over an already issued\ninvoice — carries a negative amount. A total outside the range is rejected with\n`422 VALIDATION_ERROR` and the offending field in `details`.\n\nThe upper bound is the same one `POST /v1/invoices` declares for a line total: a\ntemplate is a promise to issue an invoice, and it cannot accept less than the\ninvoice it will generate does. The derived `unit_price` (`total / quantity`) can\nstill exceed the `maximum` this contract accepts for `unit_price` itself — what\nactually bounds it then is the domain's price ceiling, not this field's contract.\n",
      +  "maximum": 99999999.99,
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / $defs / RecurringLineRequest / properties / total_including_tax
      Added value: +{
      +  "description": "Declared line total including taxes — what the customer pays. The engine works\nthe breakdown backwards so that taxable base + VAT + equivalence surcharge equals\nthis amount exactly on every generated invoice. IRPF withholding is never part of\nthe decomposition: it is a retention, not a price. Mutually exclusive with\n`unit_price` and `total_excluding_tax`.\n\nNegative totals are NOT accepted, same as `total_excluding_tax`.\n\nThe upper bound is the same one `POST /v1/invoices` declares for a line total, for\nthe same reason: the template cannot promise more than the invoice it generates\ncould ever accept. The derived `unit_price` (`total / quantity`) can still exceed\nthe `maximum` this contract accepts for `unit_price` itself — what actually bounds\nit then is the domain's price ceiling, not this field's contract.\n",
      +  "maximum": 99999999.99,
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / $defs / RecurringLineRequest / properties / unit_price / description
      Added value: +"Unit price before taxes. Supports up to 4 decimal places for micro-pricing\n(e.g. €0.0897/unit for labels, packaging); the generated invoices always round\ntheir amounts to 2 decimals. Mutually exclusive with `total_excluding_tax` and\n`total_including_tax`.\n\nThe upper bound is the same one the invoice line declares, and so is the\nacceptance of `0` (a discount granted before or simultaneously with the sale,\ne.g. a free introductory month). A price outside the range is rejected with\n`422 VALIDATION_ERROR` and the offending field in `details`.\n\nNegative prices are NOT accepted, unlike an invoice line of a corrective invoice:\na recurring template only issues `STANDARD` or `SIMPLIFIED` invoices, and a\ncorrective is created through its own endpoint over an already issued invoice —\nnever generated by a template.\n"
    • addedInput schema / $defs / RecurringLineRequest / properties / unit_price / maximum
      Added value: +999999.9999
    • changedInput schema / $defs / RecurringLineRequest / required
      Previous value: -[
      -  "description",
      -  "quantity",
      -  "unit_price",
      -  "vat_rate"
      -]New value: +[
      +  "description",
      +  "quantity",
      +  "vat_rate"
      +]
    • addedInput schema / properties / recurring_invoice_id / description
      Added value: +"Unique identifier (UUID) of the recurring invoice template, as returned when it is created or listed. A template of another company answers `404` with `RECURRING_NOT_FOUND`, exactly like one that does not exist."
  2. Changed14 schema fields changedv0.5.0
    • removedInput schema / $defs / ExemptionReason / example
      Removed value: -"EXENTA_ART_20"
    • addedInput schema / $defs / PatchRecurringInvoiceRequest / additionalProperties
      Added value: +false
    • removedInput schema / $defs / PatchRecurringInvoiceRequest / properties / email_configuration / allOf
      Removed value: -[
      -  {
      -    "$ref": "#/$defs/RecurringEmailConfigRequest"
      -  }
      -]
    • addedInput schema / $defs / PatchRecurringInvoiceRequest / properties / email_configuration / anyOf
      Added value: +[
      +  {
      +    "allOf": [
      +      {
      +        "$ref": "#/$defs/RecurringEmailConfigRequest"
      +      }
      +    ],
      +    "description": "Email delivery settings, replaced as a whole. Send `null` to stop sending the\ngenerated invoices by email.\n"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedInput schema / $defs / PatchRecurringInvoiceRequest / properties / email_configuration / description
      Removed value: -"Email delivery settings, replaced as a whole. Send `null` to stop sending the\ngenerated invoices by email.\n"
    • removedInput schema / $defs / PatchRecurringInvoiceRequest / properties / payment_method / allOf
      Removed value: -[
      -  {
      -    "$ref": "#/$defs/PaymentMethod"
      -  }
      -]
    • addedInput schema / $defs / PatchRecurringInvoiceRequest / properties / payment_method / anyOf
      Added value: +[
      +  {
      +    "allOf": [
      +      {
      +        "$ref": "#/$defs/PaymentMethod"
      +      }
      +    ],
      +    "description": "Payment method. Replaced as a whole together with `payment_iban`,\n`payment_swift` and `payment_term_days`: send them in the same request or they\nare dropped. Send `null` to state that no payment method applies.\n"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedInput schema / $defs / PatchRecurringInvoiceRequest / properties / payment_method / description
      Removed value: -"Payment method. Replaced as a whole together with `payment_iban`,\n`payment_swift` and `payment_term_days`: send them in the same request or they\nare dropped. Send `null` to state that no payment method applies.\n"
    • removedInput schema / $defs / PaymentMethod / example
      Removed value: -"BANK_TRANSFER"
    • addedInput schema / $defs / RecurringLineRequest / additionalProperties
      Added value: +false
    • removedInput schema / $defs / RecurringLineRequest / properties / exemption_reason / $ref
      Removed value: -"#/$defs/ExemptionReason"
    • addedInput schema / $defs / RecurringLineRequest / properties / exemption_reason / anyOf
      Added value: +[
      +  {
      +    "$ref": "#/$defs/ExemptionReason"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedInput schema / additionalProperties
      Added value: +false
    • changedInput schema / properties / company_id / description
      Previous value: -"NIF (company) the operation acts on. It is the only source of context: the account that owns it is derived from it, and the `BeeL-Active-Company` header plays no part. A NIF you do not reach answers `403`, and so does a NIF that does not exist, so the existence of a NIF in another account is never disclosed."New value: +"Unique identifier (UUID) of the company the operation acts on — its identifier, not its NIF. It is the only source of context: the account that owns it is derived from it, and the `BeeL-Active-Company` header plays no part. A company you do not reach answers `403`, and so does a company that does not exist, so the existence of a company in another account is never disclosed."
  3. First observedv0.3.1

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly=false, idempotent=false, destructive=false; the description goes well beyond that with replacement-vs-clear semantics, that lines are replaced wholesale (recipient survives, empty array rejected), that schedule fields recalculate the next generation and discard a pending skip, that start_date is only editable pre-issuance, and that frequency changes reschedule. This is exactly the behavioral detail annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core patch contract, then scannable bolded bullets for the fields whose behavior is surprising, then the endpoint and a pre-call warning. Dense but each bullet carries non-obvious information; the only slight redundancy is the endpoint line, which is already implied by the tool contract.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex mutation with no output schema and a large request schema, the description covers the key edge cases (mode conflicts, max_invoices semantics, payment-detail dependencies) and even notes the response carries the new next_generation. It leaves out auth/permission requirements and error-response shape, which is a minor gap rather than a blocking one.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67% and the embedded PatchRecurringInvoiceRequest already documents the body fields in depth, so the description's body-level bullets largely restate the schema. The two identifier parameters (company_id, recurring_invoice_id) get no added meaning from the description. Baseline 3 fits where the schema does most of the parameter work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Updates only the fields present in the body... of the recurring invoice template') and makes the partial-update semantics the headline, which distinguishes it from a full replace or from the status/delete/skip siblings. An agent can tell immediately this is a field-level PATCH of a recurring template.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear conditional guidance for the body (omitted keeps, null clears only where nullable, lines/payment_method replaced as a whole, schedule fields move generation) and points to beel_rules_list for fiscal context before calling. It does not explicitly route between this tool and siblings like beel_set_recurring_invoice_status or beel_generate_recurring_invoice_now, so it stops short of full when/when-not.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools