NewTell a voided invoice from a totally rectified one, without a second call
BeeL
Get StartedMulti-NIFVeriFactuStripeAPI ReferenceChangelog
Accounts

Issue a claim token for an account you provisioned

Scopeaccounts:write

Issues a single-use claim_token for an account you provisioned, so its holder can set a password and take ownership. Privileged: requires the accounts:write scope.

It serves the two moments the alta cannot: giving a holder to an account provisioned without email (send the holder's address in the body and the person is created here, not at provisioning time), and re-issuing a token that expired — they last 30 days, which with a large portfolio starts to bite in the second month.

This is not the member invitation of /v1/accounts/{account_id}/invitations. That one invites an extra person into an account that already has a holder; this one hands the account itself over to its holder. It is the counterpart of the private claim flow the holder completes, not a second way of doing it.

Tokens are a collection with a single live element: issuing again invalidates the previous token — the old link stops working the moment you ask for a new one. A 404 is returned when the account was not provisioned by you or does not exist (existence is not disclosed).


POST
/v1/accounts/{account_id}/claim-tokens
AuthorizationBearer <token>

API Key authentication.

Format: Authorization: Bearer beel_sk_<key>

Scopes: API Keys use the same scopes as OAuth2 tokens. Each key is created with specific scopes that limit which endpoints it can access. The required scope for each endpoint is documented in the operation's security section under OAuth2.

Obtaining Keys: API Keys are managed from the BeeL dashboard

Security: API Keys are secret credentials. Do not share them or store them in source code

In: header

Path Parameters

account_idstring
Formatuuid

Header Parameters

Idempotency-Key?string

Idempotency key to prevent duplicates in sensitive operations.

  • Any unique client-generated string (e.g. an order id). A UUID also works but is not required
  • Allowed characters: letters, digits, _ and - (max 255 chars)
  • If the same key is sent twice, the result of the first operation is returned
  • Keys expire 24 hours after processing

The key is scoped per user and environment, and bound to the request body, so retrying after a network timeout replays the stored response instead of repeating the operation.

StatusCodeWhen
400INVALID_IDEMPOTENCY_KEYThe key breaks the format rules above.
409IDEMPOTENCY_KEY_PROCESSINGThe first request is still in flight. Wait and retry with the same key.
409IDEMPOTENCY_KEY_MISMATCHThe key was already used with a different body. Use a new key.
Match^[a-zA-Z0-9_-]+$
Lengthlength <= 255
email?string

The holder's email address, used as their login. Required when the account has no holder (else 422). If the account already has one, it must match theirs — a different address returns 409 CLAIM_TOKEN_HOLDER_MISMATCH rather than silently replacing the holder.

Formatemail
language?string
Value in"es" | "en" | "ca"

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://app.beel.es/api/v1/accounts/497f6eca-6276-4993-bfeb-53cbbbba6f08/claim-tokens" \  -H "Content-Type: application/json" \  -d '{}'
{
  "success": true,
  "data": {
    "person_id": "087e858e-473c-4f50-b5b0-c1df6c021550",
    "claim_token": "string",
    "claim_url": "http://example.com",
    "expires_at": "2019-08-24T14:15:22Z"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication required"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "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"
  }
}
{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Resource not found"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The provided data is not valid",
    "details": {
      "field": "specific error message"
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  },
  "type": "https://docs.beel.es/errors/INVOICE_NO_LINES",
  "title": "INVOICE_NO_LINES",
  "detail": "La factura debe tener al menos una línea",
  "instance": "/v1/invoices/abc-123"
}
{
  "success": false,
  "error": {
    "code": "UNPROCESSABLE_ENTITY",
    "message": "Data cannot be processed",
    "details": {
      "field": "Specific error description"
    }
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please try again in 60 seconds."
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}
{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error"
  },
  "meta": {
    "timestamp": "2025-01-15T10:30:00Z",
    "request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
  }
}

Provision an account POST

Provisions a new account on BeeL. and returns a one-time `claim_token` to deliver to the account holder so they can set their password and take ownership. The holder can be an self-employed individual or a legal entity. Privileged: requires the `accounts:write` scope (only on your provisioner key). Idempotent by `external_ref`. Use `access_level` to choose the management level you keep over the account (default: billing only — you pay their subscription but do not see their data). If you previously ended your management of this account (`DELETE /v1/accounts/{account_id}/management`) and its holder has not claimed it yet, provisioning the same email **reactivates** that account instead of creating a new one: the same account, holder, NIFs and invoices come back under your management, with the `external_ref` and `access_level` of this request, and it counts towards your billable usage again. Once the holder has claimed the account it is theirs, and only they can grant you access again.

Preview an import of managed accounts POST

Reads the same files as `POST /v1/accounts/imports` and answers the same shape **without writing anything**: no account is provisioned, no NIF is switched on, no series and no customer are created, and nothing is billed. What it resolves per row: the row's own data — including the repairs a spreadsheet export needs, such as a title row ahead of the headers, a postal code that lost its leading zero, an IBAN copied with the spaces of a bank statement, or a number Excel saved as `28031.0` — whether the tax id is in the AEAT register, whether the `external_ref` is already an account of yours, and the **Live activation verdict** that decides whether the import would execute the row at all. `metadata.is_dry_run` is `true` and every write counter in `statistics` is `0`; `statistics.importable` is what a real import would create. **Read `statistics.live_activations_pending` before importing.** Every NIF switched on in Live adds an item to your subscription, and this is the only place to see the total before it is charged. The customers file is checked once for the whole import: whether a customer is new to a given account depends on the account, and that only shows up when the import runs.