---
title: "Customer accounts — API v1 and MCP | Nodea Documentation"
description: "Customer accounts in the Nodea API: GET /accounts and GET /me, the X-Account-Id header, tokens pinned to an account, the 13 member permissions, account_* error codes and the MCP accounts-list and whoami tools."
url: "https://nodea.io/en/api-docs/accounts"
lang: "en"
updated: "2026-09-24"
---

# Customer accounts — API v1 and MCP | Nodea Documentation

> Customer accounts reference — GET /api/v1/accounts and /me, the account context and X-Account-Id header, tokens pinned to an account, member permissions, account\_\* error codes and MCP accounts-list/whoami.

Nodea's commercial resources — support tickets, billing, domains, DNS zones, hosting and servers backed by a virtual machine — belong to **customer accounts** that a user belongs to as the owner or a member. This entry describes how an integration discovers its accounts and picks the one it acts in: the GET /api/v1/accounts and GET /api/v1/me endpoints, the X-Account-Id header, member permissions and their MCP counterparts (accounts-list, whoami). The general rules are also covered in the “Customer accounts” section of the [API introduction](https://nodea.io/en/api-docs/overview).

## Authentication and scopes

API v1 authenticates with a Passport personal access token via the Authorization: Bearer \<token\> header.

- GET /api/v1/me — **no scope required**: any valid token can check who it is and which account it acts in.
- GET /api/v1/accounts — the account:read scope.

Neither endpoint is gated by a feature flag or an account permission. Rate limit: throttle:api-v1 = 240/min per token user.

## Account context

Every request acts in **one current account**, resolved in this order:

1. the account the token is pinned to (a header cannot change it — another account in the header is 403 account\_mismatch);
2. the X-Account-Id: \<account id\> request header;
3. the user's default account (default\_account\_id);
4. the user's only membership.

The resolved account comes back in the X-Account-Id response header (no header = no context; endpoints that need an account then answer 403 no\_account\_context). Lists of commercial resources return only the current account's resources, and a resource of another account — even another account of the same user — returns 404.

**Tokens.** A token created in the panel (/app/account/api-tokens) is pinned by default to the account you are currently working in; you can pick another account you are a member of, or the “Any account (X-Account-Id header)” option, which creates an unpinned token. Tokens created before customer accounts existed are unpinned — without a header they act in your default account, as before.

## Member permissions

The owner holds every permission (their permissions list contains all 13 flags). A member holds only the flags granted by the owner. Effective access is **token scope AND account permission**.

FlagMeaningWhat it unlocks in API v1 and MCP profileModify account profile— (panel) contactsView and manage contacts— (panel) productsView products and servicesRead hosting (accounts, mailboxes, backups) and servers backed by a virtual machine. manageproductsManage products and services (requires products)Hosting actions (mailboxes, backups, restore, SSL) and actions on a VM-backed server (update, VM start/stop/reboot, WAF, components, clone, SSH test, note). productssoPerform single sign-on for services (requires products)— (SSO is panel-only) domainsView domainsRead domains and DNS zones. managedomainsManage domain settings (requires domains)Nameservers, WHOIS privacy, EPP code request, creating/updating/deleting DNS records. invoicesView and pay invoicesBilling: invoices, wallets, transactions. quotesView and accept quotes— (panel) ticketsView and open support ticketsTickets: list, show, create, reply, close. affiliatesView and manage affiliate account— (panel) emailsView email history— (panel) ordersPlace new orders, upgrades and cancellations— (panel)

Owner-only actions (no flag grants them): terminating a hosting account (DELETE /hosting/{id}) and deleting a server backed by a virtual machine (DELETE /servers/{id}) — a member gets 403 account\_owner\_required.

## API v1 — endpoints

MethodPathScopeDescriptionGET/api/v1/accountsaccount:readThe accounts the token user belongs to — to choose from in the X-Account-Id header. Not paginated. GET/api/v1/me—The token user's identity, default account and the request's current account.

### GET /accounts — response

A data array of AccountResource objects, oldest membership first. **Closed and deleted** accounts are left out (they cannot be selected). A token **pinned** to an account sees only that one account — it does not reveal the user's other accounts. The list is not paginated.

- id (int) — the id for the X-Account-Id header.
- name (string) — the account name.
- role (owner|member) — your role in the account.
- permissions (string\[\]) — the flags you hold in this account (owner: all 13).
- billing\_source (nodea|whmcs|external) — who bills the account. external = Nodea bills the account outside the panel (VAT invoice from wFirma). WHMCS and external accounts have no Nodea wallets (see [Billing](https://nodea.io/en/api-docs/billing)).
- is\_default (bool) — whether this is your default account.
- is\_current (bool) — whether the current request acts in this account.

The account's billing identity (address, tax id, PESEL, Stripe/WHMCS ids) is never returned.

curl -s https://app.nodea.io/api/v1/accounts \\ -H "Authorization: Bearer $NODEA\_TOKEN" \\ -H "Accept: application/json" { "data": \[ { "id": 17, "name": "Jane Doe", "role": "owner", "permissions": \["profile", "contacts", "products", "manageproducts", "productsso", "domains", "managedomains", "invoices", "quotes", "tickets", "affiliates", "emails", "orders"\], "billing\_source": "nodea", "is\_default": true, "is\_current": true }, { "id": 42, "name": "Acme Ltd", "role": "member", "permissions": \["products", "domains", "tickets"\], "billing\_source": "whmcs", "is\_default": false, "is\_current": false } \] }

### GET /me — response

A UserResource object: id, name, email, timezone, currency, created\_at plus the account fields:

- default\_account\_id (int|null) — your default account (used when the token is not pinned and no header was sent).
- current\_account (object|null) — the account **this** request acts in, shaped like a GET /accounts row; null when no account could be resolved.

The endpoint does not return the token's scopes (the MCP whoami tool does). The response carries the X-Account-Id header with the current account id.

curl -i https://app.nodea.io/api/v1/me \\ -H "Authorization: Bearer $NODEA\_TOKEN" \\ -H "X-Account-Id: 42" \\ -H "Accept: application/json" HTTP/2 200 X-Account-Id: 42 { "data": { "id": 7, "name": "Jane Doe", "email": "jane@example.com", "timezone": "Europe/London", "currency": "EUR", "default\_account\_id": 17, "current\_account": { "id": 42, "name": "Acme Ltd", "role": "member", "permissions": \["products", "domains", "tickets"\], "billing\_source": "whmcs", "is\_default": false, "is\_current": true }, "created\_at": "2025-03-01T10:00:00+00:00" } }

### Error codes

- 401 — missing/invalid token.
- 403 — missing account:read scope (/accounts only) or an account-context error from the table below.

HTTPCode (code)When 403account\_forbiddenThe account named by the X-Account-Id header, or the account the token is pinned to, does not exist, you are not its member, or it is closed or deleted; also a malformed header value (anything other than a positive integer). Every case gets the same answer — the API never confirms that someone else's account exists. 403account\_mismatchThe token is pinned to an account and the X-Account-Id header names a different one. 403no\_account\_contextThe endpoint needs an account and none could be resolved (e.g. you belong to several accounts, have no default account and sent no header). 403account\_permission\_deniedYour membership in the current account lacks a required permission. The response carries an extra permission field naming the missing flag. 403account\_owner\_requiredThe action is reserved for the account owner (hosting termination, deleting a server backed by a virtual machine) — no permission flag grants it. 423termination\_lockedDestructive operations (hosting termination, deleting a VM-backed server) are globally locked. The lock is checked **before** account permissions, so the owner gets it too; the resource is left untouched. 404—The resource does not belong to the current account (also when it belongs to another account of yours) — switch accounts with the X-Account-Id header. HTTP/2 403 Content-Type: application/json { "message": "Your role in this account does not grant the 'managedomains' permission.", "code": "account\_permission\_denied", "permission": "managedomains" }

## MCP — account context

The MCP server (/mcp) resolves the current account exactly like API v1: the pinned token's account → the X-Account-Id header **of the MCP connection** (set it in your client configuration next to the Authorization header) → the default account → the only membership. HTTP responses carry the X-Account-Id header. Every tool that works on commercial resources acts in that one account; to work in another account, change the connection header or use a token pinned to that account.

**Connection errors.** An invalid account is refused at the HTTP level before any tool runs: 403 with a JSON {message, code} body and code account\_forbidden (the account does not exist, is foreign, closed or deleted) or account\_mismatch (the token is pinned to a different account than the header).

**Tool errors.** Account denials come back as a tool result with isError: true, and the message ends with a machine suffix:

- (code: account\_permission\_denied, permission: \<flag\>) — missing account permission;
- (code: account\_owner\_required) — owner-only action (hosting-terminate, server-delete of a VM-backed server);
- (code: no\_account\_context) — no account could be resolved;
- (code: termination\_locked) — terminations are globally locked;
- (code: already\_terminated) — hosting-terminate on an already terminated account.

A resource outside the current account returns the usual “… not found or not accessible with your permissions.” message — the same as for a resource that does not exist. Access is token scope AND account permission; the owner holds every permission.

### Permissions per tool group

Tool groupAccount permissionTickets: tickets-list, ticket-get, ticket-create, ticket-reply, ticket-closetickets Billing: billing-invoices, billing-invoice-get, billing-wallets, billing-transactions, billing-creditsinvoices; wallets, transactions and free credits additionally need an account billed by Nodea (a WHMCS account → account\_permission\_denied, the owner included) Domains — read: domains-list, domain-getdomains Domains — actions: domain-set-nameservers, domain-whois-privacy, domain-request-eppdomains + managedomains DNS — read: dns-zones-list, dns-zone-getdomains DNS — records: dns-record-create, dns-record-update, dns-record-deletedomains + managedomains Hosting — read: hosting-list, hosting-get, hosting-emails, hosting-backupsproducts Hosting — actions: hosting-email-create/-update/-delete, hosting-backup-create/-restore, hosting-issue-sslproducts + manageproducts Hosting — hosting-terminateaccount owner only Servers backed by a virtual machine — readproducts Servers backed by a virtual machine — actions (update, VM start/stop/reboot, WAF, components, clone, SSH test, note)products + manageproducts Servers backed by a virtual machine — server-deleteaccount owner only Profile, monitoring, alerting, SSH keys, Vault, servers without a VMnone — personal resources of the user

## MCP — tools

ToolScopeModeDescriptionaccounts-listaccount:readread-only, idempotent**New.** No arguments. Returns {data: \[...\]} — rows as in GET /api/v1/accounts (id, name, role, permissions\[\], billing\_source, is\_default, is\_current). Leaves out closed and deleted accounts; a pinned token sees only its account; oldest membership first. whoami—read-onlyIdentity (id, name, email, timezone), the token's scopes and **new fields**: default\_account\_id, account (the session's current account or null — account tools then answer no\_account\_context) and accounts\[\] (the accounts the token may act in — the same rows as accounts-list).

The other tool changes (tickets, billing, domains, DNS, hosting, servers, profile-update) are described in the entries of the individual modules.

### Example — MCP (JSON-RPC)

{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "accounts-list", "arguments": {} } } { "jsonrpc": "2.0", "id": 1, "result": { "content": \[{ "type": "text", "text": "…" }\], "structuredContent": { "data": \[ { "id": 17, "name": "Jane Doe", "role": "owner", "permissions": \["profile", "contacts", "products", "manageproducts", "productsso", "domains", "managedomains", "invoices", "quotes", "tickets", "affiliates", "emails", "orders"\], "billing\_source": "nodea", "is\_default": true, "is\_current": true }, { "id": 42, "name": "Acme Ltd", "role": "member", "permissions": \["products", "domains", "tickets"\], "billing\_source": "whmcs", "is\_default": false, "is\_current": false } \] } } }

### How do I check which account my token acts in?

Call GET /api/v1/me — the current\_account field describes the current account and the X-Account-Id response header carries its id. In MCP the whoami tool returns the same (the account field).

### Why do I get 404 for a resource I can see in the panel?

The resource belongs to a different account than the request's current account. Send the X-Account-Id header with the right account id (listed by GET /api/v1/accounts) or use a token pinned to that account.

### What does the account\_permission\_denied error mean?

You are a member of the account, but the owner has not granted you the permission this operation needs. The permission field in the response names the missing flag, e.g. managedomains.

## Related

- [Nodea API v1 — introduction: base URL, tokens, scopes, limits | Nodea](https://nodea.io/en/api-docs/overview)
- [Nodea MCP server — endpoint, authentication, OAuth discovery, tools | Nodea](https://nodea.io/en/api-docs/mcp)
- [Billing — API v1 and MCP | Nodea Documentation](https://nodea.io/en/api-docs/billing)

---

Languages: [pl](https://nodea.pl/pl/dokumentacja-api/accounts.md)  
Site index: [llms.txt](https://nodea.io/en/llms.txt)
