Examples cookbook

Runnable curl + JSON for every common VeriFactu scenario, mapped to BeeL's public API.


Every scenario below maps a real AEAT case to the exact JSON BeeL's public API expects. Field names and enum values come straight from the OpenAPI spec — copy, change the recipient, and ship. For the why behind each combination, follow the cross-links into the concept pages.

All examples target https://app.beel.es/api/v1/invoices and assume your account has VeriFactu enabled. Sandbox keys (beel_sk_test_*) submit to AEAT pre-production and don't consume quota.

Quick reference

Scenariotypeexemption_reasonregime_keySurchargeRecipient
F2 simplified — under 3000 €SIMPLIFIED"01"omitted
F1 standard — Spanish B2BSTANDARD"01"NIF + address
F1 multiple VAT ratesSTANDARD"01"NIF + address
F1 with IRPFSTANDARD"01"NIF + address
F1 recargo de equivalenciaSTANDARD"18"5.2NIF + address
F1 intra-EU B2B goods (E5)STANDARDEXENTA_ART_25"01"NIF_IVA
F1 intra-EU B2B services (N2)STANDARDNO_SUJETA_LOCALIZACION"01"NIF_IVA
F1 B2C OSS over thresholdSTANDARDNO_SUJETA_LOCALIZACION"17"PASSPORT
F1 B2C under thresholdSTANDARD"01"PASSPORT
F1 export non-EU (E2)STANDARDEXENTA_ART_21"02"PASSPORT
F1 services non-EU (N2)STANDARDNO_SUJETA_LOCALIZACION"01"PASSPORT
F1 exempt E1 (medical/edu)STANDARDEXENTA_ART_20"01"NIF + address
F1 IGIC (Canarias)STANDARD"01"NIF + address
F1 not subject (N1)STANDARDNO_SUJETA_ART_7_9"01"NIF + address
F1 ISP — reverse charge (S2)STANDARDISP_ART_84_2_F"01"NIF + address
F1 REBU (used goods)STANDARD"03"NIF + address
R1 corrective — partial(corrective)"01"inherited
R5 corrective — total on F2(corrective)"01"inherited
Voiding (anulación)n/an/a

The first row of every table is the canonical pattern; everything below it is a variation. Read Tax classification per line for the full enum of exemption_reason codes and how they map to AEAT's S1/S2/N1/N2/E1–E6 four-family taxonomy.

F2 simplified — under 3000 €, no recipient

The bread-and-butter ticket invoice. Use SIMPLIFIED when the total stays under 3 000 €, the customer is a consumer, and you have no NIF to record. Pass recipient: {} — the field itself is required, but every property inside it is optional for SIMPLIFIED, and BeeL fills consumidor final automatically.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "SIMPLIFIED",
    "recipient": {},
    "lines": [
      {
        "description": "Menú del día",
        "quantity": 2,
        "unit": "unit",
        "unit_price": 14.50,
        "main_tax": { "type": "IVA", "percentage": 10, "regime_key": "01" }
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "SIMPLIFIED",
  "recipient": {},
  "lines": [
    {
      "description": "Menú del día",
      "quantity": 2,
      "unit": "unit",
      "unit_price": 14.50,
      "main_tax": { "type": "IVA", "percentage": 10, "regime_key": "01" }
    }
  ],
  "options": { "issue_directly": true }
}

See Simplified vs standard for the 3 000 € rule and the NIF-or-no-NIF decision tree.

F1 standard — Spanish business customer

The default B2B invoice between two Spanish entities. The recipient must have a valid Spanish NIF and a full address — both are required for VeriFactu to accept the registro.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 4a7d1ed4-9bc9-4f7e-b1e9-7c2a5f9b8d11" \
  -d '{
    "type": "STANDARD",
    "due_date": "2026-06-19",
    "recipient": {
      "legal_name": "ACCIONA SA",
      "nif": "A08001851",
      "address": {
        "street": "Avenida de Europa",
        "number": "18",
        "postal_code": "28108",
        "city": "Alcobendas",
        "province": "Madrid",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Consultoría de arquitectura — Sprint mayo",
        "quantity": 40,
        "unit": "hours",
        "unit_price": 75.00,
        "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
      }
    ],
    "payment_info": {
      "method": "BANK_TRANSFER",
      "iban": "ES9121000418450200051332",
      "payment_term_days": 30
    },
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "due_date": "2026-06-19",
  "recipient": {
    "legal_name": "ACCIONA SA",
    "nif": "A08001851",
    "address": {
      "street": "Avenida de Europa",
      "number": "18",
      "postal_code": "28108",
      "city": "Alcobendas",
      "province": "Madrid",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Consultoría de arquitectura — Sprint mayo",
      "quantity": 40,
      "unit": "hours",
      "unit_price": 75.00,
      "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
    }
  ],
  "payment_info": {
    "method": "BANK_TRANSFER",
    "iban": "ES9121000418450200051332",
    "payment_term_days": 30
  },
  "options": { "issue_directly": true }
}

The Idempotency-Key header is optional but recommended for any issue_directly: true call — retrying with the same UUID returns the original response instead of duplicating the registro.

F1 with multiple VAT rates per line

One invoice can mix any combination of the allowed VAT percentages (0, 4, 5, 10, 21). BeeL builds the vat_breakdown automatically by grouping lines per rate.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "ACCIONA SA",
      "nif": "A08001851",
      "address": {
        "street": "Calle Cava Baja",
        "number": "35",
        "postal_code": "28005",
        "city": "Madrid",
        "province": "Madrid",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Vino reserva (caja 6 botellas)",
        "quantity": 4,
        "unit": "box",
        "unit_price": 90.00,
        "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
      },
      {
        "description": "Servicio de catering — menú degustación",
        "quantity": 25,
        "unit": "menu",
        "unit_price": 32.00,
        "main_tax": { "type": "IVA", "percentage": 10, "regime_key": "01" }
      },
      {
        "description": "Pan artesano",
        "quantity": 50,
        "unit": "unit",
        "unit_price": 1.20,
        "main_tax": { "type": "IVA", "percentage": 4, "regime_key": "01" }
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "ACCIONA SA",
    "nif": "A08001851",
    "address": {
      "street": "Calle Cava Baja",
      "number": "35",
      "postal_code": "28005",
      "city": "Madrid",
      "province": "Madrid",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Vino reserva (caja 6 botellas)",
      "quantity": 4,
      "unit": "box",
      "unit_price": 90.00,
      "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
    },
    {
      "description": "Servicio de catering — menú degustación",
      "quantity": 25,
      "unit": "menu",
      "unit_price": 32.00,
      "main_tax": { "type": "IVA", "percentage": 10, "regime_key": "01" }
    },
    {
      "description": "Pan artesano",
      "quantity": 50,
      "unit": "unit",
      "unit_price": 1.20,
      "main_tax": { "type": "IVA", "percentage": 4, "regime_key": "01" }
    }
  ],
  "options": { "issue_directly": true }
}

What changes vs. the previous example: three lines instead of one, each with a different main_tax.percentage. The response totals.vat_breakdown carries three entries (21, 10, 4).

F1 with IRPF withholding

Professionals subject to IRPF retention add irpf_rate to the line. The accepted values are 0, 1, 2, 7, 15, 19, 24 (IrpfPercentage enum) — for general professional activity it's almost always 15 (or 7 during the first two years of activity).

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "ACCIONA SA",
      "nif": "A08001851",
      "address": {
        "street": "Avenida de Europa",
        "number": "18",
        "postal_code": "28108",
        "city": "Alcobendas",
        "province": "Madrid",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Servicios de abogacía — asesoramiento mercantil",
        "quantity": 12,
        "unit": "hours",
        "unit_price": 120.00,
        "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" },
        "irpf_rate": 15
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "ACCIONA SA",
    "nif": "A08001851",
    "address": {
      "street": "Avenida de Europa",
      "number": "18",
      "postal_code": "28108",
      "city": "Alcobendas",
      "province": "Madrid",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Servicios de abogacía — asesoramiento mercantil",
      "quantity": 12,
      "unit": "hours",
      "unit_price": 120.00,
      "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" },
      "irpf_rate": 15
    }
  ],
  "options": { "issue_directly": true }
}

IRPF is never allowed on SIMPLIFIED invoices — Art. 7 RD 1619/2012 reserves the simplified format for retail-style operations that don't carry withholding. If you need to withhold, issue an F1. See Simplified vs standard.

F1 with recargo de equivalencia

For retailers (minoristas) that have declared themselves subject to the regime, add equivalence_surcharge_rate to each line and set main_tax.regime_key: "18".

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "ACCIONA SA",
      "nif": "A08001851",
      "address": {
        "street": "Calle del Comercio",
        "number": "56",
        "postal_code": "08001",
        "city": "Barcelona",
        "province": "Barcelona",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Lote de auriculares inalámbricos para reventa",
        "quantity": 30,
        "unit": "unit",
        "unit_price": 45.00,
        "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "18" },
        "equivalence_surcharge_rate": 5.2
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "ACCIONA SA",
    "nif": "A08001851",
    "address": {
      "street": "Calle del Comercio",
      "number": "56",
      "postal_code": "08001",
      "city": "Barcelona",
      "province": "Barcelona",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Lote de auriculares inalámbricos para reventa",
      "quantity": 30,
      "unit": "unit",
      "unit_price": 45.00,
      "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "18" },
      "equivalence_surcharge_rate": 5.2
    }
  ],
  "options": { "issue_directly": true }
}

The IVA-RE pairs are strict: 4 ↔ 0.5, 5 ↔ 0.625 (RD-ley 11/2022 temporary), 10 ↔ 1.4, 21 ↔ 5.2. Pass 0 to disable the surcharge on a specific line. See Equivalence surcharge for the full table.

F1 intra-EU B2B — goods (E5)

EU-to-EU sales of goods between two businesses with valid VIES VAT-IDs are exempt under Art. 25 LIVA. The buyer self-assesses the IVA in their country. BeeL validates the German VAT-ID against VIES before submission.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Berliner Industrie GmbH",
      "alternative_id": {
        "type": "NIF_IVA",
        "number": "DE123456789",
        "country_code": "DE"
      },
      "address": {
        "street": "Friedrichstraße",
        "number": "200",
        "postal_code": "10117",
        "city": "Berlin",
        "province": "Berlin",
        "country": "Alemania",
        "country_code": "DE"
      }
    },
    "lines": [
      {
        "description": "Componentes electrónicos — pedido EU-2026-0042",
        "quantity": 500,
        "unit": "unit",
        "unit_price": 8.40,
        "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
        "exemption_reason": "EXENTA_ART_25"
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Berliner Industrie GmbH",
    "alternative_id": {
      "type": "NIF_IVA",
      "number": "DE123456789",
      "country_code": "DE"
    },
    "address": {
      "street": "Friedrichstraße",
      "number": "200",
      "postal_code": "10117",
      "city": "Berlin",
      "province": "Berlin",
      "country": "Alemania",
      "country_code": "DE"
    }
  },
  "lines": [
    {
      "description": "Componentes electrónicos — pedido EU-2026-0042",
      "quantity": 500,
      "unit": "unit",
      "unit_price": 8.40,
      "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
      "exemption_reason": "EXENTA_ART_25"
    }
  ],
  "options": { "issue_directly": true }
}

What changes vs. the previous example: recipient uses alternative_id.type: "NIF_IVA" (VIES VAT-ID) instead of nif; line carries main_tax.percentage: 0 and exemption_reason: "EXENTA_ART_25". See International customers > B2B intra-EU goods.

F1 intra-EU B2B — services (N2)

Same German customer, but selling services instead of goods. Services to an EU business are no sujetas por localización (Art. 69 LIVA): the place of supply is the buyer's country, so the operation is outside the scope of Spanish IVA.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Berliner Industrie GmbH",
      "alternative_id": {
        "type": "NIF_IVA",
        "number": "DE123456789",
        "country_code": "DE"
      },
      "address": {
        "street": "Friedrichstraße",
        "number": "200",
        "postal_code": "10117",
        "city": "Berlin",
        "province": "Berlin",
        "country": "Alemania",
        "country_code": "DE"
      }
    },
    "lines": [
      {
        "description": "Consultoría de arquitectura cloud",
        "quantity": 60,
        "unit": "hours",
        "unit_price": 110.00,
        "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
        "exemption_reason": "NO_SUJETA_LOCALIZACION"
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Berliner Industrie GmbH",
    "alternative_id": {
      "type": "NIF_IVA",
      "number": "DE123456789",
      "country_code": "DE"
    },
    "address": {
      "street": "Friedrichstraße",
      "number": "200",
      "postal_code": "10117",
      "city": "Berlin",
      "province": "Berlin",
      "country": "Alemania",
      "country_code": "DE"
    }
  },
  "lines": [
    {
      "description": "Consultoría de arquitectura cloud",
      "quantity": 60,
      "unit": "hours",
      "unit_price": 110.00,
      "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
      "exemption_reason": "NO_SUJETA_LOCALIZACION"
    }
  ],
  "options": { "issue_directly": true }
}

What changes vs. the previous example: exemption_reason flips from EXENTA_ART_25 (E5, goods) to NO_SUJETA_LOCALIZACION (N2, services). The recipient block is identical — the bienes-vs-servicios distinction is per-line, not per-customer.

F1 intra-EU B2C — OSS over threshold

Once your annual cross-border B2C sales to EU consumers exceed 10 000 € you must apply destination-country IVA via the One-Stop-Shop (OSS) and file Modelo 369. The line carries regime_key: "17", exemption_reason: NO_SUJETA_LOCALIZACION, and percentage: 0 — the destination IVA is settled outside the Spanish IVA breakdown.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Anna Schmidt",
      "alternative_id": {
        "type": "PASSPORT",
        "number": "C0HJ4P9DT",
        "country_code": "DE"
      },
      "address": {
        "street": "Müllerstraße",
        "number": "47",
        "postal_code": "80469",
        "city": "München",
        "province": "Bayern",
        "country": "Alemania",
        "country_code": "DE"
      }
    },
    "lines": [
      {
        "description": "Suscripción anual plataforma SaaS",
        "quantity": 1,
        "unit": "year",
        "unit_price": 480.00,
        "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "17" },
        "exemption_reason": "NO_SUJETA_LOCALIZACION"
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Anna Schmidt",
    "alternative_id": {
      "type": "PASSPORT",
      "number": "C0HJ4P9DT",
      "country_code": "DE"
    },
    "address": {
      "street": "Müllerstraße",
      "number": "47",
      "postal_code": "80469",
      "city": "München",
      "province": "Bayern",
      "country": "Alemania",
      "country_code": "DE"
    }
  },
  "lines": [
    {
      "description": "Suscripción anual plataforma SaaS",
      "quantity": 1,
      "unit": "year",
      "unit_price": 480.00,
      "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "17" },
      "exemption_reason": "NO_SUJETA_LOCALIZACION"
    }
  ],
  "options": { "issue_directly": true }
}

The 10 000 € threshold is an annual aggregate across all EU countries — not per-country, not per-customer. Once you cross it (or opt in voluntarily) every cross-border B2C sale is OSS until year-end.

F1 intra-EU B2C — under OSS threshold

Below the threshold (and not opted in), cross-border B2C sales are billed with Spanish IVA as if the consumer were Spanish. No exemption_reason, default regime_key: "01", normal rate.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Anna Schmidt",
      "alternative_id": {
        "type": "PASSPORT",
        "number": "C0HJ4P9DT",
        "country_code": "DE"
      },
      "address": {
        "street": "Müllerstraße",
        "number": "47",
        "postal_code": "80469",
        "city": "München",
        "province": "Bayern",
        "country": "Alemania",
        "country_code": "DE"
      }
    },
    "lines": [
      {
        "description": "Curso online — fotografía digital",
        "quantity": 1,
        "unit": "course",
        "unit_price": 149.00,
        "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Anna Schmidt",
    "alternative_id": {
      "type": "PASSPORT",
      "number": "C0HJ4P9DT",
      "country_code": "DE"
    },
    "address": {
      "street": "Müllerstraße",
      "number": "47",
      "postal_code": "80469",
      "city": "München",
      "province": "Bayern",
      "country": "Alemania",
      "country_code": "DE"
    }
  },
  "lines": [
    {
      "description": "Curso online — fotografía digital",
      "quantity": 1,
      "unit": "course",
      "unit_price": 149.00,
      "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
    }
  ],
  "options": { "issue_directly": true }
}

What changes vs. the previous example: same German individual, but regime_key drops back to "01", exemption_reason is removed, and percentage becomes the standard Spanish 21. The 10 000 €/year aggregate decides which of the two shapes to use; track it externally.

F1 export of goods to non-EU (E2)

Goods leaving the EU are exempt under Art. 21 LIVA. The line needs exemption_reason: EXENTA_ART_21, regime_key: "02" (Export), and percentage: 0. The customer's alternative_id.type will typically be PASSPORT for individuals or OTHER_DOCUMENT for foreign businesses.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Northeast Imports Inc.",
      "alternative_id": {
        "type": "PASSPORT",
        "number": "551234567",
        "country_code": "US"
      },
      "address": {
        "street": "5th Avenue",
        "number": "725",
        "postal_code": "10022",
        "city": "New York",
        "province": "NY",
        "country": "Estados Unidos",
        "country_code": "US"
      }
    },
    "lines": [
      {
        "description": "Aceite de oliva virgen extra — palet 480 botellas",
        "quantity": 1,
        "unit": "pallet",
        "unit_price": 3850.00,
        "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "02" },
        "exemption_reason": "EXENTA_ART_21"
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Northeast Imports Inc.",
    "alternative_id": {
      "type": "PASSPORT",
      "number": "551234567",
      "country_code": "US"
    },
    "address": {
      "street": "5th Avenue",
      "number": "725",
      "postal_code": "10022",
      "city": "New York",
      "province": "NY",
      "country": "Estados Unidos",
      "country_code": "US"
    }
  },
  "lines": [
    {
      "description": "Aceite de oliva virgen extra — palet 480 botellas",
      "quantity": 1,
      "unit": "pallet",
      "unit_price": 3850.00,
      "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "02" },
      "exemption_reason": "EXENTA_ART_21"
    }
  ],
  "options": { "issue_directly": true }
}

See International customers > Exports of goods for the documentary evidence (DUA / customs declaration) you should keep alongside the invoice.

F1 services to non-EU (N2)

Services to a customer outside the EU are no sujetas por localización — same N2 family as intra-EU B2B services. The recipient is non-EU but the line shape is identical to the EU service case.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Northeast Imports Inc.",
      "alternative_id": {
        "type": "PASSPORT",
        "number": "551234567",
        "country_code": "US"
      },
      "address": {
        "street": "5th Avenue",
        "number": "725",
        "postal_code": "10022",
        "city": "New York",
        "province": "NY",
        "country": "Estados Unidos",
        "country_code": "US"
      }
    },
    "lines": [
      {
        "description": "Diseño de identidad de marca",
        "quantity": 1,
        "unit": "project",
        "unit_price": 6500.00,
        "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
        "exemption_reason": "NO_SUJETA_LOCALIZACION"
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Northeast Imports Inc.",
    "alternative_id": {
      "type": "PASSPORT",
      "number": "551234567",
      "country_code": "US"
    },
    "address": {
      "street": "5th Avenue",
      "number": "725",
      "postal_code": "10022",
      "city": "New York",
      "province": "NY",
      "country": "Estados Unidos",
      "country_code": "US"
    }
  },
  "lines": [
    {
      "description": "Diseño de identidad de marca",
      "quantity": 1,
      "unit": "project",
      "unit_price": 6500.00,
      "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
      "exemption_reason": "NO_SUJETA_LOCALIZACION"
    }
  ],
  "options": { "issue_directly": true }
}

What changes vs. the previous example: exemption_reason flips from EXENTA_ART_21 (E2, goods) to NO_SUJETA_LOCALIZACION (N2, services); regime_key drops from "02" (Export) back to the default "01".

F1 exempt operation (E1) — educational/medical

Operations exempt under Art. 20 LIVA (education, medical, social, insurance, residential rental). Set exemption_reason: EXENTA_ART_20, percentage: 0, and use exemption_reason_text to record the specific subparagraph.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Academia Cervantes SL",
      "nif": "A08001851",
      "address": {
        "street": "Calle Princesa",
        "number": "27",
        "postal_code": "28008",
        "city": "Madrid",
        "province": "Madrid",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Clases particulares de matemáticas — trimestre primavera",
        "quantity": 36,
        "unit": "hours",
        "unit_price": 28.00,
        "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
        "exemption_reason": "EXENTA_ART_20",
        "exemption_reason_text": "Operación exenta de IVA según Art. 20.Uno.10º LIVA (enseñanza)"
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Academia Cervantes SL",
    "nif": "A08001851",
    "address": {
      "street": "Calle Princesa",
      "number": "27",
      "postal_code": "28008",
      "city": "Madrid",
      "province": "Madrid",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Clases particulares de matemáticas — trimestre primavera",
      "quantity": 36,
      "unit": "hours",
      "unit_price": 28.00,
      "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
      "exemption_reason": "EXENTA_ART_20",
      "exemption_reason_text": "Operación exenta de IVA según Art. 20.Uno.10º LIVA (enseñanza)"
    }
  ],
  "options": { "issue_directly": true }
}

exemption_reason_text is free-text (max 500 chars). It's shown on the PDF and persisted on the registro VeriFactu, but doesn't change AEAT classification.

F1 with IGIC (Canary Islands)

Canary Islands operations use IGIC instead of IVA. Switch main_tax.type to "IGIC" and pick a valid IGIC rate (0, 3, 5, 7, 9.5, 15, 20).

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Importaciones Atlántico SL",
      "nif": "A08001851",
      "address": {
        "street": "Calle León y Castillo",
        "number": "200",
        "postal_code": "35004",
        "city": "Las Palmas de Gran Canaria",
        "province": "Las Palmas",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Mobiliario de oficina — sillas ergonómicas",
        "quantity": 10,
        "unit": "unit",
        "unit_price": 180.00,
        "main_tax": { "type": "IGIC", "percentage": 7, "regime_key": "01" }
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Importaciones Atlántico SL",
    "nif": "A08001851",
    "address": {
      "street": "Calle León y Castillo",
      "number": "200",
      "postal_code": "35004",
      "city": "Las Palmas de Gran Canaria",
      "province": "Las Palmas",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Mobiliario de oficina — sillas ergonómicas",
      "quantity": 10,
      "unit": "unit",
      "unit_price": 180.00,
      "main_tax": { "type": "IGIC", "percentage": 7, "regime_key": "01" }
    }
  ],
  "options": { "issue_directly": true }
}

IPSI (Ceuta and Melilla) works identically: main_tax.type: "IPSI" with one of its rates (0.5, 1, 2, 4, 8, 10). See Territorial taxes for the full picture.

F1 not subject (N1)

Operations not subject to IVA under the general rules of Art. 7 LIVA — internal transfers between branches, samples for promotion, out-of-scope operations. Use exemption_reason: NO_SUJETA_ART_7_9 and percentage: 0.

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Distribuciones Hermanas Pérez SL",
      "nif": "A08001851",
      "address": {
        "street": "Polígono Industrial San Isidro",
        "number": "12",
        "postal_code": "46980",
        "city": "Paterna",
        "province": "Valencia",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Muestras comerciales sin valor — catálogo 2026",
        "quantity": 50,
        "unit": "unit",
        "unit_price": 12.00,
        "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
        "exemption_reason": "NO_SUJETA_ART_7_9",
        "exemption_reason_text": "Entrega de muestras gratuitas (Art. 7.4º LIVA)"
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Distribuciones Hermanas Pérez SL",
    "nif": "A08001851",
    "address": {
      "street": "Polígono Industrial San Isidro",
      "number": "12",
      "postal_code": "46980",
      "city": "Paterna",
      "province": "Valencia",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Muestras comerciales sin valor — catálogo 2026",
      "quantity": 50,
      "unit": "unit",
      "unit_price": 12.00,
      "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
      "exemption_reason": "NO_SUJETA_ART_7_9",
      "exemption_reason_text": "Entrega de muestras gratuitas (Art. 7.4º LIVA)"
    }
  ],
  "options": { "issue_directly": true }
}

F1 ISP — reverse charge (S2)

Inversión del sujeto pasivo: the buyer self-assesses the IVA instead of the seller charging it. Common cases: construction services subcontracted to a developer (ISP_ART_84_2_F), scrap metal deliveries (ISP_ART_84_2_E), and operations performed by non-established entities (ISP_ART_84_2_A).

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Promociones Inmobiliarias del Mediterráneo SA",
      "nif": "A46789012",
      "address": {
        "street": "Gran Vía Marqués del Turia",
        "number": "47",
        "postal_code": "46005",
        "city": "Valencia",
        "province": "Valencia",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Ejecución de obra — instalación eléctrica edificio Torre Norte",
        "quantity": 1,
        "unit": "project",
        "unit_price": 42000.00,
        "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
        "exemption_reason": "ISP_ART_84_2_F",
        "exemption_reason_text": "Inversión del sujeto pasivo — Art. 84.Uno.2º.f LIVA (ejecución de obra)"
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Promociones Inmobiliarias del Mediterráneo SA",
    "nif": "A46789012",
    "address": {
      "street": "Gran Vía Marqués del Turia",
      "number": "47",
      "postal_code": "46005",
      "city": "Valencia",
      "province": "Valencia",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Ejecución de obra — instalación eléctrica edificio Torre Norte",
      "quantity": 1,
      "unit": "project",
      "unit_price": 42000.00,
      "main_tax": { "type": "IVA", "percentage": 0, "regime_key": "01" },
      "exemption_reason": "ISP_ART_84_2_F",
      "exemption_reason_text": "Inversión del sujeto pasivo — Art. 84.Uno.2º.f LIVA (ejecución de obra)"
    }
  ],
  "options": { "issue_directly": true }
}

ISP lines must never carry equivalence_surcharge_rate — the buyer self-assesses the full tax, so the recargo cannot apply. BeeL rejects the combination at validation time.

F1 REBU (used goods, art, antiques)

Régimen especial de bienes usados: the base imponible is the margin (sale price − purchase price), but the invoice total is the full sale price. Use regime_key: "03" and pre-compute the base, cuota, and total to match the margin.

Worked example. Sale 3 000 €, cost 2 000 €, margin 1 000 €. The base = 1 000 / 1.21 = 826.45 €; cuota = 173.55 €; the invoice total remains 3 000 €. You express this by setting unit_price to the base (826.45) and adding an explanatory description — BeeL relaxes the totals reconciliation when regime_key is "03".

curl -X POST "https://app.beel.es/api/v1/invoices" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "STANDARD",
    "recipient": {
      "legal_name": "Galería de Arte Velázquez SL",
      "nif": "A08001851",
      "address": {
        "street": "Calle de Jorge Juan",
        "number": "12",
        "postal_code": "28001",
        "city": "Madrid",
        "province": "Madrid",
        "country": "España",
        "country_code": "ES"
      }
    },
    "lines": [
      {
        "description": "Pintura óleo siglo XIX — REBU (margen): venta 3 000 € / coste 2 000 €",
        "quantity": 1,
        "unit": "unit",
        "unit_price": 826.45,
        "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "03" }
      }
    ],
    "notes": "Régimen especial de bienes usados (Art. 135 LIVA). Base imponible calculada sobre el margen.",
    "options": { "issue_directly": true }
  }'
{
  "type": "STANDARD",
  "recipient": {
    "legal_name": "Galería de Arte Velázquez SL",
    "nif": "A08001851",
    "address": {
      "street": "Calle de Jorge Juan",
      "number": "12",
      "postal_code": "28001",
      "city": "Madrid",
      "province": "Madrid",
      "country": "España",
      "country_code": "ES"
    }
  },
  "lines": [
    {
      "description": "Pintura óleo siglo XIX — REBU (margen): venta 3 000 € / coste 2 000 €",
      "quantity": 1,
      "unit": "unit",
      "unit_price": 826.45,
      "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "03" }
    }
  ],
  "notes": "Régimen especial de bienes usados (Art. 135 LIVA). Base imponible calculada sobre el margen.",
  "options": { "issue_directly": true }
}

R1 corrective — partial (by differences)

The most common rectification. Apply a delta to a previously issued invoice — quantities can be positive or negative. The URL points to the original invoice; the body describes only the change. The original status flips to RECTIFIED.

curl -X POST "https://app.beel.es/api/v1/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/corrective" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8b9c2e44-bbcd-4f23-9a01-1c3d5e7f9a02" \
  -d '{
    "rectification_type": "PARTIAL",
    "rectification_code": "R1",
    "reason": "Descuento comercial post-emisión acordado con el cliente (5 horas no facturables)",
    "lines": [
      {
        "description": "Ajuste por horas no facturables — Sprint mayo",
        "quantity": -5,
        "unit": "hours",
        "unit_price": 75.00,
        "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
      }
    ],
    "options": { "issue_directly": true }
  }'
{
  "rectification_type": "PARTIAL",
  "rectification_code": "R1",
  "reason": "Descuento comercial post-emisión acordado con el cliente (5 horas no facturables)",
  "lines": [
    {
      "description": "Ajuste por horas no facturables — Sprint mayo",
      "quantity": -5,
      "unit": "hours",
      "unit_price": 75.00,
      "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
    }
  ],
  "options": { "issue_directly": true }
}

The quantity: -5 produces a negative line — that's the canonical "por diferencias" pattern. See Corrective invoices for when to pick PARTIAL vs TOTAL and which code (R1–R4) applies to your case.

R5 corrective — total on simplified F2

R5 is reserved for rectifying SIMPLIFIED invoices. The common pattern: a customer asks for a "proper" F1 after you already issued an F2. You do it in two steps — first cancel the F2 with an R5 TOTAL, then issue a brand-new F1.

curl -X POST "https://app.beel.es/api/v1/invoices/9f8e7d6c-5b4a-3210-fedc-ba9876543210/corrective" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "rectification_type": "TOTAL",
    "rectification_code": "R5",
    "reason": "Cliente solicita factura completa (F1) con sus datos fiscales tras emitir tique simplificado"
  }'
{
  "rectification_type": "TOTAL",
  "rectification_code": "R5",
  "reason": "Cliente solicita factura completa (F1) con sus datos fiscales tras emitir tique simplificado"
}

What changes vs. the previous example: rectification_type flips from PARTIAL to TOTAL, rectification_code from R1 to R5, and lines are omitted — for TOTAL rectifications BeeL copies the original lines and negates them automatically. The original F2 becomes VOIDED; you then create a fresh F1 with the right recipient data via the standard POST /v1/invoices.

Voiding (anulación)

If the operation never happened — duplicate emission, wrong customer, test invoice escaped to production — use the void endpoint, not a corrective. Voiding is for "this invoice should not exist"; corrective is for "this invoice exists but the numbers are wrong".

curl -X POST "https://app.beel.es/api/v1/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/void" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Factura emitida por error sobre un cliente equivocado (operación nunca realizada)",
    "void_date": "2026-05-20"
  }'
{
  "reason": "Factura emitida por error sobre un cliente equivocado (operación nunca realizada)",
  "void_date": "2026-05-20"
}

The invoice flips to VOIDED and, if VeriFactu was enabled, the anulación is sent to AEAT automatically. void_date defaults to today if omitted. See Cancel and fix for the decision tree between void and corrective.

What's NOT in this cookbook

A handful of AEAT scenarios are technically valid but not yet exposed in BeeL's public API. They live in the Scope and limitations page when you need to know what's blocked:

  • Autofactura (tipo D) — issued by the buyer on behalf of the seller. BeeL only emits invoices from the issuer's own series.
  • Facturación por terceros (tipo T) — third-party issuance (e.g. agency invoicing for a client). Requires an explicit delegation flow that BeeL doesn't model yet.
  • F3 sustitutiva — replacing a previously issued F2 with an F1 in a single AEAT record. BeeL's workaround is the R5 TOTAL + new F1 pattern shown above.
  • Facturas de abono standalone — credit notes not tied to an original invoice. BeeL only issues credit-style operations as CORRECTIVE against an existing factura.
  • Subsanación pública (AEAT-side correction endpoint) — AEAT exposes a path to fix a registro after submission without issuing a rectificativa, used in narrow cases (e.g. wrong hash chain). BeeL handles this internally on auto-submit retries; it's not exposed to integrators.

If your use case falls in any of these, open a ticket with the AEAT scenario and a sample payload — most of them are on the roadmap.