---
title: "Create a company"
method: POST
path: "/v1/accounts/{account_id}/companies"
tags: ["AccountCompanies"]
---

# Create a company

`POST /v1/accounts/{account_id}/companies`

## Request

- Base URL: `https://app.beel.es/api`
- URL: `https://app.beel.es/api/v1/accounts/{account_id}/companies`
- Auth: HTTP bearer

Creates a company under the account the request resolves to. The NIF is
registered in the name of that account's holder, never in the name of the caller.

- **`activate`:** unless it is `false`, the company is switched on in
  `aeat_environment` and its three default invoice series (ordinary, simplified,
  corrective) are seeded there. This endpoint never switches an existing company on:
  that is `POST /v1/companies/{company_id}/activations`.
- **`numbering`:** decides the code, format, counter reset and starting number those
  series are born with. Only accepted when the request activates the company.
- **Billing:** no charge is ever started here. Creating a production NIF requires being
  the billing subject of the account (`403` otherwise), and an account without billing is
  rejected with `402`; no checkout is opened in either case.
- **Duplicates:** a NIF that already exists in the account is rejected with `409`, and
  the response carries the existing `error.details.company_id`.
- **Addresses:** a Spanish postal code (`country_code` omitted or `ES`) must have 5 digits,
  in `address` and in `legal_representative.address`; otherwise `422 POSTAL_CODE_INVALID_ES`
  and nothing is created. Other countries' postal codes are free-form.

## Headers

- `Idempotency-Key` string

## Request body

- CreateCompanyRequest
  - `nif` string, required: NIF/CIF of the business
  - `legal_name` string, required: Legal/fiscal name
  - `entity_type` 'INDIVIDUAL' | 'LEGAL_ENTITY', required: Taxpayer type. INDIVIDUAL: Natural person (individual self-employed). LEGAL_ENTITY: Legal entity (company with legal form: SL, SA, etc.).
  - `address` Address, required: Address you send when you create or update a company, a customer or an onboarding. A required field made only of whitespace passes the length checks below but leaves the address without that part, so it is rejected with `422`: `STREET_EMPTY`, `POSTAL_CODE_EMPTY`, `CITY_EMPTY` or `PROVINCE_EMPTY`. Addresses you read back are described by their own schema.
    - `street` string, required: Full address (street, number, floor, etc.) - Latin characters only
    - `number` string: Street number. Optional: omit it when the address has none, or when `street` already carries the address in full.
    - `floor` string: Floor or level
    - `door` string: Door or apartment
    - `postal_code` string, required: Postal code (5 digits for Spain, free format for other countries)
    - `city` string, required: City or town - Latin characters only
    - `province` string: Province or state - Latin characters only. Required for an address in Spain (`country_code` `ES`, or no country at all); optional elsewhere, where many addresses have none. A Spanish address without it is rejected with a `422`.
    - `country` string: Country of the address, as its ISO 3166-1 alpha-2 code (`GB`) or its official name in Spanish, English or Catalan (`Reino Unido`, `United Kingdom`, `Regne Unit`; case and accents are ignored). Anything else, such as `UK`, is rejected with `422 COUNTRY_CODE_REQUIRED`: send `country_code` instead. If it names a different country than `country_code`, `422 COUNTRY_CODE_MISMATCH` (`España` alone yields to a foreign `country_code`: it was the old default). What is stored and returned is always the Spanish name derived from the resulting code, never the text sent. With neither field present, the address is Spanish (`España`).
    - `country_code` string: ISO 3166-1 alpha-2 country code: the canonical field that decides the country of the address. It must be a real country code (`GB`, not `UK`); otherwise `422 COUNTRY_CODE_REQUIRED`. When it is omitted, the code comes from `country` (see there). With neither field present, the address is stored as `ES`.
  - `legal_form` string: Legal form (SL, SA, ...). Recommended for LEGAL_ENTITY.
  - `legal_representative` LegalRepresentative: Legal representative data for a legal entity. Only used when entity_type = LEGAL_ENTITY.
    - `full_name` string, required: Full name of the legal representative
    - `nif` string, required: Tax ID of the legal representative (DNI/CIF/NIE)
    - `address` object, required: Address of the legal representative
      - `street` string, required: Full address (street, number, floor, etc.) - Latin characters only
      - `number` string: Street number. Optional: omit it when the address has none, or when `street` already carries the address in full.
      - `floor` string: Floor or level
      - `door` string: Door or apartment
      - `postal_code` string, required: Postal code (5 digits for Spain, free format for other countries)
      - `city` string, required: City or town - Latin characters only
      - `province` string: Province or state - Latin characters only. Required for an address in Spain (`country_code` `ES`, or no country at all); optional elsewhere, where many addresses have none. A Spanish address without it is rejected with a `422`.
      - `country` string: Country of the address, as its ISO 3166-1 alpha-2 code (`GB`) or its official name in Spanish, English or Catalan (`Reino Unido`, `United Kingdom`, `Regne Unit`; case and accents are ignored). Anything else, such as `UK`, is rejected with `422 COUNTRY_CODE_REQUIRED`: send `country_code` instead. If it names a different country than `country_code`, `422 COUNTRY_CODE_MISMATCH` (`España` alone yields to a foreign `country_code`: it was the old default). What is stored and returned is always the Spanish name derived from the resulting code, never the text sent. With neither field present, the address is Spanish (`España`).
      - `country_code` string: ISO 3166-1 alpha-2 country code: the canonical field that decides the country of the address. It must be a real country code (`GB`, not `UK`); otherwise `422 COUNTRY_CODE_REQUIRED`. When it is omitted, the code comes from `country` (see there). With neither field present, the address is stored as `ES`.
  - `trade_name` string: Commercial/trade name (optional). When omitted or blank, the company is read back with `trade_name` equal to `legal_name`: the field always carries the name to display.
  - `default_main_tax` TaxInfo: Complete tax information with cross-validations: - IVA: real rates 4, 10, 21, and the temporary 2, 5 and 7.5 (see below for 0) - IGIC: 0, 3, 5, 7, 9.5, 15, 20 — here 0 is the real "Tipo Cero" - IPSI: real rates 0.5, 1, 2, 4, 8, 10 (see below for 0) - OTHER: any percentage between 0 and 100 **0 % under IVA and IPSI is not a rate, it is the exemption sentinel.** It is accepted on a line, but only together with an `exemption_reason` (exempt or non-subject operation); on its own it says nothing and the line is rejected. That is why `GET /v1/tax-types` publishes the IVA rates without 0: the legitimate way to a 0 % IVA line is through an exemption reason, which the same response also publishes. IGIC is different — its 0 % is a real legal rate (basic necessities) and needs no reason. **IVA 5 %** (the temporary rate applied from 2022 to electricity, gas and certain foodstuffs) is no longer in force for new operations. AEAT only accepts it on operations dated from 2022-07-01 to 2024-09-30: send the `operation_date` of that period, because without one the issue date decides and a line at 5 % is rejected with `422 VAT_RATE_NOT_ACCEPTED_ON_DATE`. Its equivalence surcharge pair is 0.5 up to 2022-12-31 and 0.62 from 2023-01-01. **IVA 2 % and 7.5 %** (temporary rates of the last quarter of 2024) are accepted only on operations dated from 2024-10-01 to 2024-12-31, with surcharges 0.26 and 1. Exception: when regime_key = "17" (OSS/IOSS) the invoice applies the destination country VAT instead of the Spanish one, so any percentage in the EU range [0, 27] is accepted regardless of the tax type set — including 0 without an exemption reason.
    - `type` 'IVA' | 'IGIC' | 'IPSI' | 'OTHER', required: Tax type by territory: - IVA: Iberian Peninsula and Balearic Islands (4%, 10%, 21%; 2%, 5% and 7.5% only on operations of their period) - IGIC: Canary Islands (0%, 3%, 5%, 7%, 9.5%, 15%, 20%) - IPSI: Ceuta and Melilla (0.5%, 1%, 2%, 4%, 8%, 10%) - OTHER: Configurable 0%-100% Under IVA and IPSI, 0% is not one of these rates: it is the exemption/non-subject sentinel and always travels with an `exemption_reason`. IGIC's 0% is a real rate. See `TaxInfo` for the full rules.
    - `percentage` number, required: Tax percentage
    - `regime_key` '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' | '09' | '10' | '11' | '14' | '15' | '17' | '18' | '19' | '20': Regime key according to VeriFactu regulations. Omitted, `01` (general regime) applies: - 01: General regime operation - 02: Export (IVA and IGIC; not IPSI, whose AEAT list is `01, 08, 11, 18, 19, 20`) - 03: Used goods, art, antiques (not accepted, see below) - 04: Investment gold - 05: Travel agencies - 06: Group of entities (not accepted, see below) - 07: Cash basis - 08: Operation subject to another indirect tax — IPSI or IGIC on an IVA line, IPSI or IVA on an IGIC line. It is **not** the general regime of IGIC, which is `01`. - 09: Mediating agencies - 10: Third-party collections - 11: Local rental - 14: VAT pending in certifications (not accepted, see below) - 15: VAT pending successive tract - 17: OSS and IOSS - 18: Equivalence surcharge - 19: REAGYP - 20: Simplified regime **What AEAT requires with each key** (Validaciones VERI*FACTU 3.1.3.15.6), checked on IVA and IGIC lines before the invoice is numbered. Otherwise the request is rejected with `422` and the code in brackets: - `04`: only reverse charge (an `ISP_ART_84_2_*` reason) or an exemption (`REGIME_KEY_CLASSIFICATION_NOT_ACCEPTED`). - `08`: only `exemption_reason: NO_SUJETA_LOCALIZACION`, at 0 % (`REGIME_KEY_CLASSIFICATION_NOT_ACCEPTED`). - `10`: only `exemption_reason: NO_SUJETA_ART_7_9`, on a `STANDARD` invoice whose recipient has a `nif` (`REGIME_KEY_CLASSIFICATION_NOT_ACCEPTED`, `REGIME_KEY_REQUIRES_STANDARD_INVOICE`, `REGIME_KEY_REQUIRES_RECIPIENT_NIF`). - `11` (IVA): a subject line only at 21 %, and no reverse charge (`REGIME_KEY_REQUIRES_VAT_RATE`, `REGIME_KEY_CLASSIFICATION_NOT_ACCEPTED`). - `06` and `14` are not accepted (`REGIME_KEY_NOT_SUPPORTED`): AEAT requires with them data the invoice does not carry (a cost-based taxable base; an operation date after the issue date and a public-administration recipient). - `03` (used goods) is not accepted (`REGIME_KEY_NOT_SUPPORTED`): under it the invoice must not show the tax separately (RD 1619/2012, art. 16.2.c), and it always does. The corrective of an invoice that already carried `03` keeps it. - `05` (travel agencies) and `07` (cash basis) are accepted, and the invoice PDF carries the mention of their regime (RD 1619/2012, art. 6.1 n and p). `07`: no reverse charge, no non-subject reason and, of the exemptions, only art. 20 or `OTRO` (`REGIME_KEY_CLASSIFICATION_NOT_ACCEPTED`). `GET /v1/tax-types` only offers the keys that are accepted. **One exception to "a key you send is the key you get":** when the line ends up carrying an equivalence surcharge — whether you sent `equivalence_surcharge_rate` or it was inherited from the company's tax configuration — a `01` is rewritten to `18`, because a surcharge under the general regime is fiscally incoherent. Send `equivalence_surcharge_rate: 0` explicitly to keep `01`. See `equivalence_surcharge_rate` in the invoice line for the full rules.
  - `default_irpf_rate` number: Default IRPF retention rate for this company's invoices. Omit it and the company is created with no withholding — BeeL never assumes a rate nobody declared.
  - `numbering` CompanyNumbering: Configuration of the invoice series the company is born with. Optional and additive: omit it — or any field — and the system default applies for that field: series `F`/`S`/`R`, format `{CODIGO}-{YYYY}-{NUM:4}`, `ANNUAL` counter reset, starting at 1, exactly as before. Send it when the business already issued invoices with another system this year and wants to **continue** its numbering, or simply wants its series born with a specific shape — this is the only moment it can be expressed in the same call. Once a series issues its first invoice BeeL freezes its numbering: `PATCH /v1/companies/{company_id}/series/{series_id}` then rejects `initial_number` with `SERIES_INITIAL_NUMBER_LOCKED_HAS_INVOICES`. It covers the **three** series a company is born with: * the **ordinary** one (real invoices) — the fields at this level, default `F`. * the **simplified** one (ticket-style invoices) — `simplified`, default `S`. * the **corrective** one (rectificativas) — `corrective`, default `R`. Each series takes `code`, `initial_number`, `format` and `counter_reset`, all optional and independent: omit a field and that series keeps the system default for it. `format` and `counter_reset` must be able to tell reset periods apart, with the same rules and error codes as `POST /v1/companies/{company_id}/series`: a `MONTHLY` reset requires `{MM}` plus a year token in the format (`SERIES_MONTHLY_REQUIRES_MONTH_AND_YEAR`); an `ANNUAL` reset requires a year token (`SERIES_ANNUAL_REQUIRES_YEAR`). Mind the default reset is `ANNUAL`: a format without a year token (e.g. `{CODIGO}-{NUM:6}`) also needs `counter_reset: NEVER` in the same series block. Two series that could print the same number (for instance, the same literal format with no `{CODIGO}`) are rejected with `409 SERIES_FORMAT_OVERLAPS`, because an invoice number must be unique per issuer. The list of series is **not** negotiable — a company always starts with exactly these three, one default per document type, because a company without a default series cannot issue at all (`NO_DEFAULT_SERIES`). You configure how each of them is born, not which ones exist. More series can be added later with `POST /v1/companies/{company_id}/series`. **Per environment**: each activation is self-contained and seeds exactly what its request carries. Activating the same NIF in the other environment later does **not** copy this configuration — repeat your `numbering` block in that activation call if you want the same series there; without it the other environment gets the system defaults. Only valid when the request activates the company: with `activate: false` no series are seeded, so a `numbering` block that asks for anything is rejected with `422` `NUMBERING_REQUIRES_ACTIVATION` instead of being silently discarded.
    - `code` string: Alphanumeric series code (used in {CODIGO} variable). Allows uppercase letters, numbers, hyphens and underscores.
    - `initial_number` integer: Number the ordinary series counter starts at. If the last invoice issued elsewhere was `2026-0150`, send `151`. Defaults to 1 when omitted. It applies only to the first period in which the series issues an invoice; with an `ANNUAL` or `MONTHLY` reset every later period starts at 1.
    - `format` string: Format template with available variables (UPPERCASE ONLY): - {CODIGO}: Series code (e.g., "FAC") - {YYYY}: Year with 4 digits (e.g., "2025") - {YY}: Year with 2 digits (e.g., "25") - {MM}: Month with 2 digits (e.g., "01") - {NUM}: Sequential number without padding (e.g., "1") - {NUM:X}: Sequential number with padding (e.g., {NUM:4} → "0001") **REQUIRED**: Must contain at least {NUM} or {NUM:X} **IMPORTANT**: Only uppercase (rejects {yy}, {mm}, {codigo}, etc.) Valid examples: - "{CODIGO}-{YYYY}-{NUM:4}" → "FAC-2025-0001" - "{CODIGO}/{NUM:6}" → "FAC/000001" - "{YYYY}{MM}-{NUM:3}" → "202501-001" The generated number is the invoice number sent to the AEAT, which accepts at most 60 printable ASCII characters and none of `"`, `'`, `<`, `>`, `=`. A format whose longest possible number breaks that rule is rejected with `422 SERIES_FORMAT_NUMBER_TOO_LONG` or `SERIES_FORMAT_INVALID_CHARACTERS`. The counter counts as at least 9 digits, with or without padding: `{NUM:X}` is a minimum width, not a maximum.
    - `counter_reset` 'NEVER' | 'ANNUAL' | 'MONTHLY': Counter reset policy: - NEVER: Counter never resets (continuous numbering) - ANNUAL: Counter resets yearly - MONTHLY: Counter resets monthly
    - `simplified` CompanySeriesNumbering: How one of the series the company is born with should be seeded. All fields are optional and independent: omit one and it falls back to the system default. Same format/reset compatibility rules and error codes as the parent block.
      - `code` string: Alphanumeric series code (used in {CODIGO} variable). Allows uppercase letters, numbers, hyphens and underscores.
      - `initial_number` integer: Number this series' counter starts at, to continue the numbering already used elsewhere. Defaults to 1 when omitted. It applies only to the first period in which the series issues an invoice; with an `ANNUAL` or `MONTHLY` reset every later period starts at 1.
      - `format` string: Format template with available variables (UPPERCASE ONLY): - {CODIGO}: Series code (e.g., "FAC") - {YYYY}: Year with 4 digits (e.g., "2025") - {YY}: Year with 2 digits (e.g., "25") - {MM}: Month with 2 digits (e.g., "01") - {NUM}: Sequential number without padding (e.g., "1") - {NUM:X}: Sequential number with padding (e.g., {NUM:4} → "0001") **REQUIRED**: Must contain at least {NUM} or {NUM:X} **IMPORTANT**: Only uppercase (rejects {yy}, {mm}, {codigo}, etc.) Valid examples: - "{CODIGO}-{YYYY}-{NUM:4}" → "FAC-2025-0001" - "{CODIGO}/{NUM:6}" → "FAC/000001" - "{YYYY}{MM}-{NUM:3}" → "202501-001" The generated number is the invoice number sent to the AEAT, which accepts at most 60 printable ASCII characters and none of `"`, `'`, `<`, `>`, `=`. A format whose longest possible number breaks that rule is rejected with `422 SERIES_FORMAT_NUMBER_TOO_LONG` or `SERIES_FORMAT_INVALID_CHARACTERS`. The counter counts as at least 9 digits, with or without padding: `{NUM:X}` is a minimum width, not a maximum.
      - `counter_reset` 'NEVER' | 'ANNUAL' | 'MONTHLY': Counter reset policy: - NEVER: Counter never resets (continuous numbering) - ANNUAL: Counter resets yearly - MONTHLY: Counter resets monthly
    - `corrective` CompanySeriesNumbering: How one of the series the company is born with should be seeded. All fields are optional and independent: omit one and it falls back to the system default. Same format/reset compatibility rules and error codes as the parent block.
      - `code` string: Alphanumeric series code (used in {CODIGO} variable). Allows uppercase letters, numbers, hyphens and underscores.
      - `initial_number` integer: Number this series' counter starts at, to continue the numbering already used elsewhere. Defaults to 1 when omitted. It applies only to the first period in which the series issues an invoice; with an `ANNUAL` or `MONTHLY` reset every later period starts at 1.
      - `format` string: Format template with available variables (UPPERCASE ONLY): - {CODIGO}: Series code (e.g., "FAC") - {YYYY}: Year with 4 digits (e.g., "2025") - {YY}: Year with 2 digits (e.g., "25") - {MM}: Month with 2 digits (e.g., "01") - {NUM}: Sequential number without padding (e.g., "1") - {NUM:X}: Sequential number with padding (e.g., {NUM:4} → "0001") **REQUIRED**: Must contain at least {NUM} or {NUM:X} **IMPORTANT**: Only uppercase (rejects {yy}, {mm}, {codigo}, etc.) Valid examples: - "{CODIGO}-{YYYY}-{NUM:4}" → "FAC-2025-0001" - "{CODIGO}/{NUM:6}" → "FAC/000001" - "{YYYY}{MM}-{NUM:3}" → "202501-001" The generated number is the invoice number sent to the AEAT, which accepts at most 60 printable ASCII characters and none of `"`, `'`, `<`, `>`, `=`. A format whose longest possible number breaks that rule is rejected with `422 SERIES_FORMAT_NUMBER_TOO_LONG` or `SERIES_FORMAT_INVALID_CHARACTERS`. The counter counts as at least 9 digits, with or without padding: `{NUM:X}` is a minimum width, not a maximum.
      - `counter_reset` 'NEVER' | 'ANNUAL' | 'MONTHLY': Counter reset policy: - NEVER: Counter never resets (continuous numbering) - ANNUAL: Counter resets yearly - MONTHLY: Counter resets monthly
  - `aeat_environment` 'TEST' | 'PROD': Mode a record lives in — its Test/Live twin. It decides where invoices, customers and quota are accounted. For a company it also decides which AEAT its NIF is registered against: switching a company on in `PROD` is what registers it with the real AEAT, so `aeat_environment` is that same mode and uses this same enum.
  - `activate` boolean: Whether to **switch the company on** in `aeat_environment` as part of this call. Creating a company and activating it are two different acts. The company record is free and always creatable; the activation is what seeds the invoice series, registers the NIF and — in `PROD` — is what gets billed. * `true` (default) — unchanged behaviour: the company is created and switched on in `aeat_environment`, with its default series seeded there. * `false` — only the company record is created. It is switched on nowhere, has no series and cannot issue yet; `aeat_environment` is ignored. Activate it later with `POST /v1/companies/{company_id}/activations`, which is also the only door that opens a Stripe Checkout when the account has no card on file. Series numbering travels with the activation that seeds it: a request with `activate: false` and a `numbering` block that asks for anything is rejected with `422` `NUMBERING_REQUIRES_ACTIVATION` — the later activation door does not accept numbering, so silently accepting it here would discard it forever. Either drop the `numbering` block or activate a mode in the same call.

## Response `201`

Company created

- CompanyResponse201
  - `success` boolean
  - `data` CompanyCreatedData: The company exactly as `GET /v1/companies/{company_id}` returns it — every field of `CompanyData`, with the same values — plus `series`. On the env-additive path (the same NIF already living in the account) those are the details in force, which may differ from the ones sent.
    - `id` string, uuid: Unique company identifier.
    - `access_level` 'NONE' | 'VIEW' | 'OPERATE': How much access an actor has to an account or a company. The same three values are used everywhere access is granted or reported — whether the actor is a member of the account or a provisioner managing it on someone's behalf. `NONE` — no access to the data. `VIEW` — read invoices, customers, products, series and fiscal data. `OPERATE` — everything in `VIEW`, plus creating and editing them. Issuing invoices for an account you manage additionally requires a signed fiscal representation from the account holder (see `/v1/accounts/{account_id}/companies/{company_id}/representation`). Access level never affects billing: whoever provisioned an account pays for its subscription regardless of the level they keep over it.
    - `nif` string: Spanish Tax ID (NIF/CIF). Immutable once set.
    - `legal_name` string: Legal/fiscal name of the company. Immutable once set. It is the name that was sent when the NIF was registered, not one AEAT confirmed: for a legal entity the census identifies the CIF and the name is **not verified**. Validate a NIF (`POST /v1/nif/validate`) to read the business name the census actually holds.
    - `trade_name` string: Commercial/trade name shown in the UI and on invoices. Editable. Never empty: when no trade name has been set, it carries `legal_name`, so `trade_name == legal_name` means "no trade name of its own", not that one was written.
    - `entity_type` 'INDIVIDUAL' | 'LEGAL_ENTITY': Taxpayer type. INDIVIDUAL: Natural person (individual self-employed). LEGAL_ENTITY: Legal entity (company with legal form: SL, SA, etc.).
    - `is_primary` boolean: True for the account's primary company (the owner's own NIF).
    - `verifactu_status` 'NOT_CONFIGURED' | 'PENDING' | 'ACTIVE' | 'ERROR': State of the AEAT representation of this NIF, which Live submission to VeriFactu requires. Part of the AEAT-emission axis — independent of `environment`. - `NOT_CONFIGURED`: no representation document, or the last one was cancelled. - `PENDING`: the document is generated and waits to be signed and submitted. - `ACTIVE`: the signed representation is in force. - `ERROR`: reserved; not currently returned.
    - `environment` 'TEST' | 'PROD': Mode a record lives in — its Test/Live twin. It decides where invoices, customers and quota are accounted. For a company it also decides which AEAT its NIF is registered against: switching a company on in `PROD` is what registers it with the real AEAT, so `aeat_environment` is that same mode and uses this same enum.
    - `in_prod` boolean: Whether this company is **activated in Live** (production), regardless of whether the AEAT representation is already signed. Derived from the real activation fact — NOT from the stamped `environment` scalar — so it stays true even for a NIF registered in production but not yet signed. Drives the UI's "already in production" state (no spurious "add NIF" prompt when the account switches to Live).
    - `in_test` boolean: Whether this company is **activated in Test** (sandbox). Symmetric to `in_prod` and derived from the same activation fact: activation is independent per mode, so a company may be activated in Test only, in Live only, in both, or in neither. A company that is not activated in the mode you are working in is shown *switched off* in the dashboard (visible and labelled, but not selectable) rather than hidden.
    - `aeat_environment` 'TEST' | 'PROD': Mode a record lives in — its Test/Live twin. It decides where invoices, customers and quota are accounted. For a company it also decides which AEAT its NIF is registered against: switching a company on in `PROD` is what registers it with the real AEAT, so `aeat_environment` is that same mode and uses this same enum.
    - `account_state` 'TEST_ONLY' | 'PROD_ACTIVE': Account lifecycle stage, expressed in the same Test/Live vocabulary as `Environment`. `TEST_ONLY` means Live has not been activated for the account (no billing set up), so emission to the real AEAT is blocked; `PROD_ACTIVE` means it has.
    - `address` object, nullable: Fiscal address of the company, as set via `POST /v1/accounts/{account_id}/companies` and `PATCH /v1/accounts/{account_id}/companies/{company_id}`. All fields are optional — a company may have a partial address — and the object is `null` when no address has been set.
      - `street` string: Street of the fiscal address.
      - `number` string: Street number.
      - `floor` string: Floor or level.
      - `door` string: Door or apartment.
      - `postal_code` string: Postal code.
      - `city` string: City or town.
      - `province` string: Province.
      - `country` string: Country name.
      - `country_code` string: ISO 3166-1 alpha-2 country code.
    - `legal_form` string, nullable: Legal form (SL, SA, ...). Only for `entity_type: LEGAL_ENTITY`, immutable once set. The field `UpdateCompanyRequest.legal_form` writes.
    - `legal_representative` LegalRepresentativeResponse: Legal representative of a legal entity, as stored. Only present when entity_type = LEGAL_ENTITY.
      - `full_name` string, required: Full name of the legal representative
      - `nif` string, required: Tax ID of the legal representative (DNI/CIF/NIE)
      - `address` object, required: Address of the legal representative
        - `street` string: Full address (street, number, floor, etc.)
        - `number` string: Street number. Absent when the stored address has none.
        - `floor` string: Floor or level
        - `door` string: Door or apartment
        - `postal_code` string: Postal code (5 digits for Spain, free format for other countries)
        - `city` string: City or town
        - `province` string: Province or state. Outside Spain an address may have none.
        - `country` string: Country name: the Spanish name derived from `country_code`. Addresses stored before the country was validated may hold the name as it was sent.
        - `country_code` string: ISO 3166-1 alpha-2 country code
    - `phone` string: A phone number, as the record holds it: digits, spaces, dashes, parentheses and an optional leading `+`, up to 20 characters. This is the schema a **response** carries, and the length above is the only rule it states. It deliberately does not repeat the character rule, because a number can reach a record through a path that predates that rule or never passed through this API at all — a payment provider's customer data, a bulk import. Read the field defensively and do not assume it parses. What a **request** has to satisfy is `PhoneInput`, which adds the rules this API enforces on the way in.
    - `email` string, email: Email address (minimum valid email is 5 chars, e.g. a@b.co)
    - `website` string, nullable: Website. The field `UpdateCompanyRequest.website` writes.
    - `logo_url` string, nullable: Public URL of the logo printed on the invoice. The field `UpdateCompanyRequest.logo_url` writes. Also returned by `GET /v1/companies/{company_id}/invoice-customization` and as `issuer.logo_url` of an invoice, always as the same absolute, fetchable URL.
    - `additional_info` string, nullable: Free note printed on the invoice — the field `UpdateCompanyRequest.additional_info` writes.
    - `default_iban` string: IBAN (International Bank Account Number). Required when payment method is BANK_TRANSFER.
    - `default_swift` string: SWIFT/BIC code
    - `account_holder` string, nullable: Bank account holder. The field `UpdateCompanyRequest.account_holder` writes.
    - `iae` string, nullable: IAE code. The field `UpdateCompanyRequest.iae` writes.
    - `activity_start_date` string, date, nullable: Activity start date. The field `UpdateCompanyRequest.activity_start_date` writes.
    - `default_payment_term` integer, nullable: Default payment term in days. The field `UpdateCompanyRequest.default_payment_term` writes.
    - `invoice_template_type` 'MODERN_TABLE' | 'PROFESSIONAL_SERVICE': Invoice PDF template. `MODERN_TABLE` is a structured table layout for product/service lines; `PROFESSIONAL_SERVICE` is a text-based layout.
    - `invoice_accent_color` string, nullable: Invoice PDF accent color (`#RRGGBB`). The field `UpdateCompanyRequest.invoice_accent_color` writes. Also returned by `GET /v1/companies/{company_id}/invoice-customization`.
    - `invoice_language` 'es' | 'en' | 'ca': Supported languages: `es` Spanish, `en` English, `ca` Catalan.
    - `email_language` 'es' | 'en' | 'ca': Supported languages: `es` Spanish, `en` English, `ca` Catalan.
    - `default_irpf_rate` number, nullable: Default IRPF withholding rate applied to this company's invoices — the same number `POST /v1/accounts/{account_id}/companies` accepts and `GET`/`PUT /v1/companies/{company_id}/tax-configuration` manages, read back where you wrote it. **Absent means no rate was ever declared**, which is not the same as `0`. A company created without `default_irpf_rate` withholds nothing *because nobody said what to withhold*; a company with `0` withholds nothing *because its owner declared so*. Both invoice the same, only one is a declaration — so do not fill the absent case in with a zero. Exemption is a declaration too and reads as `0`. Read-only here. Change it with `PUT /v1/companies/{company_id}/tax-configuration`; this resource does not accept it on `PATCH`. Absent from the `201` of `POST /v1/accounts/{account_id}/companies` (that response describes the company just created, not its resolved tax configuration) — read it back with `GET`.
    - `created_at` string, date-time: When the company was created (ISO 8601).
    - `readiness` IssuingReadinessData: Issuing-readiness of a company: whether it can issue its STANDARD invoice right now, in this environment, and — if not — exactly what is missing. `ready` is true only when `blockers` is empty. Issuing any fiscal document requires the company to be activated in that environment (`COMPANY_NOT_ACTIVATED` otherwise), whether or not it goes to VeriFactu. The VeriFactu capability chain (census, signature) is only demanded on top of that when the company is under the VeriFactu regime in this environment — the same fact that decides, at issue time, whether its invoices are registered. With VeriFactu off, a NIF, a default series and a live activation are enough to be ready.
      - `ready` boolean: true if the company can issue invoices (no blockers).
      - `blockers` string[]: Reasons the company cannot issue yet (empty when ready). Each one names what is missing and how to clear it: - `COMPANY_HAS_NO_NIF`: the company has no NIF. Set `nif` with `PATCH /v1/companies/{company_id}`; once set it cannot be changed. - `SERIES_DEFAULT_NOT_FOUND`: there is no default `STANDARD` invoice series in this environment. The `SIMPLIFIED` and `CORRECTIVE` ones are created on first use. `PUT /v1/companies/{company_id}/series/defaults` creates the missing ones, or mark an existing series with `PUT /v1/companies/{company_id}/series/{series_id}/default`. - `PROFILE_INCOMPLETE`: the fiscal identity is not complete enough to write an invoice header: entity type, legal name or full fiscal address is missing. Complete `entity_type`, `legal_name` and `address` with `PATCH /v1/companies/{company_id}`. A missing NIF is reported as `COMPANY_HAS_NO_NIF` instead, never as both. - `COMPANY_NOT_ACTIVATED`: the company is not activated in the environment of the request, and it is not under the VeriFactu regime. Activate it with `POST /v1/companies/{company_id}/activations` for that environment. - `ENV_MISMATCH`: the same missing activation, for a company under the VeriFactu regime. Activate it as above, or call with a credential of the environment where it is already activated. The first stage of the VeriFactu chain. - `NIF_NOT_REGISTERED`: the NIF is not registered for VeriFactu submission in this environment. Turning VeriFactu on (`PUT /v1/companies/{company_id}/verifactu-configuration` with `enabled: true`) registers it; in Live that call needs the signed representation first. Never reported in Test, where the NIF is registered with its first submission. - `NIF_REPRESENTATION_REQUIRED`: the NIF is registered, but there is no signed AEAT representation in force. Generate it with `POST /v1/companies/{company_id}/representation`, sign it digitally and send it with `POST /v1/companies/{company_id}/representation/submit`. Live only.
      - `verifactu` object: The compliance question, separate from the operational `ready` above: would this NIF pass a VeriFactu emission right now? Relevant before putting the company under the VeriFactu regime. For a company already under the regime, `verifactu.ready` coincides with `ready` (same evaluation).
        - `ready` boolean: true only when the company is operationally `ready` AND its VeriFactu capability chain is clean. An operational blocker (missing NIF, default series, or an incomplete fiscal identity) makes this false even if the chain itself is complete — and, since those are not chain stages, it does so with an EMPTY `blockers` list here. The reason is in the top-level `blockers`, which is where operational blockers are reported.
        - `blockers` string[]: ONLY the incremental VeriFactu capability stages, in order and mutually exclusive — one reason at a time, without repeating the operational blockers (NIF/series/fiscal identity) listed above. The stages, and how to clear each one, are the same as in the top-level `blockers`: - `ENV_MISMATCH`: the company is not activated in the environment of the request. - `NIF_NOT_REGISTERED`: the NIF is not registered for VeriFactu submission in this environment; turning VeriFactu on registers it. - `NIF_REPRESENTATION_REQUIRED`: no signed AEAT representation in force. Only appears where a signed representation is actually demanded (Live).
    - `series` InvoiceSeries[]: Invoice series seeded by the activation this request performed, one per document type (ordinary, simplified, corrective) — the same shape as `GET /v1/companies/{company_id}/series`, so no second call is needed to confirm which series the company was born with (including any custom `numbering` the request carried). An empty array when the request did not activate any mode (`activate: false` seeds no series). On an env-additive activation (same NIF, other environment) it reflects the series of the environment just activated.
      - `id` string, uuid, required: Unique series ID
      - `document_type` 'UNASSIGNED' | 'STANDARD' | 'SIMPLIFIED' | 'CORRECTIVE' | 'SIMPLIFIED_CORRECTIVE' | 'PROFORMA', required: Document type associated with a series. Values mirror `InvoiceType`, so the series a document needs is named exactly like the document: - UNASSIGNED: Legacy value of series created before types existed. A series numbers only documents of its own type, so an `UNASSIGNED` series numbers none (`422 SERIES_INCOMPATIBLE_DOC_TYPE`); give it a type to keep using it. No series can be created with it or moved to it (`422 SERIES_UNASSIGNED_TYPE_NOT_ALLOWED`). The live ones were given the type they numbered most. - STANDARD: Standard invoice - SIMPLIFIED: Simplified invoice - CORRECTIVE: Corrects or cancels a previous standard invoice (R1–R4) - SIMPLIFIED_CORRECTIVE: Corrects a simplified invoice (R5). Spanish law requires R5 to be numbered apart from R1–R4, so they have a series type of their own - PROFORMA: Proforma (commercial document, non-fiscal numbering)
      - `name` string, required: Descriptive name of the series
      - `code` string, required: Alphanumeric series code (used in {CODIGO} variable). Allows uppercase letters, numbers, hyphens and underscores.
      - `description` string: Optional series description
      - `format` string, required: Format template with available variables (UPPERCASE ONLY): - {CODIGO}: Series code (e.g., "FAC") - {YYYY}: Year with 4 digits (e.g., "2025") - {YY}: Year with 2 digits (e.g., "25") - {MM}: Month with 2 digits (e.g., "01") - {NUM}: Sequential number without padding (e.g., "1") - {NUM:X}: Sequential number with padding (e.g., {NUM:4} → "0001") **REQUIRED**: Must contain at least {NUM} or {NUM:X} **IMPORTANT**: Only uppercase (rejects {yy}, {mm}, {codigo}, etc.) Valid examples: - "{CODIGO}-{YYYY}-{NUM:4}" → "FAC-2025-0001" - "{CODIGO}/{NUM:6}" → "FAC/000001" - "{YYYY}{MM}-{NUM:3}" → "202501-001" The generated number is the invoice number sent to the AEAT, which accepts at most 60 printable ASCII characters and none of `"`, `'`, `<`, `>`, `=`. A format whose longest possible number breaks that rule is rejected with `422 SERIES_FORMAT_NUMBER_TOO_LONG` or `SERIES_FORMAT_INVALID_CHARACTERS`. The counter counts as at least 9 digits, with or without padding: `{NUM:X}` is a minimum width, not a maximum.
      - `counter_reset` 'NEVER' | 'ANNUAL' | 'MONTHLY', required: Counter reset policy: - NEVER: Counter never resets (continuous numbering) - ANNUAL: Counter resets yearly - MONTHLY: Counter resets monthly
      - `initial_number` integer: Initial number configured for this series counter: the number the series starts from. It applies only to the first period in which the series issues an invoice: with `counter_reset: ANNUAL` or `MONTHLY`, every later year or month starts at 1. With `NEVER` there is a single period, so numbering simply continues from it.
      - `active` boolean, required: Indicates whether the series is active
      - `default_series` boolean, required: Indicates whether this is the user's default series (only one can be)
      - `numbering_locked` boolean: `true` once this series has issued at least one invoice. From that point the fields that drive numbering (`code`, `format`, `counter_reset`, `initial_number`) are permanently locked and any attempt to change them is rejected — numbering can only be adjusted **before** the first invoice of a series. Cosmetic fields (`name`, `description`) remain editable. To use a different numbering, create a new series.
      - `created_at` string, date-time: Creation date
      - `next_number` integer: Next invoice number that will be assigned for this series
      - `updated_at` string, date-time: Last update date
  - `meta` ResponseMeta
    - `timestamp` string, date-time
    - `request_id` string

## Other responses

- `400`: Bad request. From a dashboard session, a `BeeL-Environment` header whose value is not a known environment answers `ENVIRONMENT_HEADER_INVALID`, with the header named in `error.details` (`{"BeeL-Environment": "invalid"}`); it is never read as production. `BUSINESS_RULE_VIOLATION` is the generic answer to an operation the resource does not admit in its current state when that state has no code of its own. It carries no `details`; read the resource again before retrying.
- `401`: Missing or invalid authentication. Like every other error, `message`/`detail` is localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English when the header is missing or asks for none of those.
- `402`: Payment required before creating a production NIF. No company is created and no checkout is opened. Three distinct reasons, so branch on `error.code`: * `CHECKOUT_REQUIRED` — the account has **no card on file**. Nothing is owed; billing simply has not been set up. It gets set up by activating a company in Live. * `PAYMENT_REQUIRED` — the account has billing but is **unpaid**: payment retries are exhausted. The outstanding invoice must be settled; no new checkout is opened for it. A failed charge that is still being retried does not block Live. * `PLAN_ACTIVATION_REQUIRED` — the account is on a **fixed-quota plan still on trial**. Nothing is owed and the per-NIF checkout does not apply, because the quota already includes this NIF: the act that unblocks Live is activating the plan.
- `403`: Several distinct reasons, so branch on `error.code`: * **No `error.code` of the feature family** — you do not reach the account this request resolves to (the `BeeL-Active-Company` header points at a company you neither own nor manage with write access). Account existence is never disclosed. * `FEATURE_NOT_AVAILABLE` — you reach the account, but its plan does not include `multi_nif` and it **already has at least one company**. The first NIF of an account is always allowed (that is onboarding); every NIF after it needs the feature. `error.details.feature_code` is `multi_nif` and `error.details.current_plan` carries the account's current plan (`NONE` when it has none). `multi_nif` is contact-sales, so there is no self-service plan to upgrade to and no `action`/upgrade target travels in `details` — unlike the plan-based features, where it does. * `NOT_BILLING_OWNER` — creating a NIF **in Live** requires being the billing subject of the account. A collaborator, or an API key minted by a member who is not the account's owner, reaches the account and can create in Test, but cannot switch a NIF on in Live. The owner has to do it, or mint the key. * `BILLING_MANAGED_BY_PROVIDER` — the account's billing is run by its provider, so creating in Live has to be requested from them; retrying will not help. * `CONTACT_SALES_REQUIRED` — the account is on the API plan (billed per NIF) with **no agreed price**, which covers one NIF self-service. Not a hard error: it routes to sales, who set up a per-NIF price, after which the same request goes through. `error.details.reason` says which rule applied and `error.details.salesUrl` is where to talk to sales: * `SECOND_NIF` — the account has exactly one active company and this would be the second, in `TEST` or in `PROD`. Accounts that already have two or more are not held back here. * `LIVE_WITH_MULTIPLE_NIFS` — the request switches the NIF on in Live and the account has two or more active companies. Answered before the `409` of a NIF live in another account and before any `402`. `FEATURE_NOT_AVAILABLE` runs before the environment branches, so it applies to `TEST` and to `PROD` alike, and it runs *after* the duplicate-NIF check: re-sending a NIF you already have is a `409`, never an upsell. The two billing-subject codes only apply to a request that switches the NIF on in Live, and they are answered **before** the `409` of a NIF already live in another account and before any `402`: neither has an action you could take, so nothing about another account's state is disclosed to someone who cannot act on it.
- `404`: `SUBACCOUNT_USER_NOT_FOUND` — the person who holds the account no longer has an active user (they deleted it), so there is nobody to own the new company. Nothing was created.
- `409`: The NIF cannot be created. Branch on `error.code`: * `NIF_ALREADY_REGISTERED` — the NIF **already exists in your account**. Creating is done; switching an environment on for it is a different act and has its own endpoint: `POST /v1/companies/{company_id}/activations`. The existing company's id travels in `error.details.company_id`, so no lookup is needed to call it. * `NIF_PROD_ALREADY_ACTIVE_IN_ANOTHER_ACCOUNT` — the NIF is live in **another account**. A NIF can only issue in production from one account (tax rule). * `SERIES_FORMAT_OVERLAPS` — the `numbering` block gives two series formats that could print the same invoice number. * `NIF_LIMIT_REACHED` — the request switches the NIF on in Live, and the account's agreement caps how many NIFs can be active in Live and the cap is full. `error.details` is empty; the cap travels in `error.message`. Create it in Test, or switch another NIF off in Live, or contact BeeL to raise the cap.
- `422`: Validation or business rule error. The NIF is checked against the AEAT census before the company is created, and nothing is stored when it fails (`NIF_VALIDATION_INVALID`). For an individual the census matches the NIF with the fiscal name, so a wrong name is rejected too. For a legal entity the census checks the CIF only: the name is not verified, and it cannot fail because of the name. Check the NIF (and, for an individual, the fiscal name), then repeat the request. `PHYSICAL_PERSON_CANNOT_HAVE_LEGAL_FORM` and `PHYSICAL_PERSON_CANNOT_HAVE_REPRESENTATIVE` reject an `INDIVIDUAL` that carries a `legal_form` or a `legal_representative`: both only exist for a `LEGAL_ENTITY`. `ENTITY_TYPE_INCONSISTENT_WITH_NIF` rejects an `entity_type` that does not match the NIF: an `INDIVIDUAL` is identified by a DNI or NIE, a `LEGAL_ENTITY` by a NIF that starts with a legal-form letter. `ACCOUNT_HAS_NO_HOLDER` — the account was provisioned without a person and nobody has claimed it yet, so there is no holder to own the company; issue a claim token first. Other `error.code` values with this status: - `INVALID_IRPF` — the `irpf_rate` is not a withholding rate in force (see `IrpfPercentage`); send one of the published rates. - `INVALID_PERCENTAGE` — the `percentage` is not a rate of that tax type (e.g. IVA 13); the message lists the valid rates. OSS key `17` accepts any EU rate. - `IRPF_RATE_NOT_FOR_CORPORATE_ISSUER` — the issuer is a company (corporate income tax), which can only withhold 0, 19 or 24 %; use one of those. - `IRPF_RATE_ONLY_FOR_CORPORATE_ISSUER` — the rate (e.g. 9.5 % Ceuta/Melilla) only applies to corporate issuers; an individual issuer must use a personal-income-tax rate. - `SERIES_FORMAT_INVALID_PADDING` — the padding in `{NUM:X}` must be a whole number from 1 to 20 (e.g. `{NUM:4}` → `0001`). - `SERIES_FORMAT_NUM_REQUIRED` — the series `format` has no `{NUM}` or `{NUM:X}`, so it cannot number invoices. Add the counter. - `SERIES_FORMAT_UNRECOGNIZED_VARS` — the `format` uses a variable BeeL. does not know. Allowed: `{CODIGO}`, `{YYYY}`, `{YY}`, `{MM}`, `{NUM}`, `{NUM:X}`.
- `429`: Rate limit exceeded. `RATE_LIMIT_EXCEEDED` when the request rate of your credential is over its limit; `TOO_MANY_REQUESTS` when an email the operation sends is held back because too many went out to that recipient in a short time. Either way, retry after the `Retry-After` seconds. `QUOTA_EXCEEDED` is the other `429`: the operation would go over a quota of your plan for the current period (issued invoices, for instance). Retrying does not help until the quota resets or the plan changes. `error.details` carries `feature_code`, `current_usage`, `quota_limit` and `reset_date`, and `RateLimit-Reset` the seconds until the reset when it is known.
- `500`: Internal server error
- `502`: `EXTERNAL_SERVICE_ERROR` — the AEAT census could not be reached to validate the NIF. The company was not created. Nothing was stored. It is transient; repeat the same request later (with the same `Idempotency-Key` if you sent one). No `Retry-After` header is sent.
- `default`: Any status code the operation does not list above. Every operation declares it, so a generated client always has a branch to fall into and never loses the cause of a failure it did not anticipate. This is where the transport-level answers land — `405`, `406`, `415` and `429` — together with any status a future version of the API starts returning. All of them carry the same error envelope as the codes listed explicitly, so `error.code` is what tells them apart: switching on the status code alone is not enough. See «Transport-level errors» in the API description for when each one is produced. A `402` carrying `SUBSCRIPTION_REQUIRED` lands here when the account has no active subscription. `error.details` says why and what to do: `current_status` (absent if it never had one), `required_permission` and `action`. A `503` carrying `SERVICE_UNAVAILABLE` lands here too, with a `Retry-After` header: a dependency of BeeL itself (the database, the email provider) was momentarily unavailable and nothing was done. Retry after those seconds. A `502` carrying `EXTERNAL_SERVICE_ERROR` also lands here: an outbound integration the operation depends on failed or did not answer in time. It is a transient condition — retry with the same `Idempotency-Key` where the operation accepts one. One exception to the envelope: a failure of the network edge that never reaches the application (`502`, `503`, `504`, `524`) is generated by Cloudflare and its body is not BeeL's — it may not even be JSON. Treat those as "no answer", and retry.

---

[API](https://skmtc.dev/beel/apis/beel-public-api.md) · [All operations](https://skmtc.dev/beel/apis/beel-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/beel/apis/beel-public-api/revisions/ffbc0ae31f79?raw)
