Create a company
Scopecompanies:writeCreates 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 isfalse, the company is switched on inaeat_environmentand its three default invoice series (ordinary, simplified, corrective) are seeded there. This endpoint never switches an existing company on: that isPOST /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 existingerror.details.company_id.
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
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.
uuidHeader Parameters
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.
| Status | Code | When |
|---|---|---|
400 | INVALID_IDEMPOTENCY_KEY | The key breaks the format rules above. |
409 | IDEMPOTENCY_KEY_PROCESSING | The first request is still in flight. Wait and retry with the same key. |
409 | IDEMPOTENCY_KEY_MISMATCH | The key was already used with a different body. Use a new key. |
^[a-zA-Z0-9_-]+$length <= 255NIF/CIF of the business
Legal/fiscal name
Taxpayer type. INDIVIDUAL: Natural person (individual self-employed). LEGAL_ENTITY: Legal entity (company with legal form: SL, SA, etc.).
"INDIVIDUAL" | "LEGAL_ENTITY"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 (SL, SA, ...). Recommended for LEGAL_ENTITY.
Legal representative data for a legal entity. Only used when entity_type = LEGAL_ENTITY.
Commercial/trade name (optional)
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 retention rate for this company's invoices. Omit it and the company is created with no withholding — BeeL never assumes a rate nobody declared.
0 <= value <= 100Configuration 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, defaultS. - the corrective one (rectificativas) —
corrective, defaultR.
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.
"TEST" | "PROD"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 inaeat_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_environmentis ignored. Activate it later withPOST /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.
trueResponse 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"
}
}End your management of an account DELETE
Ends the management relationship over an account you provisioned: you lose access to it, and its NIFs stop counting towards your billable usage from the next billing cycle. - **The holder:** keeps the account, its NIFs and its invoices, and becomes responsible for their own subscription. Nothing is deleted or anonymised. - **Reversible:** only while the account stays unclaimed. Provisioning the same email again reactivates it (see `POST /v1/accounts`), and only the manager who ended the relationship can do so. Once the holder claims the account it is theirs, and getting the management back needs their consent, not just their email address. - **Entitlement:** requires `manage_accounts`.
List the companies of an account GET
Returns the companies (NIFs) belonging to the account in the path, ordered with the primary company first. An account with no companies yet returns an empty list rather than an error. - **`search`:** filters case-insensitively on NIF, legal name and trade name. - **`include=readiness`:** adds each company's issuing-readiness block. - **`pagination`:** present only when the request is paginated — that is, when any of `page`, `limit` or `search` is sent. It is omitted for the full list. - **Series:** not part of this response. Read them from `GET /v1/companies/{company_id}/series`.