API documentation
Manage names and DNS through the REST API described below. Account security and some billing actions use the panel. API requests use bearer tokens and JSON responses.
Base URL https://api.uk.app/v1
Auth Authorization: Bearer <token>
Spec https://api.uk.app/v1/openapi.json
DDNS https://ddns.uk.app/nic/update
MCP https://mcp.uk.app/
Overview
A uk.app name is a third-level name such as petersblog.uk.app. It lives in a zone served by our own authoritative DNS (PowerDNS on three authoritative nameservers: ns1.uk.app, ns2.uk.app and ns3.uk.app, DNSSEC-signed). You manage records beneath it, subject to record limits and validation: www, api, *, _acme-challenge, anything. Changes publish within seconds; resolver caches follow the TTL you set (default 300 s).
A name goes through these states:
| Status | Meaning |
|---|---|
pending | Reserved for 48 hours, not yet paid. Not in DNS. |
parked | Paid, no records of your own yet — shows the parking page. |
active | Paid and pointing somewhere. |
grace | Renewal failed; keeps working for 30 days. |
hold | Stopped resolving; restorable by paying. |
suspended | Taken down for abuse. Serves a suspension page. |
Authentication
Create tokens at my.uk.app/tokens. Each token carries scopes; requests without the required scope get 403.
| Scope | Allows |
|---|---|
read | List names and records, verify, WHOIS, account info. |
write:records | Add, change, delete records; apply presets. ACME adapters use this scope; the dyndns2 endpoint uses a separate per-name DDNS token. |
write:names | Register (including payment from available balance), release, restore and permanently delete names. |
Tokens are shown once. Revoking a token takes effect immediately. Keep tokens out of git; for CI use a token with write:records only.
Conventions & errors
- Names can be passed as
petersblogorpetersblog.uk.app; both work everywhere. - Request bodies: JSON (
Content-Type: application/json) or form-encoded. Responses are JSON unless noted. - Validation problems return
422with{"message": "...", "errors": {"field": ["..."]}}. - Rate limit: 600 requests per minute per token. Headers
X-RateLimit-RemainingandRetry-Aftertell you where you stand. - Timestamps are ISO 8601 in UTC.
| Code | When |
|---|---|
| 401 | Missing or invalid token. |
| 402 | Insufficient balance for an explicitly requested balance payment; the response includes payment links. |
| 403 | Token lacks the scope. |
| 404 | Name or record not found, or not yours. |
| 422 | Invalid input, name unavailable, limit reached, name not active yet. |
| 429 | Rate limited. |
Quick start
export TOKEN=ukapp_...
# 1. check availability and the quoted annual price
curl "https://api.uk.app/v1/names/check?name=petersblog"
# {"name":"petersblog.uk.app","available":true,"price_gbp":4.99,"billing":"yearly, auto-renew"}
# 2. reserve it (returns a checkout URL; the name activates after payment)
curl -H "Authorization: Bearer $TOKEN" -X POST https://api.uk.app/v1/names -d name=petersblog -d pay=checkout
# 3. once active, point it at your server
curl -H "Authorization: Bearer $TOKEN" -X POST https://api.uk.app/v1/names/petersblog/records \
-d host=@ -d type=A -d content=203.0.113.7
# 4. or use a preset
curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -X POST https://api.uk.app/v1/names/petersblog/presets/vercel \
-d '{"params":{"target":"YOUR-PROJECT.vercel-dns-017.com"}}'
# 5. confirm DNS + HTTPS
curl -H "Authorization: Bearer $TOKEN" -X POST https://api.uk.app/v1/names/petersblog/verify
Check availability
{"name":"petersblog.uk.app","available":true,"reason":null,"price_gbp":4.99,"billing":"yearly, auto-renew"}
{"name":"paypal-login.uk.app","available":false,"reason":"Names containing protected brands need manual review. Contact support@uk.app."}
Standard names use 3–63 characters, a-z 0-9 -, with no leading/trailing hyphen. Selected shorter names may be explicitly released for premium registration; other short names remain reserved. Punycode-style labels, system names and blocked names are unavailable. Search returns the current availability, applicable annual price and any restriction; a premium offer does not grant trademark rights.
WHOIS
Registered or available, dates, status, name servers. Owner details are never returned. Add ?format=json or send Accept: application/json; otherwise you get classic whois text, handy for curl.
$ curl https://uk.app/whois/petersblog
Domain Name: petersblog.uk.app
Registry: uk.app (third-level registry, powered by PowerDNS + DNSSEC)
Status: available
Price: £4.99/year, renews automatically
Register: https://my.uk.app/dashboard?claim=petersblog
Name Servers: ns1.uk.app, ns2.uk.app, ns3.uk.app
DNSSEC: signed
List, register, release
[{"name":"petersblog.uk.app","label":"petersblog","status":"active","records":4,"claimed_at":"2026-09-10T09:00:00Z","expires_at":"2027-09-10T09:00:00Z"}]
Body: {"name": "petersblog", "pay": "checkout"}. Explicit pay=checkout reserves the label for 48 hours and returns 201 with a checkout_url; activation follows confirmed payment. Use the price returned by availability checking, including premium pricing.
With pay=balance, the API charges the available balance and activates the name. If pay is omitted, balance payment is the default when the balance covers the annual price; otherwise a checkout link is returned. An explicit balance request with insufficient funds returns 402 and payment links. Authorise automated spending before using this route without pay=checkout. MCP reservations are different: they return a payment link and do not spend balance.
{"name":"petersblog.uk.app","status":"pending","checkout_url":"https://my.uk.app/names/42/checkout", ...}
Moves the name to the bin and removes its records from published DNS. Stored records are retained for restoration. This does not cancel a linked card subscription: cancel future card renewals separately in billing. Paid names normally remain quarantined for 30 days unless permanently deleted sooner; see bin and restoration.
Your email, limits, current standard price and token scopes. Use the individual name or availability response for its applicable annual price.
Verify DNS & HTTPS
Checks DNS and probes one resolved public address for HTTPS and a valid certificate for the hostname. HTTP status is reported separately; redirects are not followed. Results may be reused for one minute. This does not verify every address, application functionality or a game server.
{"name":"petersblog.uk.app",
"dns":[{"host":"petersblog.uk.app","type":"A","ip":"76.76.21.21","ttl":300}],
"https":{"ok":true,"issuer":"Let's Encrypt","expires":"2026-12-09T08:33:00+00:00"},
"hsts_preloaded":true,"note":"Live."}
Records
| Field | Type | Notes |
|---|---|---|
host | string | @ for the name itself (default), www, *, _acme-challenge, mc.eu (nested is fine). |
type | enum | See record types. |
content | string | IP, hostname, text, or the type-specific format below. No trailing dot needed. |
ttl | int | 60–86400 seconds, default 300. |
prio | int | MX and SRV priority, default 0. |
curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-X POST https://api.uk.app/v1/names/petersblog/records \
-d '{"host":"_minecraft._tcp","type":"SRV","content":"5 25565 petersblog.uk.app","prio":0}'
# 201 {"id":91,"host":"_minecraft._tcp","type":"SRV","content":"5 25565 petersblog.uk.app","ttl":300,"prio":0,"source":"api"}
Every write is transactional: if the DNS server rejects a record, nothing is stored and you get a 422 with the reason. Adding a real record on @ automatically removes the parking record.
Record types
| Type | Content format | Example |
|---|---|---|
A | IPv4 | 203.0.113.7 |
AAAA | IPv6 | 2001:db8::7 |
CNAME | hostname; cannot share a host with other records | cname.vercel-dns.com |
TXT | text, up to 4000 chars (quoted automatically) | v=spf1 -all |
MX | mail hostname, priority in prio | mail.protonmail.ch / prio 10 |
SRV | weight port target, priority in prio | 5 25565 petersblog.uk.app |
CAA | flags tag "value" | 0 issue "letsencrypt.org" |
NS | hostname — delegate a sub-host to another DNS provider | ns1.example-dns.com |
Presets
Replaces routing records only at the affected hosts, preserving mail, TXT and unrelated records. Conflicts return 422 without changing DNS. Delegated names must first switch to managed DNS. Parameters go in params.
Add the exact hostname to your hosting project first. For Vercel, Netlify and Pages, optional params.host selects @ (default) or www; only that hostname changes. A CNAME cannot coexist with MX or TXT at the same hostname: choose www to retain mail at @. Provider verification records must stay within your registered name.
| Preset | Params | Records created |
|---|---|---|
vercel | target | CNAME to the exact target shown in the project's Domains settings |
netlify | site | CNAME to your full site hostname, e.g. your-site.netlify.app |
cf-pages | project | CNAME to your full your-project.pages.dev hostname; add it in Pages first to avoid error 522 |
github-pages | user | 4 × @ A 185.199.108-111.153, www CNAME user.github.io |
cf-tunnel | Unavailable | Returns 422: Tunnel requires DNS records in the same Cloudflare account |
minecraft | ip, port | @ A ip, _minecraft._tcp SRV 5 port name |
server | ip | @ A ip, www CNAME name |
parking | — | back to our parking page |
curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-X POST https://api.uk.app/v1/names/petersblog/presets/minecraft \
-d '{"params":{"ip":"203.0.113.7","port":"25565"}}'
Own nameservers (delegation)
Body: {"nameservers": ["ns1.example-dns.com", "ns2.example-dns.com"]} (2–6 hosts, must resolve, must not be inside the name itself). Replaces every record with NS records so petersblog.uk.app and everything under it is served by a provider that accepts this exact zone, or your own authoritative DNS server. Create and verify the zone petersblog.uk.app there first. NS delegation does not guarantee acceptance as an independent Cloudflare zone. Export existing records before switching; delegation replaces the managed records.
Back to managed DNS on ns1/ns2/ns3.uk.app (parks the name; add records again).
Import / export
One record per line, host type content [ttl] [prio]; lines starting with ; or # are ignored. Send as zone field or as the raw request body. Import appends, so export → edit → delete → import gives you a full replace.
curl -H "Authorization: Bearer $TOKEN" https://api.uk.app/v1/names/petersblog/export
; petersblog.uk.app — exported 2026-09-10T10:00:00Z
; host type content ttl [prio]
@ A 203.0.113.7 300
www CNAME petersblog.uk.app 300
@ MX mail.example.com 3600 10
@ TXT "v=spf1 -all" 300
Bin (released names)
DELETE /v1/names/{label} moves a name to the bin and removes published DNS records; cached answers may remain until their TTL expires. Stored records are normally retained for 30 days. A linked card subscription is not cancelled by this action; cancel future card renewals in billing. Balance-funded names are not renewed while in the bin. Neither action automatically refunds a payment.
Restores stored DNS records while the name remains in the bin, its paid term has not expired and no other registration or suspension restriction prevents restoration. An expired name cannot be restored from the bin just because fewer than 30 days have passed.
Permanently removes stored records after confirming cancellation of a linked card subscription. Cancellation errors prevent completion. Successful deletion can make an otherwise eligible name available before the normal quarantine ends; reserved and blocked names remain restricted. This cannot be undone. Scheduled processing normally attempts permanent deletion after 30 days in the bin.
Dynamic DNS
Uses the dyndns2 protocol. Configure a client that accepts a custom HTTPS update server, such as ddclient. Router and NAS support depends on the model and firmware; a built-in DDNS menu alone does not guarantee compatibility. Username is the name (petersblog.uk.app), password is the DDNS token from the domain page → Dynamic DNS (scoped to that name only). Create or replace it there; copy it immediately because it is shown only once. Revoke it to stop updates without deleting DNS records. DDNS requires managed DNS and an active, parked or grace-period name. Omit myip to use the caller's address; IPv6 addresses create AAAA records. Responses: good ip, nochg ip, badauth, nohost.
# /etc/ddclient.conf
protocol=dyndns2
ssl=yes
use=web
server=ddns.uk.app
login=petersblog.uk.app
password=YOUR_DDNS_TOKEN
home.petersblog.uk.app
# or from cron
curl -u "petersblog.uk.app:YOUR_DDNS_TOKEN" "https://ddns.uk.app/nic/update?hostname=home.petersblog.uk.app"
ACME DNS-01 (wildcard certificates)
Use the adapters in the ACME setup guide with a write:records token. They create challenge TXT records and remove only the records they created, preserving unrelated or concurrent challenges. API support alone does not mean a certificate client has a native uk.app provider. Follow the client-specific setup and renewal instructions.
A custom acme.sh hook, lego exec adapter and Python CLI are available in the integration download. DNS-01 staging issuance was verified with acme.sh 3.1.5 and lego 5.4.1 on 13 September 2026. Follow the ACME setup guide. These integrations are provided here; no native uk.app provider has been merged upstream. Certificate-authority limits and domain grouping still apply; check the authority's current policy before relying on high-volume issuance.
MCP for AI agents
Connect a Streamable HTTP client to https://mcp.uk.app/. OAuth discovery redirects you to your existing uk.app login and an explicit authorization screen; PKCE S256 is required. Clients using API tokens can send Authorization: Bearer <token> instead. Existing token scopes remain enforced.
The registry tool accepts an action: check_name, list_names, get_balance, list_records, verify_domain, reserve_name, add_record or delete_record. Include name except for list_names/get_balance. Record writes use the same host/type/content/ttl/prio fields as the API; deletion requires the record ID.
OAuth approval authorizes account reads, DNS changes and reservations. Reservations return a checkout link for a person to pay; no MCP action charges a card or spends account balance. Revoke OAuth access from MCP connections. Supported registration callbacks are HTTPS under claude.ai or chatgpt.com, or local loopback callbacks; other clients require an explicit callback configuration. The download also includes the local stdio adapter.
Balance payments
Balance top-ups and name payments are separate transactions. The REST registration route can spend sufficient balance automatically unless pay=checkout is supplied; MCP reservations do not. Balance-funded live names attempt annual renewal from available funds, including retries during grace. Card subscriptions renew through Stripe. See payment and cancellation terms and the billing panel before funding automated use.
Limits & billing
| Price | Standard: £4.99/year. New premium registrations: £99.00/year. Existing premium registrations retain their agreed annual price. Check the quoted price and final checkout total; see pricing. |
| Names per account | 100 (ask support@uk.app for more). |
| Records per name | 100. |
| Reservation | 48 hours unpaid, then the label is released. |
| Lapse | Normally: 30 days grace → 30 days hold without published DNS → bin with 30-day quarantine. Scheduled processing, early permanent deletion and registration restrictions affect reuse; see terms. |
| Refund | Request within 14 days of the first registration payment if the name has not been used. This service offer does not limit statutory rights. See refund details. |
| API rate | 600 requests/minute per token; DDNS 60/minute per name. |
HTTPS & HSTS
The .app TLD is on the HSTS preload list of Chrome, Firefox, Safari and Edge. Browsers refuse plain HTTP for any .app hostname, so a uk.app site without a valid certificate does not load at all — there is no "proceed anyway". Supported hosting providers and configured servers can automate certificate issuance after hostname verification and their other requirements are met. HTTP-01 also needs the challenge to be reachable over public port 80; a DNS record alone is insufficient. Certificate-authority limits apply, including shared registered-domain limits while uk.app is not independently listed in the PSL. See Let’s Encrypt rate limits. Use verify to confirm the certificate is in place.
OpenAPI
The machine-readable spec is at https://api.uk.app/v1/openapi.json (OpenAPI 3.1). Generate a client with openapi-generator, or paste the URL into Postman, Insomnia or Bruno.