HTTP API
https://api.anchoredip.com/api/. Everything the dashboard does, it does through this — there is no private API behind it.Authentication
There is none, in the usual sense. A lease has an access token, returned once when you order, and it appears in the URL of every call about that lease. No account, no OAuth, no key rotation.
Plans
GET /api/plans/response
[
{
"slug": "solo",
"name": "Solo",
"monthly_price_usd": "19.00",
"term_price_usd": "19.00",
"term_days": 30,
"trial_days": 0,
"included_ipv4": 1,
"included_ipv6": 1,
"included_tunnels": 2,
"requires_verification": false,
"payment_methods": [{ "value": "card", "name": "Card", "detail": "…" }]
}
]Read prices from here rather than hardcoding them. The headline monthly_price_usd is per month whatever the term; term_price_usd is what is actually charged. On an annual plan they differ by a factor of twelve.
Order a lease
POST /api/leases/
Content-Type: application/json
{
"plan": "trial",
"organization_name": "Example GmbH",
"country": "DE",
"billing_email": "ops@example.com"
}response — free or trial plan
{ "access_token": "884c53fe-…", "status": "active" }response — paid plan
{
"access_token": "69c81e11-…",
"status": "pending",
"amount_usd": "19.00",
"payment_reference": "AIP-00021",
"payment_methods": [ … ]
}Limited to five orders an hour from one address. A trial is one per billing email; a second is refused with a 400 that names the paid plans, which need no approval.
Read a lease
GET /api/leases/{access_token}/Returns status, the addresses held, every tunnel with its last handshake, what is owed, and the full billing history with a link to each invoice. This is what the dashboard renders.
Create a tunnel
POST /api/leases/{access_token}/tunnels/
{
"transport": "wireguard", // or "amneziawg"
"routing_mode": "source", // or "full"
"label": "eu-worker-1"
}response
{
"tunnel_id": 42,
"filename": "anchoredip-42.conf",
"config": "[Interface]\nPrivateKey = …",
"warning": "This configuration contains a private key and is returned once."
}Pick source for a Linux host with wg-quick and full for anything else — a source-routed config cannot work in a graphical client. See routing modes.
Revoke a tunnel
DELETE /api/leases/{access_token}/tunnels/{tunnel_id}Frees the slot immediately. Meant to be callable from a shutdown hook: a container that revokes its own peer on exit will not exhaust your allowance with ghosts.
Reverse DNS
GET /api/leases/{access_token}/rdns/
POST /api/leases/{access_token}/rdns/
{ "address": "194.0.108.64", "hostname": "mail.example.com" }An empty hostname removes the record. Live within about a second — it is a row in our nameserver, not a ticket to somebody else.
Payment and renewal
POST /api/leases/{access_token}/renew/ { "plan": "solo" }
POST /api/leases/{access_token}/pay/ { "method": "card" }
POST /api/leases/{access_token}/pay/ { "method": "crypto", "txid": "…" }
GET /api/leases/{access_token}/invoice/?number=AIP-2026-0003renew without a plan renews the current one; a trial has none to renew into, so it answers 400 with the plans it can move to. Naming a plan converts the lease and keeps the addresses, which is the entire reason the trial runs on real space.
Recover access
POST /api/auth/link/ { "email": "ops@example.com" }
POST /api/auth/redeem/ { "key": "…from the email…" }The first emails a one-time link, valid thirty minutes; the second exchanges it for every lease billed to that address. An address we do not bill gets exactly the same answer as one we do.
Errors
Ordinary HTTP. 400 for a request that cannot be satisfied as written, 404 for an access token we do not know, 409 when the request is well formed but the world is not ready — a crypto payment the chain has not confirmed yet, or a renewal on a lease that has ended — 429 when throttled. The body carries detail with a sentence you can show a person.