---
title: "Get the VeriFactu configuration of a company"
method: GET
path: "/v1/companies/{company_id}/verifactu-configuration"
tags: ["CompanyVeriFactuConfiguration"]
---

# Get the VeriFactu configuration of a company

`GET /v1/companies/{company_id}/verifactu-configuration`

## Request

- Base URL: `https://app.beel.es/api`
- URL: `https://app.beel.es/api/v1/companies/{company_id}/verifactu-configuration`
- Auth: HTTP bearer

Retrieves the VeriFactu configuration of this company. The configuration belongs to
the NIF, so the NIF in the path is what decides which one is returned.

## Response `200`

Configuration retrieved successfully

- object: 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` boolean, required
  - `data` object, required: VeriFactu configuration as resolved by the server. **Response only** — the update body is `UpdateVeriFactuConfigurationRequest`, which carries just `enabled`.
    - `enabled` boolean, required: Whether this tax ID is under the VeriFactu regime in the environment of the request: while it is on, every invoice of this tax ID is registered with the AEAT; while it is off, none is. Always `true` in sandbox.
    - `nif_status` 'ACTIVATED' | 'DEACTIVATED', nullable: Whether the tax ID is registered for VeriFactu submission in this environment (null if VeriFactu was never enabled): - ACTIVATED: registered and ready to submit - DEACTIVATED: not registered, or deregistered (data retained for 30 days) **In Live**, `enabled: true` implies `ACTIVATED`: enabling *is* registering, atomically. **In sandbox that implication does not hold**: `enabled` is always `true` there — it is a constant of the mode, not a decision — while the registration travels asynchronously, so `nif_status` can still be `DEACTIVATED` or null for a while. The former `PENDING` and `ERROR` values described an in-between state that no longer exists.
    - `nif_registered_at` string, date-time, nullable: Successful activation date in VeriFactu production
    - `status` 'DISABLED' | 'UNSIGNED' | 'NOT_ACTIVATED' | 'ACTIVE' | 'ERROR', nullable: Single derived VeriFactu state for the (NIF, environment) of the request — the ONE truth every UI surface (settings banner, activation card, invoice form) reads, so they can no longer contradict each other. Read-only; resolved server-side. Null only if never configured. - DISABLED: VeriFactu not enabled for this account. - UNSIGNED: enabled but the NIF has no signed AEAT representation. - NOT_ACTIVATED: signed, but no API key for the operating environment. - ACTIVE: signed and activated with API key: ready to submit. - ERROR: historical, no longer reachable. Activation is atomic: a failed activation leaves nothing persisted and returns the reason, so no row ever rests in this state. Kept in the enum so old clients keep parsing stored values.
    - `signed` boolean, nullable: Secondary flag: whether the NIF has a signed AEAT representation (per-NIF, shared across environments). Data for the wizard, NOT the gate.
    - `activated` boolean, nullable: Secondary flag: whether the NIF is activated (has an API key) in the operating environment (per-environment). Data, NOT the gate.
    - `pdf_generated` boolean, nullable: Secondary flag: whether a representation PDF artifact exists. Used by the signature wizard as secondary data, NOT the source of truth of the gate.
  - `meta` ResponseMeta
    - `timestamp` string, date-time
    - `request_id` string

## Other responses

- `400`: The request target could not be read as declared, so nothing was looked up. Three causes, all named in `error.details`: a path or query parameter whose value does not parse as its type (`VALIDATION_ERROR` — a UUID that is not a UUID, an unknown enum value, an empty element in a list such as `status=ISSUED,`), a required parameter that was not sent (`MISSING_PARAMETER`), or a header that is meant to carry an identifier and does not (`ACTIVE_COMPANY_HEADER_INVALID`). A list parameter sent entirely empty (`status=`) is not an error: it is the same as omitting it. The fault is in the target, not in the content — which is what `422` is defined over.
- `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.
- `403`: Your account does not own or manage this company, or does not hold the required access over it. A NIF that does not exist answers the same way. That case answers `error.code` `ACTIVE_COMPANY_NOT_ACCESSIBLE`.
- `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
- `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)
