BeeL
Get StartedVeriFactuStripeAPI Reference

Changelog

Track all updates to the BeeL. API.


Feature

Read your API request logs

A new Request Logs endpoint family lets you inspect the requests your own API keys have made (live + test) — method, path, status, timing, and the full request/response detail — so you can correlate and debug integrations without leaving your stack.

  • GET /v1/developers/request-logs — list your past API requests, cursor-paginated. Filter by environment (live/test), only_errors, method, http_status, path_contains, api_key_id, and a from/to time range. By default the last 30 days are returned.
  • GET /v1/developers/request-logs/{request_id} — full detail of a single request, including request/response bodies and headers. Pass the optional timestamp hint (the value from the list) to look up logs older than the default window.
  • Cursor pagination — navigate with the opaque next_cursor / prev_cursor returned in each response; has_next / has_previous tell you when you've reached the edges.
  • Correlate with X-Request-Id — each log's request_id matches the X-Request-Id response header (and meta.request_id), so you can jump straight from a live response to its full log.
  • Works with your existing API key (Authorization: Bearer) — no extra scope required.
  • GET/v1/developers/request-logsList your API request logs (cursor-paginated, filterable by environment, status, method, path, key and time range)
  • GET/v1/developers/request-logs/{request_id}Get the full detail (bodies + headers) of a single request log
Feature

BeeL CLI — run the API from your terminal

The official BeeL CLI is now published on npm as @beel_es/cli. Run any API endpoint straight from the terminal — sandbox by default — with nothing to install thanks to npx. Commands are derived at runtime from the OpenAPI spec bundled with the installed version, so the CLI always matches the API surface of that release.

  • Zero-install with npx @beel_es/cli — or npm install -g @beel_es/cli for a global beel command. Runs against sandbox by default.
  • Every endpoint is a commandbeel commands lists them and --help at any level shows flags, enums, defaults and body fields, all derived from the spec, so there's no hand-maintained list to drift.
  • Agent-first — authenticate with an env var (ideal for agents/CI) or a ~/.config/beel/config.json (chmod 600), with a structured output contract that's easy to parse.
  • Generic escape hatch — call any endpoint the installed version doesn't know yet; update the CLI to pick up newly added endpoints as new commands.
  • Search the docs from the terminal without leaving your shell.
Feature

Node.js / TypeScript SDK now available

The official BeeL SDK for Node.js and TypeScript is now published on npm as @beel_es/sdk. It is fully typed from the OpenAPI spec, with automatic retries, idempotency keys, typed errors, and webhook signature verification built in.

  • Install with npm install @beel_es/sdk — Node.js 18+, ships both ESM and CommonJS with a single runtime dependency.
  • Fully-typed client auto-generated from the OpenAPI spec — invoices, customers, products, configuration, series, and NIF validation.
  • Automatic retries with exponential backoff on 429 and 5xx, plus auto idempotency keys on every POST so retries never create duplicates.
  • Typed errors — catch BeeLNotFoundError, BeeLValidationError, and friends instead of checking status codes.
  • Webhook signature verification with HMAC-SHA256 and PDF download as a Buffer.
ImprovementBreaking

API v1.3.0 — contract fixes: flexible idempotency keys, optional country, HTTPS-only webhooks

Contract-correctness wave from an API test pass. Idempotency keys no longer have to be UUIDs, address country becomes optional, webhook endpoints must be HTTPS, and several error responses are now more accurate (correct codes, correct status, and a previously-opaque 500 turned into an actionable 422).

  • Idempotency-Key accepts any unique string — not just a UUID. Any client-generated key matching ^[a-zA-Z0-9_-]{1,255}$ works (e.g. invoice-order-12345). UUIDs still work but are no longer required. Previously a non-UUID key was rejected with 422.
  • address.country is now optionalcountry_code (ISO 3166-1 alpha-2) is the canonical field. If you omit country it defaults to the country name; you only need to send country_code.
  • X-Request-Id response header — every response now carries X-Request-Id, matching meta.request_id in the body, so you can correlate logs without parsing the payload.
  • POST /v1/companies returns a clear 403 — when multi-NIF isn't available on your plan it now responds 403 MULTI_NIF_NOT_ENABLED instead of a misleading 404 COMPANY_NOT_FOUND on a creation endpoint.
  • Series with an unknown format variable now fails cleanlyPOST /v1/configuration/series with an unrecognized {VARIABLE} returns 422 SERIES_FORMAT_UNRECOGNIZED_VARS with the standard error envelope, instead of an opaque empty 500.
  • Consistent error code for alternative IDs — the wire error code is now ALTERNATIVE_ID_INVALID (matching the published catalog), not an internal Spanish variant.
  • Webhook endpoints must be HTTPSPOST /v1/webhooks (and updates) now reject http:// URLs with 422 WEBHOOK_URL_MUST_BE_HTTPS. Signed fiscal payloads are never delivered in cleartext. Re-register any non-HTTPS endpoint over HTTPS.
  • Customers can't carry both nif and alternative_id — sending both on POST /v1/customers now returns 422 ALTERNATIVE_ID_AND_NIF_EXCLUSIVE. Previously the alternative_id was silently dropped and only the NIF kept. Send exactly one identifier.
  • POST /v1/companies status changed 404 → 403 — clients branching on 404 COMPANY_NOT_FOUND for the multi-NIF-unavailable case must switch to 403 MULTI_NIF_NOT_ENABLED.
  • POST/v1/companiesReturns 403 MULTI_NIF_NOT_ENABLED (was 404) when multi-NIF is not available on the plan
Improvement

Renamed the active-company header

The request header that selects which company a request operates on has been renamed from X-Active-Profile to Beel-Active-Company.

  • Send Beel-Active-Company: <company_id> to scope a request to a specific company.
  • The previous X-Active-Profile header keeps working during a deprecation grace period, so you can migrate at your own pace.
  • While you still send the old header, responses include a Deprecation: true header and a Link: …; rel="deprecation" pointing to this entry. Switch to Beel-Active-Company to clear it.
ImprovementBreaking

API v1.2.0 — VeriFactu validation pack, public error catalog, metadata filters, RD-ley rates, BIZUM

Third wave of VeriFactu compliance hardening: invalid fiscal combinations are now rejected at request time with specific 422s, a public error-code catalog is available at docs.beel.es with stable per-code pages, Stripe-style metadata filtering on the invoices list, RD-ley 11/2022 temporary rates (5% IVA + 0.625% recargo de equivalencia), BIZUM as a new payment method, and several Stripe Connect refinements.

  • VeriFactu validation pack — incompatible fiscal combinations now fail with a specific 422 before the registro de facturación is built: SIMPLIFICADA combined with cross-border / IRPF / ISP, ISP carrying recargo de equivalencia, OSS regime + ISP exemption, 0% IVA lines without an explicit reason, regimes / exemption articles that are currently unsupported. Each case returns its own error code so you can branch on it.
  • Public error-code catalog at docs.beel.es/errors/{code} — every code that an API-key integrator can receive now has a stable, deep-linkable page. The type URI in error responses resolves there directly. The catalog covers 199 codes across 8 domains; codes that only surface from the web app are deliberately kept out.
  • metadata[key]=value filter on GET /v1/invoices — Stripe-style deepObject filtering. Multiple pairs are AND'd together. Up to 50 pairs per request; keys must match ^[A-Za-z0-9_\-.]{1,64}$. Example: ?metadata[external_order_id]=ORD-42&metadata[tenant]=acme.
  • New 5% VAT rate (RD-ley 11/2022)VatPercentage now accepts 5 as a valid temporary reduced rate alongside 0, 4, 10 and 21.
  • New 0.625% recargo de equivalenciaEquivalenceSurchargePercentage adds 0.625, the surcharge that pairs with 5% VAT under RD-ley 11/2022. Documented allowed pairings: 4 ↔ 0.5, 5 ↔ 0.625, 10 ↔ 1.4, 21 ↔ 5.2.
  • BIZUM as a payment methodpayment_info.method now accepts BIZUM. Returned in responses and accepted on POST/PUT /v1/invoices.
  • Clearer error when scheduling an ORDINARIA invoice without a recipient identifier — now returns 422 with a specific, actionable message instead of the previous generic validation error.
  • PDF includes the VeriFactu QR consistently — the downloaded PDF now always carries the VeriFactu QR when the invoice has one (previously a race could ship a PDF without it).
  • Stripe Connect refinements — forward and corrective invoices generated from Stripe now mirror the exact Stripe charge total (no recalculation). SIMPLIFICADA invoices preserve the Stripe customer's name/email instead of falling back to Consumidor final. The cross-border alternative-ID gap is closed.
  • Stricter VeriFactu validation rejects previously-accepted invoices — invoices that combined incompatible options (ISP + recargo de equivalencia, OSS + ISP exemption, SIMPLIFICADA + IRPF, 0% IVA without reason, etc.) used to pass the request and fail later. They now fail with 422 and a specific code at request time. Re-test integrations that exercise edge-case fiscal combinations.
  • VatPercentage schema type widened from integer to number — all currently allowed values are still whole numbers (0, 4, 5, 10, 21), so wire-level responses do not change. Strongly-typed SDK clients generated from the OpenAPI spec (Java, C#, Go) should regenerate to pick up the new schema type; loose clients (JavaScript, Python without strict typing) need no changes.
  • payment_info.method = BIZUM may be returned where it previously wasn't — clients that exhaustively switch on method should add a BIZUM branch (or a default arm).
  • lines[].iva_rate = 5.00 may now be returned — same as above for clients enumerating known rates.
  • GET/v1/invoicesAdded `metadata[key]=value` query parameter (deepObject) for filtering by metadata pairs
FeatureBreaking

API v1.2.0 — Metadata filter on invoices, RD-ley 11/2022 reduced rates (5% IVA / 0.625% RE)

GET /v1/invoices now accepts Stripe-style metadata filtering, and tax schemas add the RD-ley 11/2022 temporary rates (5% IVA paired with 0.625% recargo de equivalencia). The VatPercentage schema type widens from integer to number.

  • Metadata filter on GET /v1/invoices — Filter by any metadata key/value pair using ?metadata[key]=value (deepObject style). Multiple keys are AND'd together. Up to 50 pairs per request; keys must match ^[A-Za-z0-9_\-.]{1,64}$. Example: ?metadata[external_order_id]=ORD-42&metadata[tenant]=acme.
  • New 5% VAT rate (RD-ley 11/2022) — The VatPercentage enum accepts 5 as a valid temporary reduced rate alongside 0, 4, 10 and 21.
  • New 0.625% recargo de equivalenciaEquivalenceSurchargePercentage adds 0.625, the surcharge that pairs with 5% VAT under RD-ley 11/2022. The schema description now documents every allowed pairing explicitly: 4↔0.5, 5↔0.625, 10↔1.4, 21↔5.2.
  • VatPercentage schema type widened from integer to number — All currently allowed values are still whole numbers (0, 4, 5, 10, 21), so wire-level responses do not change. Strongly-typed SDK clients generated from the OpenAPI spec (Java, C#, Go) should regenerate to pick up the new schema type; loose clients (JavaScript, Python without strict typing) need no changes.
  • GET/v1/invoicesAdded `metadata[key]=value` query parameter (deepObject) for filtering by metadata pairs
Breaking

API v1.1.0 — Refactored invoice recipient & payment_info, new series defaults

Invoice recipient and payment_info schemas have been refactored to use structured objects with allOf composition. This change normalizes the API and enables future extensibility. Also adds new series defaults endpoints.

  • Structured recipient and payment_info — PUT /v1/invoices/{invoice_id} now uses allOf composition with PaymentInfo and Recipient schemas. Fields like nif, legal_name, iban, method are still available via the referenced schemas, but the structure changed from inline to composed. Regenerate your SDK if you use one.
  • New series defaults endpoints — POST /v1/configuration/series/defaults and GET /v1/configuration/series/defaults-status allow setting and checking per-document-type default series.
  • Idempotency-Key header — Now formally documented on POST /v1/customers.
  • Invoice email options — All invoice endpoints now return email_config and send_automatically fields in responses.
  • PUT /v1/invoices/{invoice_id} schema changerecipient and payment_info now use allOf composition referencing Recipient and PaymentInfo schemas. The fields (nif, legal_name, iban, method, etc.) remain available but the schema path changed from inline properties to a $ref. Clients using generated SDKs may need to regenerate.
  • SDK regeneration recommended — If you use generated clients from the OpenAPI spec, regenerate them to pick up the new schema references. The underlying fields are the same; only the structure (and how the SDK types represent them) has changed.
  • PUT/v1/invoices/{invoice_id}recipient and payment_info now use allOf composition — update your request payload structure
  • POST/v1/configuration/series/defaultsSet default series per document type
  • GET/v1/configuration/series/defaults-statusCheck which series have defaults configured
Breaking

API v1.1.0 — Refactored invoice recipient & payment_info, new series defaults

Invoice recipient and payment_info schemas have been refactored to use structured objects with allOf composition. This change normalizes the API and enables future extensibility. Also adds new series defaults endpoints.

  • Structured recipient and payment_info — PUT /v1/invoices/{invoice_id} now uses allOf composition with PaymentInfo and Recipient schemas. Fields like nif, legal_name, iban, method are still available via the referenced schemas, but the structure changed from inline to composed. Regenerate your SDK if you use one.
  • New series defaults endpoints — POST /v1/configuration/series/defaults and GET /v1/configuration/series/defaults-status allow setting and checking per-document-type default series.
  • Idempotency-Key header — Now formally documented on POST /v1/customers.
  • Invoice email options — All invoice endpoints now return email_config and send_automatically fields in responses.
  • PUT /v1/invoices/{invoice_id} schema changerecipient and payment_info now use allOf composition referencing Recipient and PaymentInfo schemas. The fields (nif, legal_name, iban, method, etc.) remain available but the schema path changed from inline properties to a $ref. Clients using generated SDKs may need to regenerate.
  • SDK regeneration recommended — If you use generated clients from the OpenAPI spec, regenerate them to pick up the new schema references. The underlying fields are the same; only the structure (and how the SDK types represent them) has changed.
  • PUT/v1/invoices/{invoice_id}recipient and payment_info now use allOf composition — update your request payload structure
  • POST/v1/configuration/series/defaultsSet default series per document type
  • GET/v1/configuration/series/defaults-statusCheck which series have defaults configured
ImprovementBreaking

API v1.0.3 — VeriFactu exemptions, document types, stricter validations

Second round of VeriFactu compliance improvements: invoice lines can now carry an explicit exemption reason, the tax-types endpoint exposes the full LIVA exemption catalog, invoice series can be typed, and the id_otro VeriFactu rules are now enforced with specific error messages.

  • Invoice line exemption reasonsexemption_reason (enum covering EXENTA_ART_*, NO_SUJETA_*, ISP_ART_84_2_*, REGIMEN_ART_* and OTRO) and the free-text exemption_reason_text are now accepted and returned on invoice lines. Required by VeriFactu whenever a line is exempt or not-subject.
  • Exemption reasons catalogGET /v1/configuration/tax-types returns the full LIVA exemption catalog so integrators can build UIs without hardcoding the list.
  • Typed invoice series — new document_type on /v1/configuration/series (request, response and list query filter), so you can segregate series for invoices, corrective invoices, etc.
  • Descriptive alternative ID typesid_otro.type now accepts PASSPORT, COUNTRY_ID, NIF_IVA, RESIDENCE_CERTIFICATE, OTHER_DOCUMENT, NOT_REGISTERED alongside the legacy numeric codes 0207 (still valid, now deprecated).
  • VeriFactu id_otro rules enforced at the boundary — if country_code = ES the type must be PASSPORT (03) or NOT_REGISTERED (07); if type = NOT_REGISTERED the country_code must be ES. Violations return 422 with a specific message per rule (previously a generic "identificador alternativo no es válido").
  • irpf_rate enum21.00 is removed and 1.00 is added on lines[].irpf_rate (POST/PUT /v1/invoices, POST /v1/invoices/{invoice_id}/corrective) and on default_irpf_rate (PUT /v1/configuration/taxes). 21% IRPF is not a valid withholding rate for the flows Beel supports.
  • template_html removed — the template_types[].template_html property no longer ships in GET /v1/configuration/invoice-customization-options. PDF templates are owned and rendered by the backend; clients should not inspect the raw HTML.
  • Stricter NIF patternPOST/PUT /v1/customers and POST /v1/customers/bulk now validate nif against the full DNI/NIE/CIF regex ^(\d{8}[A-Z]|[ABCDEFGHJKLMNPQRSUVW]\d{7}[A-Z0-9]|[XYZ]\d{7}[A-Z])$ instead of the permissive ^[A-Z0-9]{9}$. Previously-accepted but invalid strings (e.g. ABCDEFGHI) will now be rejected.
Improvement

API v1.0.1 — VeriFactu operation_date & spec improvements

This release aligns the API with Spanish anti-fraud law (Ley Antifraude / VeriFactu) requirements for invoice dates. The issue_date is now always set to today and a new operation_date field lets you record when the operation actually took place.

  • New operation_date field on invoices — use when invoicing for a past operation (e.g., services delivered last month but invoiced this month)
  • issue_date is now read-only and always set to today per VeriFactu regulations
  • issue_date removed from required fields in CreateInvoiceRequest
  • Duplicate invoice no longer accepts a custom issue_date — duplicates are always dated today
  • Idempotency header renamed from X-Idempotency-Key to Idempotency-Key (standard naming)
  • Improved due_date documentation — must be same as or after today's date
  • New start_date field on recurring invoice creation
  • POST/v1/invoicesoperation_date replaces issue_date in request body
  • PUT/v1/invoices/{invoice_id}operation_date (nullable) replaces issue_date
  • POST/v1/invoices/{invoice_id}/duplicateissue_date param removed from request
Release

BeeL API v1.0 — Public Launch

The BeeL API is now publicly available. Full REST API for invoicing, customer management, products, tax configuration, and VeriFactu compliance — all with a 7-day free trial.

  • Complete invoice lifecycle: create, issue, send, pay, void, and correct
  • Customer and product catalog management with bulk operations
  • VeriFactu compliance with automatic AEAT submission
  • Webhook notifications for invoice and VeriFactu events
  • Idempotency support for safe retries on all creation endpoints
  • Sandbox environment with unlimited invoices for testing
  • OpenAPI 3.0 specification for client generation in any language