Local API
Everything the web interface can do is also available as a JSON API – right in your network, no cloud involved. The interface itself uses the very same API. You authenticate with an API key, and every node ships the complete reference as an OpenAPI description.
Overview
| What | Value |
|---|---|
| Base URL | http://<node>:8080/api/ – HTTP and HTTPS run on the same port |
| Format | JSON; timestamps in ISO 8601 and UTC |
| Authentication | API key as Authorization: Bearer node64_… or the browser session |
| No login needed | only GET /api/health (for Docker) and /api/push/{token} (heartbeats) |
| Reference | /api/docs and /api/openapi.json (OpenAPI 3.1) on the node |
| Modules | endpoints of a disabled module return 404 |
In the examples, node64.lan:8080 stands for your node. It's easiest to put your key in a variable once:
export N64="http://node64.lan:8080"
export N64_KEY="YOUR_API_KEY"Reference on the node: /api/docs and /api/openapi.json
Every node comes with its own matching API reference:
/api/docs– the API menu item: all endpoints grouped by area (node, health checks, DynDNS, DNS64, PROXY64, certificates …) plus the management of your API keys./api/openapi.json– the same description as OpenAPI 3.1, e.g. for Postman, Insomnia or a code generator.
Both require you to be logged in (session or API key). To fetch the description from a script:
curl -H "Authorization: Bearer $N64_KEY" -o openapi.json "$N64/api/openapi.json"Creating an API key
- Open the API menu item (
/api/docs) and go to the API keys section. - Enter a name that describes the purpose, such as
backup-scriptorprometheus(1 to 100 characters), and click Create. - Copy the key right away. It starts with
node64_and is shown only this once; Node64 stores only a hash.
The list shows name, short hint, creation date and "last used". Delete keys you no longer need right there. With an existing key you can also do this via the API:
# create another key – the key only appears in this response
curl -X POST -H "Authorization: Bearer $N64_KEY" -H "Content-Type: application/json" \
-d '{"name": "homeassistant"}' "$N64/api/keys"
# list keys (without the key itself) and delete one
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/keys"
curl -X DELETE -H "Authorization: Bearer $N64_KEY" "$N64/api/keys/3"There are no restricted keys. So create one key per purpose, keep it as safe as a password and delete it once you don't need it anymore. More in Login & security.
Authentication
Send the key in the Authorization header with every request:
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/status"- The key only works for paths under
/api/. AI applications use separate MCP keys (mcp64_…) – see AI interface (MCP). - Requests with an API key need no CSRF token – that's only required for the browser session.
- Every use updates the key's "last used". Changes made with an API key appear in the audit log with the origin
api:<key name>. The optionalX-Agent-Actorheader sets the name that shows up there as the actor. - If the web interface uses its self-signed certificate, use
http://inside your network, or download the certificate under Settings and pass it to curl with--cacert– or set up a proper certificate with the certificate management.
Error format
Errors come back as JSON with an error field, and for invalid input often with field as well:
{"error": "authentication required"}
{"error": "...", "field": "interval_seconds"}| Status | Meaning |
|---|---|
400 | invalid JSON |
401 | authentication required (no key, no session) or invalid api key |
403 | CSRF token missing – only with a browser session and no API key |
404 | not found – or the responsible module is disabled |
409 | action not possible in the current state, e.g. "check now" on a push check |
422 | invalid input (the field is named in field) |
429 | too many requests per IP (Retry-After: 10) or too many invalid keys (5 attempts, then one every 30 seconds) |
502 | endpoints that talk to ipv64.net: ipv64 unreachable |
Examples
Health, status and modules
# health, no login needed: {"status":"ok","version":"…","time":"…"}
curl "$N64/api/health"
# dashboard data: node, modules, summary per module, ipv64 link
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/status"
# modules with version and state (name, version, enabled, running, last_error …)
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/modules"
# including each module's changelog, in English
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/modules?changelog=1&lang=en"
# enable or disable a module
curl -X POST -H "Authorization: Bearer $N64_KEY" "$N64/api/modules/dns64/enable"
curl -X POST -H "Authorization: Bearer $N64_KEY" "$N64/api/modules/dns64/disable"Listing checks
# all checks
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/checks"
# filtered by type, tag or search term
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/checks?type=http"
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/checks?tag=nas&q=backup"
# statistics of one check for the last 24 hours
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/checks/CHECK_TOKEN/stats?range=24h"Every check has a 32-character token that identifies it in all further calls.
Creating a check
curl -X POST "$N64/api/checks" \
-H "Authorization: Bearer $N64_KEY" -H "Content-Type: application/json" \
-d '{
"name": "Website",
"type": "http",
"target": "https://example.com/",
"interval_seconds": 60,
"retries": 1,
"stabilize": 3,
"params": {"accept_status": "200-299"}
}'
# measure right now (response 202)
curl -X POST -H "Authorization: Bearer $N64_KEY" "$N64/api/checks/CHECK_TOKEN/run"name, type and – except for push checks – target are required. The response (201) contains the new check including its token. All fields and defaults are listed in the /api/docs reference and under Health checks.
Push check and heartbeat
With a push check, your script reports in by itself – perfect for backups and cron jobs. If the ping doesn't arrive within the period plus grace time, the check goes down.
# create a push check: once a day, one hour of grace
curl -X POST "$N64/api/checks" \
-H "Authorization: Bearer $N64_KEY" -H "Content-Type: application/json" \
-d '{"name": "Nightly backup", "type": "push",
"params": {"period_seconds": 86400, "grace_seconds": 3600}}'
# the response contains "push_url"# heartbeat – no login needed, GET or POST
curl -fsS -m 10 "$N64/api/push/CHECK_TOKEN"
# report a failure with a short message (200 characters max.)
curl -fsS -m 10 "$N64/api/push/CHECK_TOKEN?status=down&msg=backup+failed"
# send output along (up to 4 KB, stored with the measurement)
curl -fsS -m 10 --data-binary @backup.log "$N64/api/push/CHECK_TOKEN"
# typical cron job
/usr/local/bin/backup.sh \
&& curl -fsS -m 10 "$N64/api/push/CHECK_TOKEN" \
|| curl -fsS -m 10 "$N64/api/push/CHECK_TOKEN?status=down&msg=backup+failed"- At least 1 second between pushes, at most 60 per minute per check.
- Unknown tokens get the same response – so the URL gives nothing away.
- If the node isn't the only one measuring the check, it forwards the push via ipv64 to the other measuring nodes. Without a connection to ipv64 it then responds with
503.
Fetching a certificate
Certificates from the central management can be pulled onto other devices via the API – for example with a cron job on your NAS, router or Proxmox.
# list certificates (without keys) – this shows the "id"
curl -H "Authorization: Bearer $N64_KEY" "$N64/api/certs"
# certificate with chain and the private key as separate files
curl -fsS -H "Authorization: Bearer $N64_KEY" -o fullchain.pem \
"$N64/api/certs/7/bundle?format=fullchain"
curl -fsS -H "Authorization: Bearer $N64_KEY" -o privkey.pem \
"$N64/api/certs/7/bundle?format=key"
# everything as a ZIP: fullchain.pem, cert.pem, chain.pem, privkey.pem
curl -fsS -H "Authorization: Bearer $N64_KEY" -o cert.zip "$N64/api/certs/7/bundle"format | Contents |
|---|---|
zip (default) | fullchain.pem, cert.pem, chain.pem, privkey.pem |
fullchain | certificate with chain |
cert / chain | only the certificate or only the chain |
key | private key |
pem | full chain and key in one file |
- The
ETagheader is the certificate's fingerprint. Send it back asIf-None-Matchand Node64 responds with304as long as nothing has changed.X-Cert-Not-Aftergives the expiry date. - Downloads that include the private key (
key,pem,zip) are recorded in the audit log. - For Windows, NAS devices and routers there's a password-protected PKCS#12 file:
POST /api/certs/{id}/p12with{"password": "…"}.
Create a status page and post an announcement
You manage status pages via /api/status-pages – what they can do is described under Status pages. You set a password with "password" ("-" removes it). It is never returned, only has_password. The API still accepts "groups": the entries set selection and order – including the order of the groups, by first appearance –, "label" the display name; the names of the groups are ignored, and the page is arranged by the health check groups as long as "hc_groups" is on (default true; false = a list without headings). New pages have "publish_node": true.
# Create a page with one group – the response contains the "id"
curl -X POST -H "Authorization: Bearer $N64_KEY" -H "Content-Type: application/json" \
"$N64/api/status-pages" -d '{
"title": "My homelab", "slug": "homelab", "enabled": true,
"layout": "list", "days": 90, "show_uptime": true,
"groups": [{"name": "Websites", "items": [
{"token": "CHECK_TOKEN", "label": "Blog"}
]}]
}'
# Publish an announcement (level info, warning or danger)
curl -X POST -H "Authorization: Bearer $N64_KEY" -H "Content-Type: application/json" \
"$N64/api/status-pages/3/notices" \
-d '{"title": "Router maintenance", "level": "info", "text": "Briefly offline tonight from 10 pm."}'
# Add an update and mark as resolved
curl -X PUT -H "Authorization: Bearer $N64_KEY" -H "Content-Type: application/json" \
"$N64/api/status-pages/3/notices/12" -d '{"text": "Done, all good.", "resolve": true}'
# Upload a logo (PNG, JPEG, WebP or SVG up to 256 KiB) or remove it
curl -X PUT -H "Authorization: Bearer $N64_KEY" -H "Content-Type: image/png" \
--data-binary @logo.png "$N64/api/status-pages/3/logo"
curl -X DELETE -H "Authorization: Bearer $N64_KEY" "$N64/api/status-pages/3/logo"The page's public paths (status.json, badges, feed) need no API key – see status.json, badges and feed.
Fetch Prometheus metrics
All figures of the node and its modules in Prometheus text format – with the same API key. Setting up Prometheus and the full list of metric names are under Prometheus.
curl -s -H "Authorization: Bearer $N64_KEY" "$N64/api/metrics" | grep '^node64_' | headMore endpoints
The full list is in /api/docs. A selection:
| Area | Paths |
|---|---|
| Node | /api/version, /api/settings, /api/overview, /api/logs, /api/logging, /api/audit, /api/ports, /api/retention, /api/update (self-update) |
| Notifications | /api/channels, /api/channels/{id}/test, /api/channel-types, /api/deliveries |
| Health checks | /api/checks, /api/checks/bulk, /api/checks/online-test, /api/maintenance, /api/events, /api/incidents, /api/check-types, /api/status-pages |
| DynDNS | /api/dyndns/status, /api/dyndns/targets, /api/dyndns/history |
| DNS64 | /api/dns64/status, /api/dns64/summary, /api/dns64/records, /api/dns64/groups, /api/dns64/devices, /api/dns64/pause |
| PROXY64 | /api/cdn64/hosts, /api/cdn64/streams, /api/cdn64/access-lists, /api/cdn64/stats |
| Certificates | /api/certs, /api/certs/{id}/renew, /api/certs/{id}/bundle |
| Backup & export | /api/backup, /api/backup/restore, /api/export, /api/import |
| ipv64 & group | /api/ipv64, /api/ipv64/key, /api/link, /api/group |
| Monitoring | /api/metrics – see Prometheus |
The ipv64.net API v2 – the online sibling
Besides your node's local API there is the ipv64.net API v2. It's a separate API on the internet and belongs to your ipv64.net account.
| Local Node64 API | ipv64.net API v2 | |
|---|---|---|
| Where | on your node, inside your network | at ipv64.net on the internet |
| Key | Node64 API key (node64_…) | ipv64 API key from your account |
| What for | everything this node can do: checks, modules, certificates, backup … | your ipv64 account: domains, DNS records, online health checks and more |
| Docs | /api/docs on the node | ipv64.net/api_v2_docs |
Node64 itself uses the API v2 with the ipv64 API key from its settings, for example for DynDNS and certificates – see Connect to ipv64.net. The two keys are not interchangeable.
Good to know
- CSRF only in the browser: with a browser session,
POST,PUTandDELETEneed theX-CSRF-Tokenheader. With an API key it's not needed. - Per-IP rate limit: too many requests from one address get a
429withRetry-After: 10. For Prometheus, a scrape interval of 15 to 60 seconds is plenty. - Linked to ipv64: all nodes of an account form one system. Checks, maintenance windows and channels can be changed from any node, even if they belong to another node (
owner: other). - Keep it off the internet: the API belongs in your home network. For remote access use a VPN or a secured reverse proxy.
Something unclear, missing, or a question about Node64? Ask in the official forum v64.tech.