# Scopes

Available permission scopes for API keys.

Scopes control which API endpoints your **API Key** can access. Session cookie authentication (browser dashboard) has full access and is not subject to scopes.

The exact scope each endpoint needs is shown on its page in the [API Reference](/invoices/listCompanyInvoices). Below is the full catalog, grouped in the same order as the API Reference.

## Available scopes

### Invoicing

| Scope | Grants |
|---|---|
| `invoices:read` | List and read invoices, PDFs, previews, bulk PDF, Excel export, and recurring invoices. |
| `invoices:write` | Create, update, delete, duplicate, issue, void, mark paid/sent, schedule and email invoices; manage recurring invoices. |
| `customers:read` | List and read customers; download the CSV template. |
| `customers:write` | Create, update and deactivate customers; bulk operations and CSV / Holded import. |
| `products:read` | List, read and search products. |
| `products:write` | Create, update and delete products; bulk operations. |
| `series:read` | List invoice series. |
| `series:write` | Create, update and delete series; set the default series. |

### Multi-NIF

| Scope | Grants |
|---|---|
| `members:read` | List account members and pending invitations. |
| `members:write` | Change member roles, remove members, set / revoke company grants, transfer ownership, create / revoke invitations. |
| `accounts:read` | Privileged. Read the accounts you manage — list, get one, and read your provisioning usage. |
| `accounts:write` | Privileged. Provision accounts on behalf of their holders, change your access level over them, and end the management relationship. |
| `account:admin` | Privileged. Manage the account's own credentials and billing. |
| `companies:read` | Read a single company. Also required to use the Beel-Active-Company header. |
| `companies:write` | Create, update and delete companies; generate / submit / cancel fiscal representations. |
| `companies:list` | List the account's companies and per-company stats (the company switcher). |
| `payment-connections:read` | List a NIF's payment provider connections (Stripe Connect) and the payment events they received. |
| `payment-connections:write` | Connect and disconnect a NIF's payment provider; retry a payment event and draft an invoice from it. |

### Configuration

| Scope | Grants |
|---|---|
| `configuration:read` | Read VeriFactu configuration and invoice customization options. |
| `configuration:write` | Update VeriFactu configuration, tax configuration and language preferences. |
| `nif:validate` | Validate Spanish NIFs against the AEAT census. |

### Developers

| Scope | Grants |
|---|---|
| `webhooks:read` | List and read webhook subscriptions and their deliveries. |
| `webhooks:write` | Create, update and delete webhook subscriptions, rotate secrets, send test events and retry deliveries. |
| `emails:read` | List sent emails, read a sent email with its body, and read delivery indicators. |
| `logs:read` | List and read API request logs (developer portal). |

<Callout type="info">
  **`accounts:read` and `accounts:write` are never part of the default key.** A key created
  without choosing scopes gets every other scope; these two must be ticked explicitly, and
  only an `OWNER` or `ADMIN` can put them on a key. They are also useless on their own:
  provisioning requires the managed-accounts capability on your account, which BeeL. enables
  on request — without it the calls answer `403` [`FEATURE_NOT_AVAILABLE`](/errors/FEATURE_NOT_AVAILABLE).
  See [Managed accounts](/multi-nif/managed-accounts).
</Callout>

## Webhook scopes

Subscribing to your own events is self-service: `webhooks:read` and `webhooks:write` are ordinary scopes you can tick when creating an API key.

| Scope | Grants |
|---|---|
| `webhooks:read` | List subscriptions, read one, and list its delivery attempts |
| `webhooks:write` | Create, update and delete subscriptions; send a test delivery; rotate the signing secret; retry a delivery |

They are split on purpose: changing a subscription's URL redirects **every** event to another server, so a read-only integration should never carry `webhooks:write`.

## Scope behavior

- **API Keys**: Scopes are assigned when creating the key. Cannot be changed after creation.
- **Session cookies**: Full access, scopes are not enforced (dashboard users).
- **Provisioning scopes** (`accounts:read`, `accounts:write`): never in the default set; tick them explicitly. They need the managed-accounts capability on your account.
- **Scopes do not replace a live key.** Changing members, grants and invitations, your access level over a managed account or its management answers `403` [`LIVE_CREDENTIAL_REQUIRED`](/errors/LIVE_CREDENTIAL_REQUIRED) with a `beel_sk_test_` key, whatever its scopes. Handing ownership over is dashboard-only (`403` [`OPERATION_REQUIRES_SESSION`](/errors/OPERATION_REQUIRES_SESSION)). See [Test and live keys](/multi-nif#test-and-live-keys).
- **`account:admin` is never granted to an API key.** It administers your own account — its API keys, billing and integrations — so it only exists for dashboard sessions; a key can't hold the permission that mints keys.

<Callout type="warn">
  **A scope is a ceiling, not a guarantee.** On an account you manage, the `access_level`
  you hold caps what the key can do whatever its scopes: a key with `invoices:write` on an
  account you hold at `VIEW` cannot issue invoices for it and gets
  `403` [`ACTIVE_COMPANY_NOT_ACCESSIBLE`](/errors/ACTIVE_COMPANY_NOT_ACCESSIBLE) — the same answer as a NIF you
  cannot reach at all. See [Access levels](/multi-nif/managed-accounts#access-levels).
</Callout>

## How scopes are enforced

Each API endpoint requires one or more scopes. The required scope is documented in the [API Reference](/invoices/listCompanyInvoices) for each operation.

If your token is missing a required scope:

```json
{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "The API key lacks the required permissions (scopes) for this operation."
  }
}
```

The response is `403`, and `error.details.missing_scopes` names what the key lacks, comma-separated; a new key with those scopes fixes it, since a key's scopes cannot be changed after creation.

The scope is checked **before** the request is validated: a key without the scope gets this `403` even when the body or the parameters are also wrong, never a `422` or a `400` about them. Fix the key first; the validation errors, if any, come after.

## Requesting scopes

Select scopes when creating the key in [**Settings > API Keys**](https://app.beel.es/ajustes/api-keys). Request only what your integration needs.

## Related

<Related>

- [API keys](/auth/api-keys) — create and rotate the key that carries the scopes
- [Multi-NIF overview](/multi-nif) — which credential acts on which company
- [Managed accounts](/multi-nif/managed-accounts) — the scopes a provisioner needs

</Related>

---

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