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/companies/{company_id}/invoices and assume your account has VeriFactu enabled. Sandbox keys (beel_sk_test_*) submit to AEAT pre-production and don't consume quota.
None of them send an issue date: BeeL. sets issue_date to the day the invoice is actually issued, when its billing record is generated. To record an operation that happened earlier, send operation_date (today or a past date). To issue on a future date, create a draft and use PUT /v1/companies/{company_id}/invoices/{invoice_id}/schedule.
Quick reference
| Scenario | type | exemption_reason | regime_key | Surcharge | Recipient |
|---|---|---|---|---|---|
| F2 simplified — under the cap, no recipient | SIMPLIFIED | — | "01" | — | omitted |
| F1 standard — Spanish B2B | STANDARD | — | "01" | — | NIF + address |
| F1 multiple VAT rates | STANDARD | — | "01" | — | NIF + address |
| F1 with IRPF | STANDARD | — | "01" | — | NIF + address |
| F1 equivalence surcharge | STANDARD | — | "18" | 5.2 | NIF + address |
| F1 intra-EU B2B goods (E5) | STANDARD | EXENTA_ART_25 | "01" | — | NIF_IVA |
| F1 intra-EU B2B services (N2) | STANDARD | NO_SUJETA_LOCALIZACION | "01" | — | NIF_IVA |
| F1 B2C OSS over threshold | STANDARD | — (regime key alone → N2) | "17" | — | PASSPORT |
| F1 B2C under threshold | STANDARD | — | "01" | — | PASSPORT |
| F1 export non-EU (E2) | STANDARD | EXENTA_ART_21 | "02" | — | PASSPORT |
| F1 services non-EU (N2) | STANDARD | NO_SUJETA_LOCALIZACION | "01" | — | PASSPORT |
| F1 exempt E1 (medical/edu) | STANDARD | EXENTA_ART_20 | "01" | — | NIF + address |
| F1 IGIC (Canary Islands) | STANDARD | — | "01" | — | NIF + address |
| F1 not subject (N1) | STANDARD | NO_SUJETA_ART_7_9 | "01" | — | NIF + address |
| F1 ISP — reverse charge (S2) | STANDARD | ISP_ART_84_2_F | "01" | — | NIF + address |
| F1 REBU (used goods) | not accepted | — | "03" | — | — |
| R1 corrective — partial | (corrective) | — | "01" | — | inherited |
| R5 corrective — return on F2 | (corrective) | — | "01" | — | none, like the F2 |
| Voiding | n/a | — | — | — | n/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 the cap, no recipient
The bread-and-butter ticket invoice. Use SIMPLIFIED when the total stays under 3,000 €, the customer is a consumer, and you don't identify them. A SIMPLIFIED invoice with a nif or alternative_id in recipient is rejected (SIMPLIFIED_INVOICE_FORBIDS_IDENTIFIED_RECIPIENT) — identify the customer and it is an F1. 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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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 € cap, the 400 € limit that is your responsibility, and why BeeL. always issues an identified customer's invoice as an F1.
F1 standard — Spanish business customer
The default B2B invoice between two Spanish entities. The recipient needs a Spanish NIF, which BeeL. checks against the AEAT census together with the name.
curl -X POST "https://app.beel.es/api/v1/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 4a7d1ed4-9bc9-4f7e-b1e9-7c2a5f9b8d11" \
-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": "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",
"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 record.
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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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, 2.8, 6, 7, 7.6, 9.5, 15, 19 or 24 (IrpfPercentage enum) — for general professional activity it's almost always 15 (or 7 during the first three years of activity). The issuer here is an individual professional: a company issuer only bears 0, 19, 24 and 9.5, and any other rate is rejected with 422 IRPF_RATE_NOT_FOR_CORPORATE_ISSUER (see Amounts and rounding).
curl -X POST "https://app.beel.es/api/v1/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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 }
}BeeL. never accepts IRPF on SIMPLIFIED invoices: a simplified invoice issued through BeeL. does not identify its recipient, and a withholding is made by an identified payer. If your customer withholds, issue an F1. See Simplified vs standard.
F1 with equivalence surcharge
For retailers 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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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, 10 ↔ 1.4, 21 ↔ 5.2 (and 21 ↔ 1.75 for tobacco); the temporary rates have their own pairs, accepted only on operations of their period. 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. checks that the German VAT-ID has the DE structure; whether it is active in VIES is for you to check before invoicing — see International customers.
curl -X POST "https://app.beel.es/api/v1/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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 not subject by place of supply (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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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" and the destination country's rate — 19 % for Germany below. The regime key widens the accepted rates beyond the Spanish menu, and it alone classifies the line as N2, so the line takes no exemption_reason: adding one would force the rate to 0 % and drop the destination IVA from the breakdown.
curl -X POST "https://app.beel.es/api/v1/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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": 19, "regime_key": "17" }
}
],
"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": 19, "regime_key": "17" }
}
],
"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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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 not subject by place of supply — 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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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 VeriFactu record, 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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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)
Reverse charge (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_C), and operations performed by non-established entities (ISP_ART_84_2_A).
curl -X POST "https://app.beel.es/api/v1/companies/{company_id}/invoices" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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 surcharge cannot apply. BeeL. rejects the combination at validation time.
F1 REBU (used goods, art, antiques)
Not accepted: a line with regime_key: "03" is rejected with 422 REGIME_KEY_NOT_SUPPORTED. Under the used-goods regime the invoice must not show the tax separately (RD 1619/2012, art. 16.2.c), and a BeeL. invoice always does. See Regime keys.
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/companies/{company_id}/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/corrective" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-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 "by differences" pattern. See Corrective invoices for when to pick PARTIAL vs TOTAL and which code (R1–R4) applies to your case.
R5 corrective — return on simplified F2
R5 is reserved for rectifying SIMPLIFIED invoices, whatever the cause. The common case: the customer returns one of the items on the ticket.
curl -X POST "https://app.beel.es/api/v1/companies/{company_id}/invoices/9f8e7d6c-5b4a-3210-fedc-ba9876543210/corrective" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"rectification_type": "PARTIAL",
"rectification_code": "R5",
"reason": "El cliente devolvió uno de los dos artículos del tique",
"lines": [
{
"description": "Devolución - camiseta talla M",
"quantity": -1,
"unit_price": 16.53,
"main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
}
]
}'{
"rectification_type": "PARTIAL",
"rectification_code": "R5",
"reason": "El cliente devolvió uno de los dos artículos del tique",
"lines": [
{
"description": "Devolución - camiseta talla M",
"quantity": -1,
"unit_price": 16.53,
"main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" }
}
]
}What changes vs. the previous example: rectification_code goes from R1 to R5, and, like the F2, the R5 reaches AEAT without recipient data. A customer who asks for an invoice with their details after a ticket is not a correction: nothing in the ticket is wrong, so that is not an R5 but an exchange of the simplified invoice.
Voiding
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/companies/{company_id}/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/void" \
-H "Authorization: Bearer $BEEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Duplicado de la factura F-2026-0142, emitida dos veces por error",
"issued_in_error": true
}'{
"reason": "Duplicado de la factura F-2026-0142, emitida dos veces por error",
"issued_in_error": true
}The invoice flips to VOIDED and, if AEAT had accepted its registration, the cancellation record is sent automatically; if the registration never reached AEAT, nothing is sent. issued_in_error: true confirms the invoice was issued by mistake: it is required once the invoice has been sent or paid (VOID_REQUIRES_ISSUED_IN_ERROR). See Cancel and fix for the decision tree between void and corrective.