NewThree filters returned the wrong rows
BeeL
Get StartedMulti-NIFVeriFactuStripeAPI ReferenceChangelog
Companies

Create a company

Scopecompanies:write

Creates a company (NIF) 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 on an account without billing is rejected with 402, and no checkout is opened.
  • Duplicates: a NIF that already exists in the account is rejected with 409, and the response carries the existing error.details.company_id.

POST
/v1/accounts/{account_id}/companies
AuthorizationBearer <token>

Keys are prefixed beel_sk_, and each one carries the scopes it was created with: a key short of the scope an operation needs is answered 403. The scope an operation requires is shown next to its title, and the full catalogue lives in the Scopes reference.

Keys are created from the BeeL dashboard. They are secret credentials: do not share them or commit them to source control.

In: header

Path Parameters

account_idstring

Your own account, or an account you provisioned. It — not the credential — decides which account the operation acts on; a 403 is returned when you do not reach it, the same response an account that does not exist gets.

Formatuuid

Header Parameters

Idempotency-Key?string

Idempotency key to prevent duplicates in sensitive operations.

  • Any unique client-generated string (e.g. an order id). A UUID also works but is not required
  • Allowed characters: letters, digits, _ and - (max 255 chars)
  • If the same key is sent twice, the result of the first operation is returned
  • Keys expire 24 hours after processing

The key is scoped per user and environment, and bound to the request body, so retrying after a network timeout replays the stored response instead of repeating the operation.

StatusCodeWhen
400INVALID_IDEMPOTENCY_KEYThe key breaks the format rules above.
409IDEMPOTENCY_KEY_PROCESSINGThe first request is still in flight. Wait and retry with the same key.
409IDEMPOTENCY_KEY_MISMATCHThe key was already used with a different body. Use a new key.
Match^[a-zA-Z0-9_-]+$
Lengthlength <= 255
nifstring

NIF/CIF of the business

legal_namestring

Legal/fiscal name

entity_typestring

Taxpayer type. INDIVIDUAL: Natural person (individual self-employed). LEGAL_ENTITY: Legal entity (company with legal form: SL, SA, etc.).

Value in"INDIVIDUAL" | "LEGAL_ENTITY"
address

Address you send when you create or update a company, a customer or an onboarding. The street number is mandatory here: an address without it is rejected with 422.

Addresses you read back are described by their own schema, and do not guarantee the street number: records registered before it was collected have none.

legal_form?string

Legal form (SL, SA, ...). Recommended for LEGAL_ENTITY.

legal_representative?

Legal representative data for a legal entity. Only used when entity_type = LEGAL_ENTITY.

trade_name?string

Commercial/trade name (optional)

default_main_tax?

Complete tax information with cross-validations:

  • IVA: real rates 4, 5, 10, 21 (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 4, 5, 10 and 21 for IVA and not 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 % (RD-ley 11/2022 and its extensions, on electricity, gas and basic foodstuffs) is no longer in force for new operations, but it stays valid: corrective invoices and late-filed invoices for the periods when it applied must be able to carry it. Its equivalence surcharge pair is 0.625.

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.

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.

Range0 <= value <= 100
numbering?

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 its numbering is frozen by law: 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.

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.

aeat_environment?string
Value in"TEST" | "PROD"
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 NIF profile 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 NIF profile is created. The company 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.

Defaulttrue

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://app.beel.es/api/v1/accounts/497f6eca-6276-4993-bfeb-53cbbbba6f08/companies" \  -H "Content-Type: application/json" \  -d '{    "nif": "B12345674",    "legal_name": "Mi Empresa SL",    "entity_type": "INDIVIDUAL",    "address": {      "street": "Calle Mayor, 123",      "number": "123",      "postal_code": "28001",      "city": "Madrid",      "province": "Madrid"    }  }'
{
  "success": true,
  "data": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "access_level": "NONE",
    "nif": "string",
    "legal_name": "string",
    "trade_name": "string",
    "entity_type": "INDIVIDUAL",
    "is_primary": true,
    "verifactu_status": "NOT_CONFIGURED",
    "environment": "PROD",
    "in_prod": true,
    "in_test": true,
    "aeat_environment": "PROD",
    "account_state": "TEST_ONLY",
    "address": {
      "street": "string",
      "number": "string",
      "floor": "string",
      "door": "string",
      "postal_code": "string",
      "city": "string",
      "province": "string",
      "country": "string",
      "country_code": "string"
    },
    "legal_form": "string",
    "legal_representative": {
      "full_name": "María García López",
      "nif": "12345678A",
      "address": {
        "street": "Calle Mayor, 123",
        "number": "123",
        "floor": "2º A",
        "door": "A",
        "postal_code": "28001",
        "city": "Madrid",
        "province": "Madrid",
        "country": "España",
        "country_code": "ES"
      }
    },
    "phone": "+34 612 345 678",
    "email": "user@example.com",
    "website": "string",
    "logo_url": "string",
    "additional_info": "string",
    "default_iban": "ES1234567890123456789012",
    "default_swift": "ABCDESMMXXX",
    "account_holder": "string",
    "iae": "string",
    "activity_start_date": "2019-08-24",
    "default_payment_term": 365,
    "invoice_template_type": "MODERN_TABLE",
    "invoice_accent_color": "#fc481d",
    "invoice_language": "es",
    "email_language": "es",
    "default_irpf_rate": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "readiness": {
      "ready": true,
      "blockers": [
        "COMPANY_HAS_NO_NIF"
      ],
      "verifactu": {
        "ready": true,
        "blockers": [
          "ENV_MISMATCH"
        ]
      }
    },
    "series": [
      {
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "document_type": "UNASSIGNED",
        "name": "Main Series",
        "code": "FAC",
        "description": "Series for standard invoices",
        "format": "{CODIGO}-{YYYY}-{NUM:4}",
        "counter_reset": "NEVER",
        "initial_number": 1,
        "active": true,
        "default_series": false,
        "numbering_locked": true,
        "created_at": "2019-08-24T14:15:22Z",
        "next_number": 0,
        "updated_at": "2019-08-24T14:15:22Z"
      }
    ]
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "BAD_REQUEST",
    "message": "Invalid request"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication is required to access this resource"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "PAYMENT_REQUIRED",
    "message": "You have an outstanding payment. Settle it before creating a production company."
  },
  "meta": {
    "timestamp": "2026-05-29T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "FEATURE_NOT_AVAILABLE",
    "message": "The 'Multi-NIF (Business Profiles)' feature is not available on your current plan.",
    "details": {
      "feature_code": "multi_nif",
      "current_plan": "PRO"
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "NIF_ALREADY_REGISTERED",
    "message": "This NIF is already registered in your account",
    "details": {
      "company_id": "9c8f1f2e-2b7a-4a1e-9d1f-3f5a8c2b7e10"
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "UNPROCESSABLE_ENTITY",
    "message": "Data cannot be processed",
    "details": {
      "field": "Specific error description"
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please try again in 60 seconds."
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "UNSUPPORTED_MEDIA_TYPE",
    "message": "Unsupported media type: text/plain. Supported: application/json"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}