beel-es · Schema
UpdateInvoiceRequest
Partial update for a DRAFT invoice. Only fields present in the body are applied; omitted fields preserve their existing value.
invoicingSpainAPIfintechSaaS
Properties
| Name | Type | Description |
|---|---|---|
| type | object | New invoice type. Allowed transitions: `STANDARD` ↔ `SIMPLIFIED`. Transitions to/from `CORRECTIVE` are rejected (corrective invoices have a dedicated `POST /v1/invoices/{invoice_id}/corrective` endpoi |
| series_id | object | Series ID. If provided, changes the invoice series (only for DRAFT invoices). The invoice number will be reassigned from the new series when issued. |
| operation_date | stringnull | Date when the operation occurred. **Must be today or a past date**, and not more than twenty years before today (AEAT does not accept an older one): an older date answers `422 OPERATION_DATE_TOO_OLD`, |
| due_date | stringnull | New due date. Must be the same as or after `issue_date`. Set to null to clear the due date. If not provided, keeps the existing value. |
| valid_until | stringnull | Offer validity date. Only rendered on PROFORMA invoices; on any other invoice type the field is inert. Purely informational. Set to null to clear it. If not provided, keeps the existing value. |
| recipient | object | Replaces the recipient when present. Provide `customer_id` to switch to a registered client, or inline `legal_name`/`nif`/`address` for an ad-hoc receptor, not both (422 `RECIPIENT_CUSTOMER_AND_DATA_E |
| lines | array | |
| payment_info | object | Replaces the payment information when present (sets method/IBAN/SWIFT/term days). Omit to keep the current payment info. |
| notes | string | |
| custom_fields | arraynull | Replaces the custom fields of the invoice as a whole: the list sent becomes the new list. Omit it to keep the current ones; send `null` or `[]` to remove them all. The same rules as on creation apply: |
| options | object | Processing options for the draft. Fields are optional and follow partial update semantics: omitted fields preserve the existing value. |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/beel-es/json-schema/beel-es-update-invoice-request-schema.json",
"title": "UpdateInvoiceRequest",
"description": "Partial update for a DRAFT invoice. Only fields present in the body are applied;\nomitted fields preserve their existing value.\n",
"x-generated": "2026-10-30",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/beel-es-openapi.json#/components/schemas/UpdateInvoiceRequest",
"type": "object",
"properties": {
"type": {
"allOf": [
{
"$ref": "#/$defs/InvoiceType"
}
],
"description": "New invoice type. Allowed transitions: `STANDARD` ↔ `SIMPLIFIED`.\nTransitions to/from `CORRECTIVE` are rejected (corrective invoices have a\ndedicated `POST /v1/invoices/{invoice_id}/corrective` endpoint).\nTransitions to/from `PROFORMA` are rejected too — a proforma is converted\ninto an invoice via its dedicated conversion flow, never by editing its type.\n"
},
"series_id": {
"allOf": [
{
"$ref": "#/$defs/UUID"
}
],
"description": "Series ID. If provided, changes the invoice series (only for DRAFT invoices).\nThe invoice number will be reassigned from the new series when issued.\n"
},
"operation_date": {
"type": [
"string",
"null"
],
"format": "date",
"description": "Date when the operation occurred. **Must be today or a past date**, and not more than\ntwenty years before today (AEAT does not accept an older one): an older date answers\n`422 OPERATION_DATE_TOO_OLD`, on update and again on issue.\nSet to null to clear (operation date = issue date).\nIf not provided, keeps the existing value.\n"
},
"due_date": {
"type": [
"string",
"null"
],
"format": "date",
"description": "New due date. Must be the same as or after `issue_date`.\nSet to null to clear the due date. If not provided, keeps the existing value.\n"
},
"valid_until": {
"type": [
"string",
"null"
],
"format": "date",
"description": "Offer validity date. Only rendered on PROFORMA invoices; on any other\ninvoice type the field is inert. Purely informational.\nSet to null to clear it. If not provided, keeps the existing value.\n"
},
"recipient": {
"allOf": [
{
"$ref": "#/$defs/Recipient"
}
],
"description": "Replaces the recipient when present. Provide `customer_id` to switch to a\nregistered client, or inline `legal_name`/`nif`/`address` for an ad-hoc receptor,\nnot both (422 `RECIPIENT_CUSTOMER_AND_DATA_EXCLUSIVE`). Omit to keep the current\nrecipient.\n"
},
"lines": {
"type": "array",
"items": {
"type": "object",
"required": [
"quantity"
],
"properties": {
"description": {
"type": "string",
"maxLength": 2000,
"description": "Required for NORMAL lines; optional for SUPLIDO lines.\n"
},
"quantity": {
"type": "number"
},
"unit": {
"type": "string"
},
"unit_price": {
"type": "number",
"minimum": 0,
"maximum": 999999.9999,
"description": "Unit price before taxes. `0` is accepted (a discount granted before or\nsimultaneously with the sale, e.g. a free introductory month).\nSupports up to 4 decimal places for micro-pricing (e.g., €0.0897/unit for labels, packaging).\nFinal amounts are always rounded to 2 decimals.\n"
},
"total_excluding_tax": {
"type": "number",
"maximum": 99999999.99,
"description": "Declared line total excluding taxes (total-declared mode, e.g. 300 units\ninvoiced for exactly 1.00). The taxable base of the line is EXACTLY this\namount — it is never recalculated from the unit price. The unit price\nbecomes derived and informational (`total / quantity`, 4 decimals).\nEach line must carry exactly one of `unit_price`, `total_excluding_tax`\nor `total_including_tax` (anything else is rejected with\n`LINE_UNIT_PRICE_XOR_DECLARED_TOTAL`). Incompatible with\n`discount_percentage` (`LINE_DECLARED_TOTAL_FORBIDS_DISCOUNT`): any\ndiscount is already included in the declared total. Can be negative\nin corrective invoices.\n"
},
"total_including_tax": {
"type": "number",
"maximum": 99999999.99,
"description": "Declared line total including taxes (tax-inclusive total-declared\nmode): what the customer paid for this line — taxable base + VAT +\nequivalence surcharge. IRPF withholding is NOT part of it (it is a\nretention, not price; it is computed on the derived base as usual).\nThe engine works the breakdown backwards from the unrounded base\n(`base_raw = total / (1 + vat + surcharge)`, DGT V1919-18) so the\nrounded amounts add up to the declared total exactly (e.g. 100.00\nat 21% → 82.64 + 17.36 = 100.00). On exempt or 0% lines it is\nequivalent to `total_excluding_tax` (base = total, quota 0).\nEach line must carry exactly one of `unit_price`, `total_excluding_tax`\nor `total_including_tax` (anything else is rejected with\n`LINE_UNIT_PRICE_XOR_DECLARED_TOTAL`). Incompatible with\n`discount_percentage` (`LINE_DECLARED_TOTAL_FORBIDS_DISCOUNT`).\nCan be negative in corrective invoices.\n"
},
"discount_percentage": {
"type": "number"
},
"main_tax": {
"$ref": "#/$defs/TaxInfo"
},
"equivalence_surcharge_rate": {
"$ref": "#/$defs/EquivalenceSurchargePercentage"
},
"irpf_rate": {
"allOf": [
{
"$ref": "#/$defs/IrpfPercentage"
}
],
"description": "IRPF withholding rate for this line.\n\n**Default behaviour:** if omitted, the line inherits the\naccount's default IRPF rate (configured in the tax profile,\ne.g. 15%). To issue a line **without** withholding you must\nsend `irpf_rate: 0` explicitly. On SIMPLIFIED invoices (F2)\nIRPF withholding is **not allowed** (AEAT forbids it on F2):\nsending an `irpf_rate` other than 0 is **rejected** with\n`SIMPLIFICADA_FORBIDS_IRPF` — it is not coerced to 0. Omit the\nfield or send `irpf_rate: 0` on F2 lines. On all other invoice\ntypes an explicit value is always respected.\n\nThe rate must be one the issuer can bear (see `WithholdingOptions` in the\ntax configuration). No entity pays IRPF: a legal person or a permanent\nestablishment (NIF starting with `A`, `B`, `C`, `D`, `F`, `G`, `Q`, `R`,\n`U` or `W`) only accepts `0`, `19`, `24` and `9.5` (rents in Ceuta and\nMelilla), a non-resident entity (`N`) `0`, `19` and `24`, and the State,\nan Autonomous Community or a local entity (`S`, `P`) only `0`; any other\nrate is rejected with `IRPF_RATE_NOT_FOR_CORPORATE_ISSUER`. `9.5` from an\nindividual is rejected with `IRPF_RATE_ONLY_FOR_CORPORATE_ISSUER`: under IRPF the Ceuta\nand Melilla reduced rates are `6`, `2.8` and `7.6`. Checked on creation,\non edit and again on issue; corrective invoices are not checked: they\ncorrect by differences what the original carried.\n"
},
"exemption_reason": {
"$ref": "#/$defs/ExemptionReason",
"nullable": true
},
"exemption_reason_text": {
"type": [
"string",
"null"
],
"maxLength": 500
},
"line_type": {
"allOf": [
{
"$ref": "#/$defs/InvoiceLineType"
}
],
"description": "Fiscal line type. Omitted, `NORMAL` applies.\nUse `SUPLIDO` for payments on behalf of the final client\n(art. 78.Tres.3 LIVA). Requires `source_invoice_reference`.\n"
},
"source_invoice_reference": {
"type": [
"string",
"null"
],
"maxLength": 50,
"description": "Reference to the original invoice issued by the third party in the\nclient's name. Required when `line_type=SUPLIDO`.\n"
},
"source_invoice_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Ids of the issued invoices that make up the SUPLIDO. They may belong to the\nissuing account or to accounts it manages with VIEW access.\nTheir sum is the amount (never typed). Audit traceability.\n"
}
}
}
},
"payment_info": {
"allOf": [
{
"$ref": "#/$defs/PaymentInfo"
}
],
"description": "Replaces the payment information when present (sets method/IBAN/SWIFT/term days).\nOmit to keep the current payment info.\n"
},
"notes": {
"type": "string"
},
"custom_fields": {
"type": [
"array",
"null"
],
"maxItems": 20,
"description": "Replaces the custom fields of the invoice as a whole: the list sent becomes the new\nlist. Omit it to keep the current ones; send `null` or `[]` to remove them all. The\nsame rules as on creation apply: at most one value per `key`, a `key` the company does\nnot have answers `422 CUSTOM_FIELD_UNKNOWN` and an archived field answers\n`409 CUSTOM_FIELD_ARCHIVED`, even when the draft already carries it. Every field in\nthe list is saved again with the label it has now. Only a draft, a scheduled invoice\nor an active proforma can change them; any other status answers\n`422 STATUS_NOT_MODIFIABLE`.\n\nWhen the request changes the recipient and omits `custom_fields`, the saved fields are\ncarried over to the new customer; one archived since is left out, with no error.\n\nThey are informational: they are not part of the VeriFactu record sent to the AEAT and\ndo not enter its hash.\n",
"items": {
"$ref": "#/$defs/InvoiceCustomFieldInput"
}
},
"options": {
"type": "object",
"description": "Processing options for the draft. Fields are optional and follow partial update\nsemantics: omitted fields preserve the existing value.\n",
"properties": {
"send_automatically": {
"type": "boolean",
"description": "Whether the invoice should be auto-emailed after issuing."
},
"email_config": {
"allOf": [
{
"$ref": "#/$defs/EmailConfiguration"
}
],
"nullable": true,
"description": "Email configuration for auto-send. null clears the existing config."
}
}
}
},
"$defs": {
"Address": {
"description": "Address you send when you create or update a company, a customer or an onboarding.\n\nA required field made only of whitespace passes the length checks below but leaves the\naddress without that part, so it is rejected with `422`: `STREET_EMPTY`,\n`POSTAL_CODE_EMPTY`, `CITY_EMPTY` or `PROVINCE_EMPTY`.\n\nAddresses you read back are described by their own schema.\n",
"type": "object",
"required": [
"street",
"postal_code",
"city"
],
"properties": {
"street": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[a-zA-Z0-9À-ÿ\\u0100-\\u017F\\u00B7\\u2018\\u2019\\u0060\\u00B4\\s\\.,\\-\\/'ºª°:;\"()&#]+$",
"description": "Full address (street, number, floor, etc.) - Latin characters only"
},
"number": {
"type": "string",
"minLength": 1,
"maxLength": 20,
"description": "Street number. Optional: omit it when the address has none, or when `street` already\ncarries the address in full.\n"
},
"floor": {
"type": "string",
"maxLength": 10,
"description": "Floor or level"
},
"door": {
"type": "string",
"maxLength": 10,
"description": "Door or apartment"
},
"postal_code": {
"type": "string",
"minLength": 1,
"maxLength": 20,
"description": "Postal code (5 digits for Spain, free format for other countries)"
},
"city": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"pattern": "^[a-zA-Z0-9À-ÿ\\u0100-\\u017F\\u00B7\\u2018\\u2019\\u0060\\u00B4\\s\\.,\\-\\/'ºª°:;\"()&#]+$",
"description": "City or town - Latin characters only"
},
"province": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"pattern": "^[a-zA-Z0-9À-ÿ\\u0100-\\u017F\\u00B7\\u2018\\u2019\\u0060\\u00B4\\s\\.,\\-\\/'ºª°:;\"()&#]+$",
"description": "Province or state - Latin characters only. Required for an address in Spain\n(`country_code` `ES`, or no country at all); optional elsewhere, where many addresses\nhave none. A Spanish address without it is rejected with a `422`.\n"
},
"country": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"pattern": "^[a-zA-Z0-9À-ÿ\\u0100-\\u017F\\u00B7\\u2018\\u2019\\u0060\\u00B4\\s\\.,\\-\\/'ºª°:;\"()&#]+$",
"description": "Country of the address, as its ISO 3166-1 alpha-2 code (`GB`) or its official name\nin Spanish, English or Catalan (`Reino Unido`, `United Kingdom`, `Regne Unit`;\ncase and accents are ignored). Anything else, such as `UK`, is rejected with\n`422 COUNTRY_CODE_REQUIRED`: send `country_code` instead. If it names a different\ncountry than `country_code`, `422 COUNTRY_CODE_MISMATCH` (`España` alone yields to\na foreign `country_code`: it was the old default). What is stored and\nreturned is always the Spanish name derived from the resulting code, never the\ntext sent. With neither field present, the address is Spanish (`España`).\n"
},
"country_code": {
"type": "string",
"pattern": "^[A-Z]{2}$",
"minLength": 2,
"maxLength": 2,
"description": "ISO 3166-1 alpha-2 country code: the canonical field that decides the country of\nthe address. It must be a real country code (`GB`, not `UK`); otherwise\n`422 COUNTRY_CODE_REQUIRED`. When it is omitted, the code comes from `country`\n(see there). With neither field present, the address is stored as `ES`.\n"
}
}
},
"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."
},
"Email": {
"type": "string",
"format": "email",
"minLength": 5,
"maxLength": 255,
"description": "Email address (minimum valid email is 5 chars, e.g. a@b.co)"
},
"EmailConfiguration": {
"type": "object",
"description": "Who the invoice is emailed to when `send_automatically` is true. Every address in\n`recipients` and `cc` must have a domain with a dot, or the request answers\n`422 INVALID_EMAIL_FORMAT`. With `send_automatically` true and no recipients here, no\n`customer_id` and no recipient email, there is nobody to send to: `422`\n`AUTOMATIC_EMAIL_CONFIG_INVALID`.\n",
"required": [
"recipients"
],
"properties": {
"recipients": {
"type": "array",
"items": {
"$ref": "#/$defs/Email"
},
"minItems": 1,
"description": "List of recipient emails (at least 1 required)"
},
"cc": {
"type": "array",
"items": {
"$ref": "#/$defs/Email"
},
"description": "List of CC emails (optional)"
},
"subject": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Custom email subject (optional). Priority: the request that sends the email > this\n`email_config.subject` > the `defaults.subject` of the company's email configuration >\nthe standard subject.\n"
},
"message": {
"type": "string",
"minLength": 1,
"maxLength": 2000,
"description": "Custom message (optional, added to the email body). It is sent with the email.\nPriority: the request that sends the email > this `email_config.message` > the\n`defaults.message` of the company's email configuration > the standard message.\n"
}
}
},
"EquivalenceSurchargePercentage": {
"type": "number",
"enum": [
0,
0.26,
0.5,
0.62,
1,
1.4,
1.75,
5.2
],
"description": "Equivalence surcharge percentage in decimal format, one of the values AEAT accepts.\nPairs allowed (VAT rate ↔ surcharge): 21↔5.2, 21↔1.75 (tobacco products), 10↔1.4,\n4↔0.5, and the temporary ones, only on operations of their period: 5↔0.5 up to\n2022-12-31, 5↔0.62 from 2023-01-01 to 2024-09-30, and 7.5↔1 and 2↔0.26 from\n2024-10-01 to 2024-12-31. A pair outside its period is rejected with\n`422 SURCHARGE_RATE_NOT_ACCEPTED_ON_DATE`. `GET /v1/tax-types` publishes every pair with\nits `valid_from` / `valid_until`.\nThe backend automatically normalizes equivalent formats (5.20 → 5.2).\n"
},
"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"
},
"IBAN": {
"type": "string",
"pattern": "^[A-Z]{2}\\d{2}[A-Z0-9]{1,30}$",
"minLength": 15,
"maxLength": 34,
"description": "IBAN (International Bank Account Number).\nRequired when payment method is BANK_TRANSFER.\n"
},
"InvoiceCustomFieldInput": {
"type": "object",
"description": "The value of one custom field of the company on an invoice. The field must exist in the company and be active; the label is taken from it when the invoice is saved.",
"required": [
"key",
"value"
],
"properties": {
"key": {
"$ref": "#/$defs/CustomFieldKey"
},
"value": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Text of the value. Leading and trailing spaces are removed; a value that is empty after that answers `422`. When an option of the field is equivalent (it matches ignoring case, accents and repeated spaces), the invoice stores the text of that option, archived options included. Otherwise the text is stored as sent and, when the invoice has a registered customer (`recipient.customer_id`), it is added as an option of that customer; with recipient data sent inline, no option is created. On a field with `suggest_values: false` the value is never compared with the options and never creates one: the invoice stores the text as sent, without the leading and trailing spaces."
}
}
},
"InvoiceLineType": {
"type": "string",
"description": "Fiscal line type. `NORMAL` contributes to the taxable base and VAT;\n`SUPLIDO` is a payment made on behalf of the client and is excluded from both.\n",
"enum": [
"NORMAL",
"SUPLIDO"
]
},
"InvoiceType": {
"type": "string",
"enum": [
"STANDARD",
"CORRECTIVE",
"SIMPLIFIED",
"PROFORMA"
],
"description": "- STANDARD: Standard invoice\n- CORRECTIVE: Corrects or cancels a previous invoice\n- SIMPLIFIED: Simplified invoice (ticket), for a recipient that is not identified. BeeL.\n requires a STANDARD invoice when the recipient is identified, at any amount: a\n SIMPLIFIED invoice whose recipient carries an `nif` or `alternative_id` is rejected\n with `SIMPLIFIED_INVOICE_FORBIDS_IDENTIFIED_RECIPIENT`. The only amount BeeL\n enforces is a cap of 3,000€ VAT included (`SIMPLIFIED_INVOICE_EXCEEDS_LEGAL_LIMIT`). The\n general limit of RD 1619/2012 is 400€ (art. 4.1.a); up to 3,000€ applies only to the\n activities listed in art. 4.2. BeeL does not check which activity the issuer carries\n out.\n- PROFORMA: Commercial document (formal quote) with no fiscal validity.\n Never enters VeriFactu (no QR, no AEAT submission): `verifactu.enabled` is\n always `false`, whatever the company's regime. Requires full recipient data,\n like STANDARD.\n Cannot be corrective nor reference a rectified invoice.\n"
},
"IrpfPercentage": {
"type": "number",
"enum": [
0,
1,
2,
2.8,
6,
7,
7.6,
9.5,
15,
19,
24
],
"description": "Withholding (IRPF) percentage, as the IRPF regulation (Royal Decree 439/2007) sets it: 0 (no withholding), 1 (pig fattening and poultry, and some activities\nunder objective estimation), 2 (other agricultural, livestock and forestry activities),\n7 (professional activity in its first three years, and the other 7 % cases), 15\n(professional activities, and intellectual property income), 19 (rent of urban property\nand other income of art. 75.2.b; also the general rate of the Corporate Income Tax\nwithholding) and 24 (image rights). A company that pays Corporate Income Tax can only use\n0, 19, 24 and 9.5: see `WithholdingOptions`.\n\nCeuta and Melilla: income with the Ceuta and Melilla deduction bears the base rate reduced as\nthe law sets it. Under IRPF, 15 % and 7 % (professional activities) and 19 % (rent of urban\nproperty located there) are reduced by 60 %: 6, 2.8 and 7.6. Under Corporate Income Tax, 19 %\non those rents is halved: 9.5, which only a company can use\n(`IRPF_RATE_ONLY_FOR_CORPORATE_ISSUER` otherwise). Whether the reduction applies is the\nissuer's choice: the NIF does not show it.\n\nThe value counts, not how it is written: `15.0` is `15` and `2.80` is `2.8`.\n"
},
"PaymentInfo": {
"type": "object",
"properties": {
"method": {
"allOf": [
{
"$ref": "#/$defs/PaymentMethod"
}
],
"description": "Preferred payment method. Omitted, `BANK_TRANSFER` applies.\nIf NONE is selected, no payment information will be shown on the invoice.\n"
},
"iban": {
"$ref": "#/$defs/IBAN"
},
"swift": {
"$ref": "#/$defs/SWIFT"
},
"payment_term_days": {
"type": [
"integer",
"null"
],
"minimum": 0,
"maximum": 365,
"description": "Payment term in days. When marking an invoice as paid, every field of this object\nthat travels replaces the stored one and every omitted field keeps its current value.\n"
}
}
},
"PaymentMethod": {
"type": "string",
"description": "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",
"enum": [
"NONE",
"BANK_TRANSFER",
"CARD",
"CASH",
"CHECK",
"DIRECT_DEBIT",
"BIZUM",
"OTHER"
]
},
"PhoneInput": {
"type": "string",
"minLength": 9,
"maxLength": 20,
"pattern": "^[+]?[0-9\\s\\-\\(\\)]+$",
"description": "A phone number as this API accepts it: 9 to 20 characters, and only digits, spaces,\ndashes, parentheses and an optional leading `+`. Every request that takes a phone number\nuses this schema.\n\nIt is `Phone` plus the rules enforced on input. A value this schema accepts always\nsatisfies `Phone`, so anything you send here is something a response can return.\n"
},
"Recipient": {
"type": "object",
"description": "Invoice recipient: either a registered customer (`customer_id`) or the recipient's
# --- truncated at 32 KB (40 KB total) ---
# Full source: https://artifacts.apis.io/beel-es/json-schema/beel-es-update-invoice-request-schema.json
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/beel-es-update-invoice-request"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.