Nodea API v1 — introduction: base URL, tokens, scopes, limits | Nodea
The Nodea API (version v1) gives you programmatic access to everything the /app panel offers: website and heartbeat monitoring, alert integrations and escalations, servers, SSH keys, DNS zones, Vault devices, and your account (profile, tickets, billing, domains, hosting, migrations). It is a fully RESTful interface that accepts and returns JSON, and every resource is scoped to the token owner.
This page is the introduction — it covers the base URL, authentication, permission scopes, rate limits, error format, and pagination. Documentation for individual modules (endpoints, fields, examples) lives in separate entries in this collection.
Base URL
All API v1 paths are relative to a single prefix:
https://app.nodea.io/api/v1
For example, the token-identity endpoint is GET /api/v1/me, and the list of monitored sites is GET /api/v1/websites. All responses have Content-Type: application/json. When sending data, set the Accept: application/json and Content-Type: application/json headers.
Authentication
API v1 is protected by the Passport guard (auth:api). You authenticate with a Personal Access Token (PAT) — a long-lived OAuth token you generate yourself in the panel.
How to generate a token
- Sign in to the panel and go to account settings → API Tokens (
/app/account/api-tokens). - Click Create token, give it a name, and select only the scopes the integration actually needs.
- Copy the full token value immediately — it is shown only once. Afterwards the panel displays only the token's name and its scopes.
Authorization header
Attach the token to every request in the Authorization header as a Bearer token:
Authorization: Bearer 1|AbCdEf0123456789...
A request without a valid token — or with a revoked one — returns 401 Unauthorized. You can revoke a token at any time in the panel; revocation takes effect immediately.
Scopes (permission tiers)
A token does not grant full account access — it carries only the permissions you select when you create it. Scopes are organized into 4 module groups, each at three tiers: read (listing and reading), write (create, update, and non-destructive actions — e.g. "run now", pause, test notification), and delete (irreversible actions — resource removal, VM stop, hosting termination).
That is 12 scopes in total (4 groups × 3 tiers):
| Group | Scopes | What it authorizes |
|---|---|---|
| monitoring | monitoring:readmonitoring:writemonitoring:delete | Websites, heartbeats, reports, and status pages. read = lists and details; write = create/edit, "run now", pause/resume, maintenance windows; delete = remove a monitor together with its history. |
| alerting | alerting:readalerting:writealerting:delete | Notification integrations, notification groups, escalation policies, and sharing. write includes sending a test notification; delete = remove an integration/policy/share. |
| infra | infra:readinfra:writeinfra:delete | Servers, SSH keys, DNS zones, and Vault devices. write = create/edit and operational actions; delete = destructive actions such as stopping a VM or removing a key/zone. |
| account | account:readaccount:writeaccount:delete | Profile, tickets, billing, domains, hosting, and the migrator. delete = irreversible actions such as hosting termination. |
The rule is simple: grant a token the least privilege it needs. An integration that only reads monitoring status needs just monitoring:read — do not give it :write or :delete. Endpoints also inherit the same feature flags (Pennant) as the panel, so if a module is disabled for your account, no token will unlock it.
A request with a token that lacks the required scope returns 403 Forbidden.
Rate limit
API v1 is limited to 240 requests per minute per token. The counter is keyed by token (tokenless requests fall back to a per-IP limit). Once you exceed the limit you get 429 Too Many Requests; the X-RateLimit-Limit, X-RateLimit-Remaining, and Retry-After headers tell you when to retry. Cache responses and avoid polling in tight loops.
Error format
Errors are returned as JSON of the shape:
{
"message": "Human-readable description, ready to display.",
"code": "optional_machine_code"
}
On validation errors (422) the response also includes an errors object with per-field messages. The HTTP status codes the API uses:
| Code | Meaning |
|---|---|
400 | Bad Request — the request is malformed. |
401 | Unauthorized — missing, invalid, or revoked token. |
403 | Forbidden — the token lacks the required scope, or the module is disabled. |
404 | Not Found — the resource does not exist or does not belong to the token owner. |
409 | Conflict — the action conflicts with the resource state (e.g. a duplicate). |
422 | Unprocessable Entity — validation error (details in errors). |
429 | Too Many Requests — rate limit exceeded. |
502 | Bad Gateway — an upstream dependency failed (e.g. an infrastructure provider). |
503 | Service Unavailable — temporary outage (e.g. maintenance mode). |
Pagination
List endpoints are paginated. Control the page size with the per_page parameter (default 20, maximum 100) and the page number with page. The response carries a data array plus pagination metadata (current page, page count, total records).
Endpoints that browse very long histories (e.g. individual monitoring runs) use simplePaginate — they return only "next/previous page" cursors without counting every record, which is far cheaper at millions of rows. Iterate them by following the next-page link rather than computing the page count up front.
Example: curl
The simplest way to test a token is the GET /api/v1/me endpoint, which returns the token owner's identity and granted scopes.
Without a token — 401:
curl -i https://app.nodea.io/api/v1/me
HTTP/2 401
Content-Type: application/json
{ "message": "Unauthenticated." }
With a valid token — 200:
curl -s https://app.nodea.io/api/v1/me \
-H "Authorization: Bearer 1|AbCdEf0123456789..." \
-H "Accept: application/json"
{
"data": {
"id": 42,
"name": "Jane Doe",
"email": "jane@example.com",
"scopes": ["monitoring:read", "alerting:read"]
}
}
Once this works, move on to the documentation for a specific module — each one describes its endpoints, parameters, and request examples.
What is the Nodea API base URL?
All API v1 endpoints are relative to the prefix https://app.nodea.io/api/v1 — e.g. GET /api/v1/me or GET /api/v1/websites. Responses are JSON.
How do I get an API token?
Generate a Personal Access Token in the panel under API Tokens (/app/account/api-tokens). Name it, select the scopes you need, and copy the value — it is shown only once.
How do I pass the token in a request?
Attach the token in the Authorization header as a Bearer token, e.g. Authorization: Bearer 1|AbCd... A request without a valid token returns 401 Unauthorized.
How many scopes are there and what do they cover?
There are 12 scopes: 4 groups (monitoring, alerting, infra, account) at 3 tiers each (read/write/delete). read = read access, write = create/edit and non-destructive actions, delete = irreversible actions. Grant a token only the scopes it needs.
What is the rate limit?
240 requests per minute per token. Once exceeded you get 429 Too Many Requests; the Retry-After header tells you when to retry.
How does pagination work?
Lists are paginated with per_page (default 20, max 100) and page. Endpoints with very long histories use simplePaginate — iterate them by following the next-page link.
