CDN64 API: manage names, tunnels and port mapper via API v2

With the CDN64 API (part of the IPv64.net API v2) you switch names in CDN64 on and off, set target, access list and port mappings, pause names and query quota, traffic and events. The page ipv64.net/cdn64 and Node64 use the same endpoints.

Basics: address, authentication, format

All endpoints live under the API v2 base URL; the CDN64 paths start with /cdn64o:

https://ipv64.net/api/v2/cdn64o

Authentication with API key

You authenticate with an API key from Account → API or your account's API key – in a header, not as a parameter:

Authorization: Bearer DEIN_API_KEY
X-API-Key: DEIN_API_KEY

One of the two headers is enough. Without a key the API answers 401 with unauthenticated; if the key is wrong, expired or the account is not active, 401 with invalid_token. With the header X-IPv64-Act-As (account ID or e-mail) you act for an account that allowed you to manage it via account sharing.

Requests and responses

  • Requests with a body are sent as JSON (Content-Type: application/json); form-urlencoded works too. The body may be at most 1 MB.
  • Success: 200 or 201 (created) with the result under data, e.g. {"data": {…}}. Deleting answers 204 without content.
  • Errors: JSON according to RFC 9457 (application/problem+json) with type, title, status, detail and code, for input errors also field. All codes are listed under error codes.
  • Times are ISO 8601 with time zone, e.g. 2026-10-26T14:05:00+01:00.
  • {id} of a name is the numeric ID or the full name, e.g. /cdn64o/hosts/www.deinedomain.ipv64.net.

Rate limit

API v2 limits requests independently of your account class's API limit: per account 300 requests at once, then 10 per second; per IP address 600 at once, then 20 per second. Failed logins are limited per IP to 20 at once, then 12 per minute. Every response carries RateLimit-Limit and RateLimit-Remaining; above the limit you get 429 with Retry-After (seconds).

All endpoints

MethodPathPurpose
GET/cdn64oOverview: quota, edge servers, tunnels, names
POST/cdn64o/hostsSwitch on a name
GET/cdn64o/hosts/{id}Get a name
PATCH/cdn64o/hosts/{id}Change mode, tunnels, pause, WAF/JA4
DELETE/cdn64o/hosts/{id}Switch off a name
PUT/cdn64o/hosts/{id}/targetSet the target (mode 3 only)
GET, PUT/cdn64o/hosts/{id}/aclAccess list
GET, POST/cdn64o/hosts/{id}/mappingsList, create port mappings
DELETE/cdn64o/hosts/{id}/mappings/{mid}Delete a port mapping
GET, PUT/cdn64o/hosts/{id}/serversEdge servers of the name, choose number and connections (Business, Company)
GET/cdn64o/hosts/{id}/eventsEvents of a name
GET/cdn64o/statsStatistics per name and day
GET/cdn64o/protectionProtection statistics of the account
POST/cdn64o/tunnelsRegister a tunnel (done by Node64)
POST/cdn64o/tunnels/{id}/tokenIssue a new tunnel token
DELETE/cdn64o/tunnels/{id}Remove a tunnel
GET, PUT/cdn64o/tunnels/{id}/serversfor all names of a tunnel (older Node64)
GET, PUT/cdn64o/tunnels/{id}/listsBlock and allow list of the tunnel (done by Node64)
GET/plansAccount class limits (no authentication)

The OpenAPI description of API v2 (https://ipv64.net/api/v2/openapi.json) and the page ipv64.net/api_v2_docs describe the other areas of API v2.

Get the overview: GET /cdn64o

Returns your quota, the edge servers, your tunnels and all names of your account in CDN64 in one call. There is no separate list GET /cdn64o/hosts – the names are here under hosts.

curl "https://ipv64.net/api/v2/cdn64o" -H "Authorization: Bearer DEIN_API_KEY"
{
  "data": {
    "quota": {
      "domains":  {"used": 2, "old_cdn": 0, "limit": 5},
      "mappings": {"used": 1, "old_cdn": 0, "limit": 10},
      "traffic_mb": {"used": 1834.2, "old_cdn": 0, "limit": 102400},
      "bandwidth_mbit": 1000
    },
    "edges": [
      {"name": "…", "host": "…", "port": 7844, "ips": ["2001:db8::7", "192.0.2.7"]}
    ],
    "tunnels": [ … ],
    "hosts": [ … ]
  }
}
FieldMeaning
quota.domainsCDN domains in use (used), of which in the former IPv64 CDN (old_cdn), limit of the account class (limit)
quota.mappingsport mappings, same fields
quota.traffic_mbtraffic this month in MB (in + out) and limit in MB
quota.bandwidth_mbitbandwidth of the class in Mbit/s, 0 = unlimited
edgesthe edge servers the tunnel of the requesting node connects to (header X-Node64-Node; without it all servers of the account's tunnels): name, host name, tunnel port, IP addresses, for a server that is currently down standby (true; the node keeps connecting to notice its return), during a failover replaced_by (stand-in) or, at the stand-in, stands_in (the failed one), during load balancing at the new server balance_from (the old one, dropped once the tunnel is up on the new one). The servers per tunnel are in tunnels, those per name in hosts (servers per name).
tunnelsyour tunnels (see tunnels)
hostsyour names, each as a name object

Edge servers of a name: GET and PUT /cdn64o/hosts/{id}/servers

Your account class decides how many edge servers a name uses (servers per name). GET shows the assignment; with PUT, Business (1 or 2 servers, 1 or 2 connections) and Company (1 to all servers, 1 to 4 connections) choose for this name the number of servers (count) and the connections per server (sessions; no effect in mode 3). A missing field stays. Node64 offers a button for this in the row of the proxy host (CDN64 column). The name object shows the same choice under servers.

curl -X PUT "https://ipv64.net/api/v2/cdn64o/hosts/www.deinedomain.ipv64.net/servers" -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" -d '{"count": 3, "sessions": 2}'
{
  "data": {
    "count": 3, "choice": 3, "max": 4, "all": true, "total": 4, "selectable": true,
    "assigned": ["…", "…", "…"],
    "active": ["…", "…", "…"],
    "sessions": 2, "sessions_max": 4
  }
}
FieldMeaning
countnumber of servers of the name; in a PUT the number you want, for Company 0 = all (including future servers). A number stays fixed even when servers are added.
choicethe chosen number (0 = highest of the class, or all for Company)
sessions, sessions_maxconnections per server (in a PUT the number you want) and the highest choice of the class
max, totalhighest number you can choose and number of edge servers overall
alltrue: the class may use all servers (Company)
selectabletrue: the number can be chosen (Business, Company)
assignedthe assigned servers (names)
activethe servers currently in the DNS of the name – if an assigned one is down for more than 3 minutes, its stand-in is listed here
replacedfailover: failed server → stand-in (empty without failover; every name has the same field)

Errors: class without a choice 403 (plan_not_allowed), number out of range 422 (out_of_range), foreign name 404. After a PUT, IPv64.net updates the DNS of the name (event servers_changed); the tunnel of its node connects to the new servers within a minute.

GET and PUT /cdn64o/tunnels/{id}/servers (same fields) remain for older Node64: the PUT sets the choice for all names of the tunnel (and for the tunnel itself while it has no names), the GET shows the one of its first name.

Switch names on, change and switch off

Switch on a name: POST /cdn64o/hosts

FieldRequiredMeaning
fqdnyesname, e.g. www.deinedomain.ipv64.net; must belong to an active domain of your account
modeno1 (default), 2 or 3 – see modes
tunnel_idfor modes 1 and 2ID of a tunnel of your account, e.g. tn_…
source, target, scheme, port, …no (mode 3 only)the target, fields as in PUT …/target

Before switching on, IPv64.net checks: account class with CDN domains, free quota and traffic, name in your account, name not yet in CDN64, domain not in the former CDN, no CNAME and no active DNS failover on the name, and for mode 3 with source=records at least one public A/AAAA address. Then IPv64.net changes the DNS (see DNS). If that fails, nothing is changed (502, dns_update_failed). If the rollback cannot be written either, the name stays in place (also 502, the ID is in detail); remove it later with DELETE /cdn64o/hosts/{id}. Response: 201 with the name object.

curl -X POST "https://ipv64.net/api/v2/cdn64o/hosts" \
  -H "Authorization: Bearer DEIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"fqdn":"www.deinedomain.ipv64.net","mode":3,"source":"fixed","target":"server.example.org","scheme":"https","port":443}'

A name in mode 1 on an existing tunnel:

curl -X POST "https://ipv64.net/api/v2/cdn64o/hosts" \
  -H "Authorization: Bearer DEIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"fqdn":"cloud.deinedomain.ipv64.net","mode":1,"tunnel_id":"tn_DEINE_TUNNEL_ID"}'
Modes 1 and 2 with Node64

Names in modes 1 and 2 are normally created by Node64, which keeps them in sync with its proxy hosts. Without a Node64 that actually opens the tunnel, such a name is not reachable. It is best to set up modes 1 and 2 in Node64.

Get a name: GET /cdn64o/hosts/{id}

curl "https://ipv64.net/api/v2/cdn64o/hosts/www.deinedomain.ipv64.net" -H "Authorization: Bearer DEIN_API_KEY"
{
  "data": {
    "id": 42, "fqdn": "www.deinedomain.ipv64.net", "mode": 3, "wildcard": false,
    "status": "active", "blocked_reason": null, "paused": false, "paused_at": null, "error": null,
    "tunnels": [], "domain_id": 1234, "edges": [ … ], "servers": { … },
    "traffic_month": {"bytes_in": 1048576, "bytes_out": 52428800, "conns": 310, "requests": 2048, "rejected": 3},
    "created_via": "web", "created_at": "2026-10-20T09:12:00+02:00", "updated_at": "2026-10-20T09:12:01+02:00",
    "target": {"source": "fixed", "target": "server.example.org", "addrs": null, "port": 443, "scheme": "https",
               "verify_tls": false, "prefer_ipv6": true, "frontend": 2, "websockets": true, "cache_mb": 0, "cache_minutes": 10},
    "acl": {"default": "off", "list": []},
    "mappings": [],
    "waf": true, "ja4": "block",
    "protection": {"blocked_list": 120, "blocked_acl": 0, "blocked_flood": 4, "blocked_limit": 2, "blocked_waf": 37,
                   "blocked_ja4": 0, "ja4_hits": 15, "blocked_ips": 61, "conns": 310, "conns_v4": 88}
  }
}
FieldMeaning
id, fqdnID and name
mode1, 2 or 3
wildcardwildcard is enabled for the domain
statusactive, blocked (reason in blocked_reason, e.g. traffic) or briefly while creating pending
paused, paused_atname paused, since when
errorlast error or null
tunnelsIDs of the assigned tunnels in order of priority (modes 1 and 2)
domain_idID of the domain the name belongs to
traffic_monthnumbers for this month: bytes in/out, connections, requests, rejections
created_viaweb (ipv64.net/cdn64) or node (API, Node64)
targettarget in mode 3 (otherwise null); with source=records the current addresses are in addrs
aclaccess list
mappingsport mappings
waf, ja4WAF patterns and JA4 level of the name
protectionprotection figures of the last 30 days, fields as in GET /cdn64o/protection

Change mode and tunnels: PATCH /cdn64o/hosts/{id}

All fields are optional; only what you send is changed.

  • mode – switch between 1 and 2. Switching from or to mode 3 is not possible (422, mode_change_not_possible); switch the name off and on again instead.
  • tunnels – list of tunnel IDs of your account, not empty. The order is the priority: the first connected tunnel serves the name. The list replaces the previous assignment.
  • paused – true or false (see below).
  • waf, ja4 – protection on the edge servers (see below).
curl -X PATCH "https://ipv64.net/api/v2/cdn64o/hosts/42" \
  -H "Authorization: Bearer DEIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"tunnels":["tn_ERSTE_NODE","tn_ZWEITE_NODE"]}'

Pause and resume

With paused: true the edge servers stop accepting anything for the name and close open connections; DNS stays on the servers. With paused: false it continues. Response: the name object.

curl -X PATCH "https://ipv64.net/api/v2/cdn64o/hosts/www.deinedomain.ipv64.net" \
  -H "Authorization: Bearer DEIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"paused":true}'

Switch WAF patterns and JA4

waf (true/false) switches the WAF patterns (effective in modes 2 and 3). ja4 sets the level for attack tools: off, count (count only) or block (all modes); other values result in 422 (invalid_field). If ja4_global in GET /cdn64o/protection is count, the servers only count even with block. Every change is listed in the events (waf).

curl -X PATCH "https://ipv64.net/api/v2/cdn64o/hosts/42" \
  -H "Authorization: Bearer DEIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"waf":true,"ja4":"block"}'

Switch off a name: DELETE /cdn64o/hosts/{id}

Switches the name off: the edge server records are deleted, your original A/AAAA records are activated again, and target, access list, port mappings and certificate are removed. Response: 204. If the DNS server rejects the change, you get 502 (dns_update_failed) – try again later.

curl -X DELETE "https://ipv64.net/api/v2/cdn64o/hosts/42" -H "Authorization: Bearer DEIN_API_KEY"

Set the target (mode 3): PUT /cdn64o/hosts/{id}/target

Only for names in mode 3 (otherwise 409, not_mode_3). Fields you leave out keep their previous value. POST /cdn64o/hosts accepts the same fields when switching on; the defaults apply there.

FieldValuesDefaultMeaning
sourcerecords, fixedrecordsrecords = the name's current A/AAAA records, fixed = fixed target from target
targetpublic IP or host name, up to 253 characters–only with fixed; private, CGNAT, documentation and server-owned addresses are not allowed
schemehttps, httphttpsprotocol to the target; a change sets port to 443 or 80 unless you send a port
port1–65535443port on the target
verify_tlsboolfalseverify the target's certificate
prefer_ipv6booltrueconnect over IPv6 first
frontend0–320 = no website (port mappings only), 1 = HTTP only, 2 = HTTPS with redirect from port 80, 3 = HTTPS only
cache_mb0 up to the class's cache size0cache per name in MB, 0 = off; above it 422, cache_limit
cache_minutes1–144010unused cache entries are dropped after this time
curl -X PUT "https://ipv64.net/api/v2/cdn64o/hosts/42/target" \
  -H "Authorization: Bearer DEIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"source":"records","scheme":"http","port":8080,"frontend":2,"cache_mb":256}'

Response: the name object. The edge servers use the new target within a few seconds.

Access list: GET and PUT /cdn64o/hosts/{id}/acl

The allow/block list works on the edge servers, in all modes and also for the name's port mappings (in mode 1 by the IP of the connection). PUT replaces the whole list.

FieldValuesMeaning
default (required)off, allow, denyoff = list off; allow = everyone except the list; deny = only the list
listarray or comma-separated textIP addresses and networks (IPv4/IPv6, CIDR), at most 200; duplicates are dropped. Entries are stored normalised (::ffff:203.0.113.0/120 as 203.0.113.0/24); addresses with a zone (fe80::1%eth0) are invalid
curl -X PUT "https://ipv64.net/api/v2/cdn64o/hosts/42/acl" \
  -H "Authorization: Bearer DEIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"default":"deny","list":["192.0.2.0/24","2001:db8:1234::/48"]}'
{"data": {"default": "deny", "list": ["192.0.2.0/24", "2001:db8:1234::/48"]}}

Port mapper: /cdn64o/hosts/{id}/mappings

A port mapping opens a port between 50000 and 62000 on all edge servers and passes TCP or UDP on: in mode 3 to the port of your target, in modes 1 and 2 through the tunnel to a stream in Node64 (target_port = port of the stream in the node).

Create: POST

FieldRequiredMeaning
target_portyesport on the target or stream, 1–65535
transportnotcp (default) or udp
listen_portnopreferred server port, 50000–62000; taken = 409, port_in_use
namenolabel, up to 64 characters, e.g. WireGuard

Without listen_port, IPv64.net takes the port another mapping of the name already uses for the same target port, otherwise the target port itself if it is free within the range, otherwise a free port. Response: 201 with all port mappings of the name.

curl -X POST "https://ipv64.net/api/v2/cdn64o/hosts/42/mappings" \
  -H "Authorization: Bearer DEIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"name":"WireGuard","transport":"udp","target_port":51820}'
{"data": [{"id": 7, "name": "WireGuard", "listen_port": 55349, "transport": "udp", "target_port": 51820}]}

The service is then reachable at www.deinedomain.ipv64.net:55349 (UDP). Per name and transport, each target port may appear only once (409, mapping_exists).

List and delete

curl "https://ipv64.net/api/v2/cdn64o/hosts/42/mappings" -H "Authorization: Bearer DEIN_API_KEY"
curl -X DELETE "https://ipv64.net/api/v2/cdn64o/hosts/42/mappings/7" -H "Authorization: Bearer DEIN_API_KEY"

Deleting answers 204.

Statistics and events

GET /cdn64o/stats

Numbers from the edge servers per name and day for all names of your account. Parameter days: 1–400, default 30.

curl "https://ipv64.net/api/v2/cdn64o/stats?days=7" -H "Authorization: Bearer DEIN_API_KEY"
{"data": [
  {"host_id": 42, "fqdn": "www.deinedomain.ipv64.net", "day": "2026-10-25",
   "bytes_in": 1048576, "bytes_out": 52428800, "conns": 310, "requests": 2048, "rejected": 3}
]}

rejected counts rejections by the edge servers, e.g. by the access list or a block. Names that were switched off no longer appear here.

GET /cdn64o/protection

What the edge servers fended off for the names of your account. Parameter days: 1 (today), 7 or 30 (default); other values result in 422.

curl "https://ipv64.net/api/v2/cdn64o/protection?days=7" -H "Authorization: Bearer DEIN_API_KEY"
{"data": {
  "days": 7, "ja4_global": "block",
  "totals": {"blocked_list": 120, "blocked_acl": 0, "blocked_flood": 4, "blocked_limit": 2, "blocked_waf": 37,
             "blocked_ja4": 0, "ja4_hits": 15, "blocked_ips": 61, "conns": 310, "conns_v4": 88},
  "daily": [{"day": "2026-10-21", "blocked_list": 18, …}, …],
  "hosts": [{"id": 42, "fqdn": "www.deinedomain.ipv64.net", "mode": 2, "blocked_list": 120, …}],
  "ja4_top": [{"ja4": "t13d1516h2_8daaf6152771_02713d6af862", "hits": 15}]
}}
FieldMeaning
ja4_globalblock = JA4 acts as set for the name; count = temporarily count only, even with block
totals, daily, hoststotal of the period, per day (including days without numbers) and per name
blocked_listrejected by blocklists
blocked_aclrejected by the access list
blocked_flood, blocked_limitoverload: connection limits or request limits per IP
blocked_wafrejected by WAF patterns (403)
blocked_ja4, ja4_hitsclosed because of JA4, or JA4 hits in total (including those only counted)
blocked_ipsblocked IP addresses (IPv6 per /64)
conns, conns_v4connections via CDN64, of them via IPv4
ja4_topthe 10 most frequent JA4 fingerprints in the period

GET /cdn64o/hosts/{id}/events

The last 100 events of a name, newest first, each with time, kind and message. Possible values of kind:

kindMeaning
enabled, disabledname switched on or off
changedmode or tunnels changed
wafWAF patterns or JA4 level changed
paused, resumedpaused or resumed
target, acl, mappingtarget, access list or port mapping changed
blocked, unblockedblocked because of traffic or released again
edge_down, edge_backan edge server was removed from DNS or added back (message in German, e.g. “srv08 nicht erreichbar” or “zurück auf srv08”)
edge_replacedan assigned edge server has been away for more than 3 minutes, another one stands in (message e.g. “Ersatz srv09 für srv08”)
servers_changedthe edge servers of the account changed (number chosen, class changed, server in maintenance); message names the servers in DNS
balanceload balancing: new server added, move done (“Lastausgleich: srv08 → srv10”) or cancelled
acmeTXT record for a certificate set

Tunnels: /cdn64o/tunnels

A tunnel stands for one Node64 instance. Node64 registers it itself when you switch on CDN64; you mainly need these endpoints to remove a tunnel that is no longer used.

  • POST /cdn64o/tunnels with name (up to 100 characters) and node_id (up to 64 characters) creates a tunnel. The response (201) contains the tunnel object, the edge servers and under token the tunnel token – only this one time. IPv64.net only stores a hash of it. At most 10 tunnels per account (403, limit_reached); without CDN domains in the class 403, plan_not_allowed.
  • POST /cdn64o/tunnels/{id}/token issues a new token; the old one is invalid immediately.
  • DELETE /cdn64o/tunnels/{id} removes the tunnel (204). Names that are no longer assigned to any other tunnel are switched off – DNS back, target, access list and port mappings removed. If the DNS server rejects this, you get 502 (dns_update_failed); tunnel and name stay so you can try again later.

GET and PUT /cdn64o/tunnels/{id}/lists read and set the block list (deny) and the allow list (allow) of the tunnel: IP addresses and networks (IPv4/IPv6, CIDR), at most 1000 per list (otherwise 422, list_too_long). Entries are stored normalised, IPv4-mapped networks as IPv4; addresses with a zone give 422. The edge servers reject addresses on the block list for all names of the tunnel right at connection setup; the allow list takes precedence. PUT replaces the lists sent, a missing field stays. Node64 keeps both lists in line with the lists under PROXY64 → Access lists.

The tunnel object (also in GET /cdn64o) contains id (e.g. tn_…), name, node_id, status, created_at, last_seen (last connection to an edge server), last_edge, node_version, sessions (highest number of connections per server), edges (the servers the tunnel connects to – those of all its names –, each with sessions: the highest value of the names there) and servers (choice of its first name, see edge servers of a name).

curl -X DELETE "https://ipv64.net/api/v2/cdn64o/tunnels/tn_DEINE_TUNNEL_ID" -H "Authorization: Bearer DEIN_API_KEY"
Protect the token

With the tunnel token a node can log in to the edge servers as your tunnel. Do not share it. If it has leaked, issue a new one.

Account class limits: GET /plans

Public, without API key. Returns per account class the name, price and under limits the current limits; for CDN64: cdn_domains, cdn_traffic_gb, cdn_bandwidth_mbit (missing when unlimited), cdn_mappings, cdn_tunnel_sessions, cdn_edges (edge servers per account, 0 = all) and cdn_edges_selectable (number can be chosen).

curl "https://ipv64.net/api/v2/plans"

The response may be cached for 10 minutes. The values are explained under quota and traffic.

Edge server endpoints

The paths under /cdn64o/edge/ (configuration, traffic reports, certificates, ACME TXT) are only used by the IPv64.net edge servers with their own server secret. With an API key they answer 401.

Error codes

HTTPcodeMeaning
401unauthenticated, invalid_tokenAPI key missing, or invalid, expired or account not active
403plan_not_allowedaccount class without CDN domains
403limit_reachedCDN domains, port mappings or tunnels used up
403traffic_limit_reachedmonthly traffic used up
403act_as_deniedno active account sharing for X-IPv64-Act-As
404cdn64o_host_not_found, cdn64o_tunnel_not_found, not_foundname, tunnel or port mapping not found (or not in your account)
409cdn64o_existsname is already in CDN64
409old_cdn_activedomain is still in the former IPv64 CDN
409cname_exists, failover_activeCNAME or DNS failover on the name
409tunnel_blockedtunnel is blocked
409not_mode_3only mode 3 has a target
409mapping_exists, port_in_usetarget port already mapped, or server port taken or none free
422missing_field, invalid_field, out_of_rangefield missing, wrong format or out of range (name in field)
422domain_not_in_accountname does not belong to an active domain of your account
422mode_not_available, mode_change_not_possibleunknown mode, or switch between mode 3 and 1/2
422no_target_records, target_not_publicno public A/AAAA address as target, or target IP not public
422cache_limit, acl_too_longcache larger than the class allows, or more than 200 list entries
429rate_limitedtoo many requests, see Retry-After
502dns_update_failedDNS server rejected the change; the name stays, try again later

An example error response:

{"type": "https://ipv64.net/api/v2/errors#cname_exists", "title": "Conflict", "status": 409,
 "detail": "The name has a CNAME record. Remove it first.", "code": "cname_exists"}

What the messages mean in practice is explained under CDN64 → troubleshooting. The other areas of the API are described on the API page.

Found a mistake or missing something? Tell us in the v64.tech forum. · Updated: 2026-11-03