---
title: "Update a company"
method: PATCH
path: "/v1/companies/{company_id}"
tags: ["Company"]
---

# Update a company

`PATCH /v1/companies/{company_id}`

## Request

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

Updates the editable fields of a company; the set is the one
`UpdateCompanyRequest` declares.

- **Immutable fields:** `nif`, `entity_type` and `legal_form`, once set. Sending one of
  them with a different value answers `422` with a code that names the field; sending the
  value it already has is not a change.
- **`legal_name`:** changing it requires the NIF to pass an AEAT census re-validation. For a
  legal entity (`LEGAL_ENTITY`) the census identifies the company by its NIF alone: the name
  is not verified, so the name sent cannot make it fail. For an `INDIVIDUAL` the name must
  match the one the census holds for that NIF.
- **Census not answering:** if the AEAT census cannot be reached, the change is not
  rejected. The response is `200` with the new `legal_name` stored, and BeeL repeats the
  census check in the background. The outcome of that check is not part of this resource:
  no field of `CompanyData` carries it. To know what the census says about a NIF and a name,
  ask `POST /v1/nif/validate`.
- **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`.
  Other countries' postal codes are free-form.

## Test credentials on a Live company

Once the company is activated in Live, a test credential may only write the fields that
affect how the invoice looks: `logo_url`, `invoice_accent_color`,
`invoice_template_type`, `invoice_language`, `email_language` and `additional_info`. Any
other field describes the real business — fiscal address, legal representative, bank
details, contact data, IAE, activity start date, payment term — and answers
`422 FISCAL_IDENTITY_LIVE_ONLY` from Test, since the company is a single record shared by
both modes. A company not activated in Live accepts the whole body from Test, and sending
a field its current value is never a change.

## What comes back

The `200` returns `CompanyData` with **every field this request accepts**, under the same
name and the same type — so the response is the confirmation of what was stored, and a
later `GET` says the same. A field you never set comes back absent, which means "nothing
stored", not "hidden".

Two things live outside this body and keep their own reads: the invoice series
(`GET /v1/companies/{company_id}/series`) and the rendering block, which is also served
on its own by `GET /v1/companies/{company_id}/invoice-customization`.

## Request body

- UpdateCompanyRequest: Editable fields of a company. `entity_type`, `nif` and `legal_form` are immutable once set; `legal_name` can only be corrected together with a successful AEAT census re-validation of the NIF. For a company that re-validation checks the CIF only — the name is **not verified**, so it can never fail because of the name you send. **Everything here reads back.** The `200` of the update — and every later `GET /v1/companies/{company_id}` — returns `CompanyData`, which carries each of these fields under the same name and the same type. No need to keep your own copy to reconcile: write it, read it back. Five of them also have a read of their own, `logo_url`, `invoice_template_type`, `invoice_accent_color`, `invoice_language` and `email_language`, all returned by `GET /v1/companies/{company_id}/invoice-customization`. A field you never set is **absent** from the read, which means "nothing stored" — not "hidden from you", and not a default. What varies by caller is what you may *write* (see the Test-credential rule below), never what comes back. **From Test, on a company activated in Live, only six of these fields are writable**: `logo_url`, `invoice_accent_color`, `invoice_template_type`, `invoice_language`, `email_language` and `additional_info` — what the invoice *looks like* and the free note it carries. Everything else describes the real business and answers `422 FISCAL_IDENTITY_LIVE_ONLY` unless the call is made with a live credential.
  - `entity_type` 'INDIVIDUAL' | 'LEGAL_ENTITY', nullable: Entity type. IMMUTABLE once set.
  - `legal_name` string, nullable: Legal/fiscal name. Changing it triggers AEAT census re-validation of the NIF. For a self-employed individual the census matches NIF and name together, so a name it does not recognise is rejected. For a legal entity the name is **not verified**: the re-validation only confirms the CIF, and the business name held by the census is the only thing to contrast yours against.
  - `nif` string, nullable: NIF/CIF. IMMUTABLE once set.
  - `legal_form` string, nullable: Legal form (SL, SA, ...). IMMUTABLE once set. Only for LEGAL_ENTITY.
  - `trade_name` string, nullable: Commercial/trade name for the company
  - `address` Address: 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_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`.
  - `phone` string: A phone number as this API accepts it: 9 to 20 characters, and only digits, spaces, dashes, parentheses and an optional leading `+`. Every request that takes a phone number uses this schema. It is `Phone` plus the rules enforced on input. A value this schema accepts always satisfies `Phone`, so anything you send here is something a response can return.
  - `email` string, email, nullable: Email address (minimum valid email is 5 chars, e.g. a@b.co)
  - `website` string, nullable: Website
  - `logo_url` string, nullable: Logo URL
  - `additional_info` string, nullable: Free note printed on the invoice. It is presentation, not fiscal identity, so a test credential may change it even on a company activated in Live. Read it back in `CompanyData.additional_info` (`GET /v1/companies/{company_id}`).
  - `default_iban` string, nullable: IBAN (International Bank Account Number). Required when payment method is BANK_TRANSFER.
  - `default_swift` string, nullable: SWIFT/BIC code
  - `account_holder` string, nullable: Bank account holder
  - `iae` string, nullable: IAE code
  - `activity_start_date` string, date, nullable: Activity start date
  - `default_payment_term` integer, nullable: Default payment term in days
  - `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)
  - `invoice_language` 'es' | 'en' | 'ca', nullable: Language for invoice PDFs
  - `email_language` 'es' | 'en' | 'ca', nullable: Language for emails

## Response `200`

Company updated. The body is `CompanyData`, which echoes every field this request
accepts — the stored value, not the one you sent, so it is also the confirmation of
what a partial update left untouched.

- CompanyResponse
  - `success` boolean
  - `data` CompanyData: A company owned by the account. Its status is described by **two independent axes** — do not conflate them: * **Mode activation** (`in_test` / `in_prod`) — which modes this NIF is activated in, matching the dashboard's Test/Live switch. A company is a single env-agnostic record — there is no Test copy and no Live copy of it; what is per-mode is the *activation*, and a NIF can be activated in Test, in Live, in both, or in neither. It decides where invoices and quota are accounted, NOT whether they reach AEAT. * **AEAT emission capability** (`account_state`, `verifactu_status`, and the `readiness` block requested with `?include=readiness`) — whether invoices are submitted to AEAT with a signed VeriFactu representation. A company can bill in the **Live** mode and still have AEAT emission disabled (e.g. before the VeriFactu representation is signed). `TEST_ONLY` / `in_prod=false` therefore do **not** mean "this account cannot invoice". **Every field `PATCH /v1/companies/{company_id}` accepts is read back here** — same names, same types as `UpdateCompanyRequest`. A field with no value is absent, which means "nothing stored", never "hidden from you": the field set does not depend on who asks (owner, member with `VIEW`, API key or the managed twin `GET /v1/accounts/{account_id}/companies` all see the same one).
    - `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).
  - `meta` ResponseMeta
    - `timestamp` string, date-time
    - `request_id` string

## Other responses

- `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 with write access. That case answers `error.code` `ACTIVE_COMPANY_NOT_ACCESSIBLE`.
- `422`: Validation or business rule error. These codes are specific to this operation: - `FISCAL_IDENTITY_LIVE_ONLY` — the call came from Test on a company that is activated in Live and touched a field outside the six a test credential may write (`logo_url`, `invoice_accent_color`, `invoice_template_type`, `invoice_language`, `email_language`, `additional_info`). Repeat it with a live key; nothing was written. - `IMMUTABLE_NIF`, `IMMUTABLE_ENTITY_TYPE`, `IMMUTABLE_LEGAL_FORM` — the request changes `nif`, `entity_type` or `legal_form`, which cannot change once set. Nothing was written; drop the field from the request. - `NIF_CENSUS_MISMATCH`, `NIF_DE_BAJA`, `NIF_REVOCADO` — the request changes `legal_name` and the AEAT census re-validation rejects it: the census does not recognise the NIF (for an `INDIVIDUAL`, with that name; for a legal entity the name is not verified, only the NIF), or the NIF is deregistered or revoked. Nothing was written. - `POSTAL_CODE_INVALID_ES` — a Spanish postal code in `address` or in `legal_representative.address` does not have 5 digits. Nothing was written. - `INVALID_IBAN` — `default_iban` is not an IBAN: two letters, two digits and up to 30 letters or digits, 15 to 34 characters in all, once it is upper-cased and anything that is not a letter or a digit is removed. Nothing was written. - `SWIFT_INVALID` — `default_swift` is not a SWIFT/BIC of 8 or 11 characters. Nothing was written. - `PHYSICAL_PERSON_CANNOT_HAVE_LEGAL_FORM`, `PHYSICAL_PERSON_CANNOT_HAVE_REPRESENTATIVE` — the company, as it would stand after the change, is an `INDIVIDUAL` with a `legal_form` or a `legal_representative`; both only exist for a `LEGAL_ENTITY`. Nothing was written. - `UNPROCESSABLE_ENTITY` — the generic validation failure, with the offending field in `error.details`.
- `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)
