Managed accounts
The provisioner flow for agencies and fleets — provision accounts, choose your access level, track their lifecycle, and issue invoices on their behalf.
A managed account is a separate account that a provisioner (an agency / gestoría or a fleet operator) creates and operates on behalf of the account holder. You keep a chosen access level over each account and can issue invoices for them without them ever touching the API.
The endpoints on this page use the privileged provisioner scopes — granted by
BeeL. only on your provisioner key: accounts:write for provisioning and
changing access, accounts:read for tracking your portfolio (list, get,
usage). All results are scoped to the caller: you only ever see accounts you
provisioned.
Quickstart
From zero to invoicing on a business's behalf. Start in sandbox — the same URL,
a beel_sk_test_… key routes there.
Get a provisioning key
Use a key with the accounts:write and accounts:read scopes, in the
Sandbox environment — they cover provisioning and changing access
(accounts:write) plus listing your portfolio and usage (accounts:read). Both
are privileged (provisioned by BeeL, not self-assignable). Add companies:read /
customers:write / invoices:write to operate on their behalf.
Provision the business
One POST /v1/accounts with a tax_profile and access_level: "OPERATE" creates
the account, its NIF (company), default series and VeriFactu config, and returns the
company_id you'll invoice against — plus a one-time claim_token. See
Provision an account.
Issue in their name
Create a customer and POST /v1/companies/{company_id}/invoices with the company_id
the previous step returned. In sandbox it's numbered and (if enabled) submitted to the AEAT test system under
their NIF. See Issue invoices on a managed account's behalf.
Go live
Swap to a beel_sk_live_… key. Production issuing under someone else's NIF needs
their signed fiscal representation (the OPERATE requirement in
Access levels). Optionally hand them the account with the
claim_token so they take ownership while you keep your access.
The full lifecycle
End to end, from an email address to a NIF that invoices.
sequenceDiagram
autonumber
participant You as Provisioner
participant API as BeeL. API
participant Holder as Account holder
You->>API: POST /v1/accounts
API-->>You: 201 account_id + claim_token
You->>API: POST /v1/accounts/{account_id}/companies
API-->>You: 201 company_id
You->>API: POST /v1/companies/{company_id}/activations
You->>API: POST /v1/companies/{company_id}/representation
Holder->>API: signs the fiscal representation
You->>API: GET /v1/companies/{company_id}/issuing-readiness
API-->>You: 200 ready true
You->>API: POST /v1/companies/{company_id}/invoices
Holder->>API: claims the account
You->>API: DELETE /v1/accounts/{account_id}/management
| Stage | Endpoint | Detail |
|---|---|---|
| Provision | POST /v1/accounts | Below |
| Add the NIF | POST /v1/accounts/{account_id}/companies | Companies |
| Switch on an environment | POST /v1/companies/{company_id}/activations | Companies |
| Authorise issuing on their behalf | POST /v1/companies/{company_id}/representation, then the holder signs | Companies |
| Confirm it can issue | GET /v1/companies/{company_id}/issuing-readiness | Overview |
| Take payments | POST /v1/companies/{company_id}/payment-connections/authorizations | Payment connections |
| Operate | POST /v1/companies/{company_id}/invoices | Below |
| Hand over | The holder claims the account | Below |
| End the relationship | DELETE /v1/accounts/{account_id}/management | Below |
Access levels
Your access over a managed account is one of three access_level values — the same
three used everywhere access is granted or reported in BeeL:
| access_level | What the holder can do |
|---|---|
NONE | Cover their subscription. No access to their data. This is the default. |
VIEW | Read their invoices, customers, products, series and fiscal data. |
OPERATE | Everything in VIEW, plus creating and editing them. Issuing on their behalf additionally requires a signed fiscal representation from the account holder. |
Which one do you actually need?
The level is cheap to lower and, after the claim, impossible to raise — so the choice is really "what is the most I will ever need from this account?", asked once, up front.
OPERATEis for platforms that invoice instead of the holder: fleets billing on behalf of their riders, agencies issuing for clients who never log in. It is the only level that lets you create invoices, customers and payment connections under their NIF — and the only one that requires a signed fiscal representation before production issuing works. Take it whenever issuing is part of your product, even if you do not issue on day one.VIEWis for platforms that report on an account they set up: dashboards, reconciliation, "your invoices" screens. You see the data and the readiness state but cannot change anything, so an integration bug can never emit a fiscal document in someone else's name.NONEis for a relationship that is over in practice but not on paper — you provisioned the account, you still pay for it, and you no longer want access to its data. If you also want to stop paying, what you want is ending the management, notNONE.
Access level never affects billing. Whoever provisioned an account pays for its
subscription regardless of the level they keep over it — including NONE.
Provision an account
POST /v1/accounts — accounts:write. Creates a new account and returns a
one-time claim_token — plus a ready-to-use claim_url — to deliver to the holder
so they can set their password and take ownership. The response status
(PROVISIONED · CLAIMED · ACTIVE) tells you where the account stands right after
the call.
It is idempotent by external_ref (your own id for the account): re-sending the
same external_ref returns 201 with the same account id (not 409) and
re-issues a fresh claim_token while the account is still unclaimed — this is how you
resend the claim. For exact response idempotency on network retries (no fresh
token, no re-sent email), also send an Idempotency-Key header: a repeat with the
same key returns the cached response with Idempotency-Replay: true (cached 24h).
Ready-to-invoice in one call
Include a tax_profile to create the account ready to invoice atomically — its
NIF profile, its default invoice series (ordinary F, simplified S, corrective R)
and VeriFactu config are set up in the same request, and the response returns the
company_id you put in the path of every call that invoices for them.
curl -X POST https://app.beel.es/api/v1/accounts \
-H "Authorization: Bearer beel_sk_live_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f8c1e10-3b2a-4c9d-8e7f-1a2b3c4d5e6f" \
-d '{
"email": "autonomo@example.com",
"display_name": "Autónomo Example",
"external_ref": "your-ref-0042",
"language": "es",
"access_level": "OPERATE",
"tax_profile": {
"nif": "12345678Z",
"legal_name": "Autónomo Example",
"entity_type": "INDIVIDUAL",
"address": {
"street": "Calle Mayor",
"number": "10",
"postal_code": "28001",
"city": "Madrid",
"province": "Madrid"
}
}
}'The full field list, with types and defaults, is in Provision an account. Three of them decide the shape of the whole relationship and are worth reading here:
access_levelpicks how much you can do afterwards, and it is the one choice you cannot fully undo: once the holder claims the account, only they can raise it. See Access levels.external_refis your own id for the account, and doubles as the idempotency key described above. Pick something stable in your system — a customer id, not a timestamp.tax_profileis what makes the account able to invoice from the first call. It takes the same fields as creating a NIF, and it is required whenaccess_levelisOPERATE— issuing on someone's behalf needs a NIF to issue under, so omitting it is422. Leave it out only when the holder will register their own NIF on claim.
default_irpf_rate has no default. Omit it and the NIF is created with no
withholding at all — BeeL. never assumes a rate nobody declared. You know your
account holder's regime: send it only when they do withhold (e.g.
"default_irpf_rate": 7 for an autónomo who chose the reduced rate), and 0 only
when they declared themselves exempt. Preselecting a number falsifies their fiscal
declaration.
Response
{
"success": true,
"data": {
"person_id": "9f8c1e10-3b2a-4c9d-8e7f-1a2b3c4d5e6f",
"account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "PROVISIONED",
"claim_token": "claim_one_time_secret",
"claim_url": "https://app.beel.es/reclamar?token=claim_one_time_secret",
"company_id": "550e8400-e29b-41d4-a716-446655440000"
}
}Every field is described in Provision an account. What the shape does not tell you is how two of them interact:
claim_tokenis shown once and never again, so capture it here. Itsclaim_urlis the same token wrapped in the link for the current environment.- A
nullclaim_tokenis not an error — readstatusto know why.nullwithstatus: CLAIMEDorACTIVEmeans the holder already took ownership, so what they need is a password reset, not another claim link. company_idisnullwhen you sent notax_profile. The account exists but has no NIF to invoice under yet; get it back later fromGET /v1/accounts/{account_id}/companies.
A 409 is returned when the email already belongs to a BeeL. account this request can
neither reuse idempotently (same external_ref) nor reactivate. Branch on
error.code:
error.code | What it means for you |
|---|---|
PROVISIONING_ACCOUNT_CLAIMED | You did manage this account and ended it, but its holder has already claimed it. It is theirs now — ask them to grant you access; provisioning cannot take it back. |
PROVISIONING_EMAIL_ALREADY_REGISTERED | The email belongs to an account you never managed, one someone else manages, or one whose management someone else ended. Use a different email or contact support. |
Change your access level
PATCH /v1/accounts/{account_id}/access-level — accounts:write. Set
access_level to NONE, VIEW or OPERATE. Returns 204.
curl -X PATCH https://app.beel.es/api/v1/accounts/3fa85f64-5717-4562-b3fc-2c963f66afa6/access-level \
-H "Authorization: Bearer beel_sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "access_level": "VIEW" }'A 403 is returned when the account was not provisioned by you, when it does not
exist (existence is not disclosed), or when you try to raise the access level
after the holder has claimed the account — once claimed, only the holder can
raise it; you may keep or lower it.
End your management of an account
DELETE /v1/accounts/{account_id}/management — accounts:write. Returns 204.
You lose access to the account and its NIFs stop counting towards your billable usage
from the next billing cycle. Nothing is deleted or anonymised: the holder keeps the
account, its NIFs and its invoices, and becomes responsible for their own
subscription.
curl -X DELETE https://app.beel.es/api/v1/accounts/3fa85f64-5717-4562-b3fc-2c963f66afa6/management \
-H "Authorization: Bearer beel_sk_live_xxx"Reversible only while the account stays unclaimed. If the holder has not claimed
it, provisioning the same email again reactivates that same account — same holder,
NIFs and invoices — under the external_ref and access_level of the new request.
Once they claim it, provisioning returns 409 PROVISIONING_ACCOUNT_CLAIMED: getting
the management back then requires their consent, not just their email address. Only
the manager who ended the relationship can reactivate it.
Track the accounts you provisioned
Provisioned accounts move through a lifecycle:
PROVISIONED → CLAIMED → ACTIVE
(created, (holder set (holder registered
pending) password) ≥1 NIF, can operate)Claiming is done by the holder on BeeL., not by you. You deliver the
claim_token; the account holder redeems it on BeeL. — sets a password (if new) and
takes ownership, moving the account PROVISIONED → CLAIMED. There is no public
claim endpoint for you to call: it's a session action on BeeL.'s side, the same
way a member accepts an invitation.
You track the result with the lifecycle endpoints below.
What claiming changes for you
Less than integrators expect, and one thing more than they expect:
- You keep your access. Claiming makes the holder the owner of their account; it
does not evict you. Your
access_levelsurvives untouched. - You keep the bill. Whoever provisioned an account pays for its subscription
regardless of who owns it or what access level you keep — including
NONE. - You can no longer raise your own access. Before the claim you set it freely; after
it, only the holder can raise it. You may still keep it or lower it. So if you will
ever need
OPERATE, ask for it before you hand the token over, not after. - Reactivation stops being possible. While the account is unclaimed, ending your
management and provisioning the same email again brings the same account back. Once
claimed, that same call returns
409 PROVISIONING_ACCOUNT_CLAIMED— getting the relationship back then needs their consent, not just their email address.
List
GET /v1/accounts — accounts:read. Newest first, cursor-paginated. Only the
accounts you provisioned. Filter by status, or look one up by your own
external_ref (returns 0..1 accounts; an unknown external_ref returns an empty
list, never an error).
curl "https://app.beel.es/api/v1/accounts?status=ACTIVE&limit=50" \
-H "Authorization: Bearer beel_sk_live_xxx"Filters, page size and the response fields are in List provisioned accounts. Two habits make this endpoint the one you reconcile against:
- Look accounts up by your own
external_ref, not by email. It returns 0..1 accounts, and anexternal_refyou never used returns an empty list rather than an error — so the same call answers "do I already have this customer?" safely. - It is cursor-paginated, not page-numbered: follow
data.next_cursoruntil it comes backnull. A portfolio that grows between two calls will not skip or repeat rows the way an offset would.
Get one
GET /v1/accounts/{account_id} — accounts:read. Returns the authoritative
status and access for one account you provisioned. A 403 is returned when it was
not provisioned by you or does not exist.
List its NIFs
GET /v1/accounts/{account_id}/companies — companies:list (plus an
access_level other than NONE over the account). POST /v1/accounts returns
company_id once, at creation; this is how you get it back afterwards, and the only
way to reach an account provisioned without a tax_profile whose holder registered
their NIF later.
Issue invoices on a managed account's behalf
With OPERATE access, issue invoices for the managed company by putting its
company_id (from the provision response) in the path. In sandbox you can issue
right away; in production, real AEAT submission under the holder's NIF requires
their signed VeriFactu representation first (the OPERATE requirement in
Access levels):
curl -X POST https://app.beel.es/api/v1/companies/550e8400-e29b-41d4-a716-446655440000/invoices \
-H "Authorization: Bearer beel_sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"type": "STANDARD",
"recipient": { "legal_name": "Cliente Final SL", "nif": "B87654321" },
"lines": [ { "description": "Monthly service fee", "quantity": 1, "unit_price": 100 } ]
}'The customer you invoice is created the same way, under the same NIF:
POST /v1/companies/{company_id}/customers. See
Where each identifier goes for the addressing
rules and the Invoices API for the body.
Connect a payment provider (white-label)
With OPERATE access you also connect Stripe to each managed NIF white-label —
the holder authorizes from your own portal and charges are auto-invoiced under the
correct NIF. The connect · list · disconnect endpoints, scopes and OAuth flow are the
same as for a company you own — see Connect Stripe
for the full flow, and Stripe for how connected charges become invoices.
Provisioning usage
GET /v1/accounts/{account_id}/usage —
accounts:read. Returns your provisioning totals, scoped to the caller.
curl https://app.beel.es/api/v1/accounts/3fa85f64-5717-4562-b3fc-2c963f66afa6/usage \
-H "Authorization: Bearer beel_sk_live_xxx"Read nifs as "billable units", not as "real NIFs". The unit that is billed is the
provisioned account: every account you provision counts as 1, including the empty
and unclaimed ones, so nifs normally equals provisioned_accounts and only diverges
when an account holds more than one NIF. An account you provisioned and forgot about is
still on the bill until you
end your management of it.