---
title: "Get my identity"
method: GET
path: "/v1/me/identity"
tags: ["Identity"]
---

# Get my identity

`GET /v1/me/identity`

## Request

- Base URL: `https://app.beel.es/api`
- URL: `https://app.beel.es/api/v1/me/identity`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `BEEL_SESSION`

Returns the identity of the authenticated principal: the account the credential belongs to,
the person's email, name, logo and interface language, and a description of the credential
itself. Unlike every other operation, it requires no scope — any valid credential
resolves, so a `200` confirms the credential works and tells you which account it belongs
to, and a `401` that it does not.

- **`account_id`:** identifies who the credential belongs to, not what it is currently
  pointed at; selecting a different company with `BeeL-Active-Company` does not change it.
- **`name`:** resolves as `trade_name ?? legal_name` of the active fiscal profile, and is
  `null` until onboarding creates one.
- **`credential`:** describes the credential the call was authenticated with — its type,
  the environment it operates on and the permissions it holds — so a client can adapt what
  it offers instead of discovering the limits through a `403`.
- **Caching:** responses are never cached (`Cache-Control: no-store`).

## Response `200`

Identity of the authenticated principal

- 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: Minimal display identity of the authenticated principal (whoami).
    - `account_id` string, uuid, required: The account the credential belongs to. It identifies who you are, not what you are currently looking at: selecting a different company with `BeeL-Active-Company` does not change it, so a credential health-check can safely key on it.
    - `name` string, nullable: trade_name ?? legal_name of the active fiscal profile. Null pre-onboarding.
    - `email` string, email, required: Email address (minimum valid email is 5 chars, e.g. a@b.co)
    - `logo_url` string, nullable: URL of the active fiscal profile logo, or null.
    - `language` 'es' | 'en' | 'ca': Interface language of the person behind the credential. It is a preference of the person, not of a fiscal profile: the language of invoices and of e-mails are separate settings of each company.
    - `credential` MyCredential: The credential this call was authenticated with. Lets a client discover, in a single request, what it is allowed to do and which environment it operates on, instead of learning it from a `403`.
      - `type` 'api_key' | 'oauth_token' | 'session', required: How the caller authenticated. * `api_key` - a secret key sent as a bearer token. * `oauth_token` - an access token issued by the authorisation server. * `session` - a browser session cookie.
      - `environment` 'TEST' | 'PROD', required: Environment every request made with this credential operates on. For a key it is fixed by its prefix; for a session it follows the `BeeL-Environment` header.
      - `scopes` string[], required: Permissions granted to this credential, each named after the resource it covers and the action it allows. For a key or token these are the scopes it was issued with; for a session they are the permissions its holder's role grants on the account and on the company in focus. Empty means the credential can only read its own identity.
  - `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`: The credential is genuine, but the account's plan does not include API access (`error.code` = `FEATURE_NOT_AVAILABLE`, `error.details.feature_code` = `api_access`). Whoami requires no scope, so for an API key this is the only refusal besides `401`: without `api_access` the key reaches no public endpoint at all, and saying so here — rather than a `401` that reads as "wrong key" — tells a health-check the credential is fine and the plan is not. Browser sessions never get this.
- `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)
