Create an invitation
Scopemembers:writeCreates a single-use invitation for a person to join the account with the given
account_role.
token: the acceptance secret, returned once and never readable again, so deliver it to the invitee.invitation_urlis the ready-to-use link built from that same token.grants: the companies aMEMBERstarts with. Omit it, or send[], to invite them with no company access yet; an explicitnullis rejected with422. Grants are only valid forMEMBER, sinceOWNERandADMINreach every company implicitly.account_role:OWNERcannot be invited. An account has exactly one owner, handed over only throughPUT /v1/accounts/{account_id}/owner.send_email: defaults tofalse, so BeeL sends no email and you deliver the token orinvitation_urlyourself. Set it totrueto have the invitation emailed toinvited_emailas well.
Keys are prefixed beel_sk_, and each one carries the scopes it was created with: a key
short of the scope an operation needs is answered 403. The scope an operation requires
is shown next to its title, and the full catalogue lives in the Scopes reference.
Keys are created from the BeeL dashboard. They are secret credentials: do not share them or commit them to source control.
In: header
Path Parameters
Your own account, or an account you provisioned. It — not the credential — decides which account the operation acts on; a 403 is returned when you do not reach it, the same response an account that does not exist gets.
uuidHeader Parameters
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) - Retrying with the same key replays the first response when it was a success (2xx) or a
server error (5xx): same status and body, plus the header
Idempotency-Replay: true. After a 5xx, check whether the operation took effect before retrying with a new key - A 4xx is not stored: the key is released, so the corrected request can reuse it
- Stored responses 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.
| Status | Code | When |
|---|---|---|
400 | INVALID_IDEMPOTENCY_KEY | The key breaks the format rules above. |
409 | IDEMPOTENCY_KEY_PROCESSING | The first request is still in flight. Wait for the Retry-After seconds (2) and retry with the same key. |
409 | IDEMPOTENCY_KEY_MISMATCH | The key was already used with a different body. Use a new key. |
^[a-zA-Z0-9_-]+$length <= 255Email address of the invited person.
email1 <= lengthWho administers the account. Independent of access_level, which says how much access someone has to a given company.
OWNER — full control, including billing, API keys and transferring ownership. Exactly one per account, so it is never an accepted value when you SET a role (inviting a member or changing one's role): both reject it with 422 OWNER_ROLE_NOT_ASSIGNABLE. Ownership moves only through PUT /v1/accounts/{account_id}/owner.
ADMIN — everything an OWNER can do, except transferring ownership.
MEMBER — no account administration. Access to each company is granted individually and reported as access_level; a member only sees the companies granted to them.
"OWNER" | "ADMIN" | "MEMBER"If true, an invitation email with the acceptance link is sent to invited_email in addition to returning the token. Defaults to false (you deliver the token/link yourself).
falseInitial grants (only when account_role is MEMBER). Omit it, or send [], to invite with no company access yet (granted later). An explicit null is rejected with 422 VALIDATION_ERROR.
[]Response Body
application/json
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/invitations" \ -H "Content-Type: application/json" \ -d '{ "invited_email": "ana.garcia@example.com", "account_role": "MEMBER", "send_email": true, "grants": [ { "company_id": "550e8400-e29b-41d4-a716-446655440000", "access_level": "OPERATE" } ] }'{
"success": true,
"data": {
"invitation_id": "a6e6785a-3ea9-406c-b873-17eaf2ed5fc9",
"invited_email": "user@example.com",
"account_role": "OWNER",
"expires_at": "2019-08-24T14:15:22Z",
"token": "string",
"invitation_url": "http://example.com"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "BAD_REQUEST",
"message": "Invalid request"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication is required to access this resource"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "LIVE_CREDENTIAL_REQUIRED",
"message": "This operation changes the real account; it requires a live API key or a dashboard session."
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}{
"success": false,
"error": {
"code": "MEMBER_ALREADY_IN_ACCOUNT",
"message": "That person already belongs to this account."
},
"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": "The invoice must have at least one line",
"instance": "/v1/invoices/abc-123"
}{
"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"
}
}{
"success": false,
"error": {
"code": "UNSUPPORTED_MEDIA_TYPE",
"message": "Unsupported media type: text/plain. Supported: application/json"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"request_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}List the account's invitations GET
Lists the invitations sent to join the account, whatever their `status`. Accepted, revoked and expired invitations stay in the list: the record is the trail of who was granted access to the account's fiscal data.
Retrieve an invitation GET
Returns one invitation of the account, with the same shape the list returns. An invitation stays readable for its whole life: `ACCEPTED`, `REVOKED` and `EXPIRED` ones are returned with their `status`, because the record is the trail of who was granted access to the account's fiscal data and revoking it does not erase it.