# Get user tax configuration (deprecated) API Reference

**Deprecated.** Use `GET /v1/companies/{company_id}/tax-configuration`, which behaves
identically.

Retrieves the tax configuration of the company in focus: the default main tax
(`IVA`, `IGIC`, `IPSI` or `OTHER`) with its percentage and regime key, the default
exemption reason, the IRPF and equivalence surcharge settings, and the default payment
method and payment term.

**Retires on 9 December 2026.** See the [migration guide](https://docs.beel.es/changelog/resources-under-the-nif) for what moved where and what changes when you switch.


## GET /v1/configuration/taxes

**Get user tax configuration**

**Deprecated.** Use `GET /v1/companies/{company_id}/tax-configuration`, which behaves
identically.

Retrieves the tax configuration of the company in focus: the default main tax
(`IVA`, `IGIC`, `IPSI` or `OTHER`) with its percentage and regime key, the default
exemption reason, the IRPF and equivalence surcharge settings, and the default payment
method and payment term.

**Retires on 9 December 2026.** See the [migration guide](https://docs.beel.es/changelog/resources-under-the-nif) for what moved where and what changes when you switch.

**Deprecated.**

### Authentication

Accepts any of:

- `ApiKeyAuth` (HTTP bearer, token format `beel_sk_*`)

### Responses

#### 200: Configuration retrieved successfully

**Content `application/json`:**

- **success** (required) `boolean`: No description (example: true)
- **data** (required): The payload. An object for a single resource; an object holding the named collection (and its `pagination`) for a listing. Never a bare array at this level in v1.
- **meta** `ResponseMeta`
- **data** `TaxConfiguration`

#### 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.


**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

**Example:**

```json
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication is required to access this resource"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
```

#### 403: Authenticated but not allowed. Fourteen causes shared by every operation, told apart by
`error.code`; an operation that adds a cause of its own names it in its `403`. You can
branch on them exhaustively.

- `INSUFFICIENT_SCOPE` — the credential lacks a scope the operation requires;
  `error.details.missing_scopes` names them as a single comma-separated string (for
  example `"invoices:write,customers:read"`), not as an array; `required_scopes` has the
  same shape and lists every scope the operation needs. Retrying will not help: mint a key
  that holds them.
- `COMPANY_READ_ONLY` — the scope is there, but your access level over that NIF only
  lets you read it.
- `ACCOUNT_MANAGEMENT_FORBIDDEN` — the scope is there, but your role over the account,
  or the management relationship you hold over it, does not cover this operation.
- `ACCOUNT_NOT_ACCESSIBLE` — the account is not yours to reach, which is also the answer
  when it does not exist, so existence is never disclosed.
- `ACTIVE_COMPANY_NOT_ACCESSIBLE` — the same, for a NIF: the company in the path, or the
  one named by `BeeL-Active-Company`, is not one this credential may reach — and again,
  this is also the answer when it does not exist.
- `COMPANY_ACCESS_REVOKED` — your access to the NIF was withdrawn while the request was
  already in flight, so the write was rejected and nothing was recorded. Retrying will
  not help until the access is granted again.
- `LIVE_CREDENTIAL_REQUIRED` — the operation changes the real account and the call came
  from a test API key (`beel_sk_test_…`). Use your live key or the dashboard.
- `FEATURE_NOT_AVAILABLE` — your subscription does not include the entitlement the
  operation needs; `error.details.feature_code` names it. This gate runs **before** the
  scope gate, so for such an operation you never see `INSUFFICIENT_SCOPE` first.
- `NO_ACTIVE_ACCOUNT` — the credential does not resolve to an account, so no scope can be
  evaluated against one. Fail-closed, not a permission that can be granted to you.
- `OPERATION_REQUIRES_SESSION` — the operation is available only from the web session; no
  API key and no OAuth2 token can perform it, whatever scopes it holds.
- `OPERATION_REQUIRES_API_KEY` — the reverse: the operation needs a scope that only an API
  key can hold (such as `accounts:write`), so a dashboard session never satisfies it.
- `API_KEY_LIVE_NOT_AVAILABLE` — the call came with a live API key (`beel_sk_live_…`) and
  the account has no Live mode yet. It is never degraded to Test: use your test key, or
  activate Live first.
- `ACCOUNT_REQUIRES_FOCUS_SWITCH` — dashboard session only: you are a member of the account
  in the path, but it is not the account in focus. Switch focus to it and retry.
- `REQUEST_BLOCKED` — the edge security filter stopped the request before the API saw its
  body, usually because a text field carries something that looks like markup or a
  script (HTML tags, `<script>`). Review the body and retry.


**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

**Example:**

```json
{
  "success": false,
  "error": {
    "code": "FORBIDDEN",
    "message": "You do not have permission to access this resource"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
```

#### 500: Internal server error

**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

**Example:**

```json
{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
```

#### 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.


**Content `application/json`:**

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

**Example:**

```json
{
  "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"
  }
}
```

---

# Related Schema Definitions

## SuccessResponse

The envelope every successful JSON response of the BeeL. API is wrapped in. There are no
bare resources in v1 and none are planned: the payload always hangs off `data`.

- A **single resource** is an object in `data`.
- A **collection** hangs off a named key inside `data`, together with its `pagination`,
  also inside `data` — `data: {invoices: [...], pagination: {...}}`.
- A collection carries `pagination` unless its operation declares itself a **closed
  catalogue**: a fixed, bounded list with nothing to page through. The declaration is
  explicit in the operation; a missing `pagination` is never something to infer.
- `GET /v1/accounts` pages by cursor (`data: {accounts: [...], next_cursor}`). It is a
  documented variant of pagination, not another envelope.

Putting the array straight into `data` with `pagination` as its sibling is the shape a v2
would adopt; v1 is not being flipped to it.

- **success** (required) `boolean`: No description (example: true)
- **data** (required): The payload. An object for a single resource; an object holding the named collection (and its `pagination`) for a listing. Never a bare array at this level in v1.
- **meta** `ResponseMeta`

## ResponseMeta

- **timestamp** `string` (date-time): No description (example: "2025-01-15T10:30:00Z")
- **request_id** `string`: No description (example: "4bf92f3577b34da6a3ce929d0e0e4736")

## TaxConfiguration

- **default_main_tax** (required): No description
- **default_exemption_reason** `ExemptionReason`: Tax exemption reason code per the Spanish VAT Law (Ley 37/1992, LIVA), with the VeriFactu code each one is reported as. - `EXENTA_ART_20`: exempt, art. 20 (domestic operations such as medical, educational, cultural and financial services, or housing rentals). E1. - `EXENTA_ART_21`: exempt, art. 21 (exports of goods). E2. - `EXENTA_ART_22`: exempt, art. 22 (operations treated as exports). E3. - `EXENTA_ART_24`: exempt, art. 24 (free zones, warehouses and customs regimes). E4. - `EXENTA_ART_25`: exempt, art. 25 (intra-community supplies of goods). E5. - `EXENTA_ART_26`: exempt, art. 26 (intra-community acquisitions of goods). It exempts the buyer's acquisition, not a supply the seller invoices, so an invoice line that carries it is rejected with `EXEMPTION_NOT_FOR_ISSUED_INVOICE`; a supply to another Member State is `EXENTA_ART_25`. - `NO_SUJETA_ART_7_9`: not subject under art. 7 (such as the transfer of a business as a going concern, art. 7.1º). N1. - `NO_SUJETA_LOCALIZACION`: not subject by the place-of-supply rules (intra-community or non-EU services, arts. 69 and 70). N2. - `ISP_ART_84_2_A` … `ISP_ART_84_2_F`: reverse charge (the invoice states «inversión del sujeto pasivo»), art. 84.Uno.2.º letters a) (supplier not established in Spain), b) (unwrought or semi-finished gold), c) (scrap, waste and recovery materials, plastic, paper, cardboard, glass and textile waste, and semi-finished non-ferrous metal products), d) (greenhouse gas emission allowances), e) (certain real estate supplies: in insolvency proceedings, with the exemption waived, or enforcing a security) and f) (construction or renovation works). S2. - `ISP_ART_84_2_G`: reverse charge of letter g) (silver, platinum, palladium, mobile phones, consoles, laptops and tablets). The law requires these supplies to be invoiced in a special series, so an invoice line that carries it is rejected with `REVERSE_CHARGE_CASE_NOT_SUPPORTED`. - `EXENTA_ART_140`: investment gold exemption, art. 140 bis (usually with `regime_key` `04`). E6. - `REGIMEN_ART_129` (agriculture, livestock and fishing, arts. 124 to 134 bis), `REGIMEN_ART_135` (second-hand goods, art and antiques), `REGIMEN_ART_141` (travel agencies), `REGIMEN_ART_154` (equivalence surcharge) and `REGIMEN_ART_163_DECIES` (cash basis, arts. 163 decies to 163 sexiesdecies): operations of special regimes, which VeriFactu identifies by the regime key rather than by an exemption code. An invoice line that carries one is rejected with `EXEMPTION_REGIME_NOT_SUPPORTED_IN_VERIFACTU`; declare the regime with `regime_key` instead. - `OTRO`: any other provision. Requires the text in `exemption_reason_text`. E6.
- **default_exemption_reason_text** `string`: Custom exemption text. Only used when `default_exemption_reason` is `OTRO`, where it is mandatory — same rule as in the invoice line.
- **apply_equivalence_surcharge** (required) `boolean`: Whether the freelancer is under the equivalence surcharge regime. **Business rule**: If `true`, the `default_equivalence_surcharge` field is REQUIRED.
- **default_equivalence_surcharge** `number`: Default equivalence surcharge, as the configuration holds it. It is what is stored, not what a request accepts (see `EquivalenceSurchargePercentage`): a configuration saved with the `0.625` surcharge of VAT at 5 %, before it was corrected to 0.62, is returned as `0.625` until it is updated. **Business rule**: REQUIRED if `apply_equivalence_surcharge` is `true`. (example: 5.2)
- **apply_irpf** (required) `boolean`: Whether IRPF withholding should be applied to invoices. Defaults to `false`: no withholding is applied until the user declares one (a rate nobody declared is never invented). **Business rule**: If `true` and `irpf_exempt` is `false`, the `default_irpf_rate` field is REQUIRED.
- **default_irpf_rate** `number`: Default IRPF for new invoices, as the configuration holds it. It is what is stored, not what a request accepts (see `IrpfPercentage`): a configuration saved with a rate the table no longer has is returned as it is until it is updated. **Business rule**: REQUIRED if `apply_irpf` is `true` and `irpf_exempt` is `false`. (example: 15)
- **irpf_exempt** `boolean`: Whether the freelancer is exempt from IRPF withholding (e.g., business start). **Note**: When `true`, any provided `default_irpf_rate` is saved but not applied to invoices. This allows pre-configuring the rate for when the exemption ends.
- **default_payment_method**: Default payment method for new invoices. If NONE is selected, no payment information will be shown on the invoice.
- **payment_term_days** `integer`: Default payment term in days (0-365). Null means no default term.
- **proforma_validity_days** `integer`: Default validity term in days for new proformas (0-365). Null means no default: proformas are created without an expiry date. UI-only default: the dashboard uses it to prefill `valid_until` when creating a proforma (issue date + N days, editable). It is never applied server-side, so the public API contract of `valid_until` does not change.
- **withholding_options**: The withholding (IRPF) rates this company can put on its invoices, deduced from its NIF, and the one suggested by default. Read-only: it is ignored if sent. Use it to build the IRPF picker of this company instead of the whole list of `GET /v1/tax-types`, which is the same for everyone.

## ErrorResponse

Error response shared by all BeeL. APIs.

The payload carries **two contracts at once** (additive, non-breaking):

- **Legacy** (`success`, `error.{code,message,details}`, `meta`) — kept
  intact for existing consumers.
- **RFC 9457** (`type`, `title`, `detail`, `instance`) — new fields
  for integrators following Problem Details for HTTP APIs. The
  `type` URI is the stable, shareable link to the error's
  documentation page (e.g. `https://docs.beel.es/errors/{code}`).

Future migration: the legacy fields will be deprecated via
`Deprecation`/`Sunset` headers after a sufficient adoption window,
and the response Content-Type will move to
`application/problem+json`.

- **success** (required) `boolean`: No description (example: false)
- **error** (required) `ErrorDetail`
- **meta** `ResponseMeta`
- **type** `string` (uri): Stable URI that identifies the problem type and where the integrator will find its documentation. (example: "https://docs.beel.es/errors/INVOICE_NO_LINES")
- **title** `string`: Short summary of the problem type. Stable between occurrences of the same `type`. (example: "INVOICE_NO_LINES")
- **detail** `string`: Specific message for this occurrence, localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English. Matches the legacy `error.message`. (example: "The invoice must have at least one line")
- **instance** `string` (uri-reference): URI that identifies the specific occurrence of the problem — typically the path of the affected resource. (example: "/v1/invoices/abc-123")

## ErrorDetail

- **code** (required) `string`: No description (example: "VALIDATION_ERROR")
- **message** (required) `string`: No description (example: "The provided data is not valid")
- **details** `object`: No description (example: {"field":"specific error message"})

## ExemptionReason

Tax exemption reason code per the Spanish VAT Law (Ley 37/1992, LIVA), with the
VeriFactu code each one is reported as.

- `EXENTA_ART_20`: exempt, art. 20 (domestic operations such as medical, educational,
  cultural and financial services, or housing rentals). E1.
- `EXENTA_ART_21`: exempt, art. 21 (exports of goods). E2.
- `EXENTA_ART_22`: exempt, art. 22 (operations treated as exports). E3.
- `EXENTA_ART_24`: exempt, art. 24 (free zones, warehouses and customs regimes). E4.
- `EXENTA_ART_25`: exempt, art. 25 (intra-community supplies of goods). E5.
- `EXENTA_ART_26`: exempt, art. 26 (intra-community acquisitions of goods). It exempts the
  buyer's acquisition, not a supply the seller invoices, so an invoice line that carries it
  is rejected with `EXEMPTION_NOT_FOR_ISSUED_INVOICE`; a supply to another Member State is
  `EXENTA_ART_25`.
- `NO_SUJETA_ART_7_9`: not subject under art. 7 (such as the transfer of a business as
  a going concern, art. 7.1º). N1.
- `NO_SUJETA_LOCALIZACION`: not subject by the place-of-supply rules (intra-community
  or non-EU services, arts. 69 and 70). N2.
- `ISP_ART_84_2_A` … `ISP_ART_84_2_F`: reverse charge (the invoice states «inversión del
  sujeto pasivo»), art. 84.Uno.2.º letters a) (supplier not established in Spain), b) (unwrought
  or semi-finished gold), c) (scrap, waste and recovery materials, plastic, paper, cardboard, glass and textile waste, and semi-finished non-ferrous metal products), d) (greenhouse gas emission
  allowances), e) (certain real estate supplies: in insolvency proceedings, with the exemption
  waived, or enforcing a security) and f) (construction or renovation works). S2.
- `ISP_ART_84_2_G`: reverse charge of letter g) (silver, platinum, palladium, mobile phones,
  consoles, laptops and tablets). The law requires these supplies to be invoiced in a special
  series, so an invoice line that carries it is rejected with
  `REVERSE_CHARGE_CASE_NOT_SUPPORTED`.
- `EXENTA_ART_140`: investment gold exemption, art. 140 bis (usually with `regime_key`
  `04`). E6.
- `REGIMEN_ART_129` (agriculture,
  livestock and fishing, arts. 124 to 134 bis), `REGIMEN_ART_135` (second-hand goods,
  art and antiques), `REGIMEN_ART_141` (travel agencies), `REGIMEN_ART_154` (equivalence
  surcharge) and `REGIMEN_ART_163_DECIES` (cash basis, arts. 163 decies to 163
  sexiesdecies): operations of special regimes, which VeriFactu identifies by the regime
  key rather than by an exemption code. An
  invoice line that carries one is rejected with `EXEMPTION_REGIME_NOT_SUPPORTED_IN_VERIFACTU`;
  declare the regime with `regime_key` instead.
- `OTRO`: any other provision. Requires the text in `exemption_reason_text`. E6.

Type: `string` — one of: EXENTA_ART_20, EXENTA_ART_21, EXENTA_ART_22, EXENTA_ART_24, EXENTA_ART_25, EXENTA_ART_26, EXENTA_ART_140, NO_SUJETA_ART_7_9, NO_SUJETA_LOCALIZACION, ISP_ART_84_2_A, ISP_ART_84_2_B, ISP_ART_84_2_C, ISP_ART_84_2_D, ISP_ART_84_2_E, ISP_ART_84_2_F, ISP_ART_84_2_G, REGIMEN_ART_129, REGIMEN_ART_135, REGIMEN_ART_141, REGIMEN_ART_154, REGIMEN_ART_163_DECIES, OTRO


---

Full OpenAPI spec: https://docs.beel.es/api/openapi