DNSCove

DNSCove control-plane API (1.0)

Download OpenAPI specification:

JSON API for the DNSCove control-plane: magic-link auth, zones and records, delegation/parity checks, DNSSEC signing, snapshot publish, Route53 import, plan and subscription management, and scoped machine tokens for automation (ACME DNS-01, per-zone record management, and tenant-wide provisioning).

Two credential types:

  • Session — established by POST /api/auth/exchange (magic-link) or POST /api/webauthn/login/finish (passkey) and ended by POST /api/auth/logout. Delivered as an HttpOnly Set-Cookie, never in a response body or an Authorization header (see the sessionCookie security scheme below). Full access to the tenant's zones for as long as the cookie is valid and not revoked — see SECURITY.md for the revocation model. Because a browser attaches this cookie to requests automatically, every mutating request that carries it must also pass an Origin/Sec-Fetch-Site check and echo a matching X-CSRF-Token header; see API.md for the cookie attributes and the CSRF rule. Used by the console.

  • Scoped machine token (dnsc_<id>_<secret>) — sent as Authorization: Bearer <token>. Never a browser credential, so it is exempt from the CSRF/Origin checks above (see API.md). Carries one scope:

    • acme-dns01 — bound to one zone; may call only POST /api/zones/{id}/acme-challenge on that zone.
    • zone-admin — bound to one zone; full record CRUD + publish + delegation/parity + ACME on that zone. No zone lifecycle or token minting.
    • tenant-admin — tenant-wide (no zone binding): create/list/delete zones, act on any zone, publish, and mint/revoke tokens. Root-equivalent — prefer a narrower scope when one zone is enough.

    An endpoint that doesn't accept a token's scope answers 403.

Guides: the Quickstart walks a zone from create to live over the API; Migrating from Route 53 imports a hosted zone in one call; cert-manager issues Let's Encrypt certificates on Kubernetes; and Terraform / OpenTofu and CloudFormation manage DNS as code.

auth

Request a magic-link sign-in token

Request Body schema: application/json
required
email
required
string <email>

Responses

Request samples

Content type
application/json
{
  • "email": "user@example.com"
}

Response samples

Content type
application/json
{
  • "sent": true,
  • "dev_token": "string",
  • "dev_link": "string"
}

Exchange a magic-link token for a session

Consumes a single-use magic-link token and starts a console session. The session itself is never returned in the body — it is delivered as an HttpOnly Set-Cookie (see the Set-Cookie response header below and sessionCookie in securitySchemes), alongside a second, non-HttpOnly dnscove.csrf cookie the console echoes back as X-CSRF-Token on subsequent mutating requests. See API.md for the cookie attributes and the CSRF rule.

Request Body schema: application/json
required
token
required
string

Responses

Request samples

Content type
application/json
{
  • "token": "string"
}

Response samples

Content type
application/json
{
  • "email": "string",
  • "tenant": "string"
}

End the console session

Revokes the session's jti (see SECURITY.md) and clears both the session and dnscove.csrf cookies. Deliberately NOT gated behind an active session: a missing, malformed, expired, or already-revoked cookie all take the same path to the same 204 as a live session being logged out, so the endpoint can never be used to probe whether a session exists. When the request DOES carry a live session cookie it must still satisfy the same Origin/Sec-Fetch-Site and X-CSRF-Token double-submit checks as any other mutating route (see API.md) — those checks run ahead of this handler, not inside it.

header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

passkeys

Begin passkey registration (returns PublicKeyCredentialCreationOptions)

Requires a live console session (cookie) — never accepts a scoped machine token, so passkeys always bind to a signed-in human.

Authorizations:
sessionCookie
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{ }

Finish passkey registration

Authorizations:
sessionCookie
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
required
object

the browser's attestation PublicKeyCredential

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
{
  • "error": {
    }
}

List the caller's registered passkeys

Authorizations:
sessionCookie

Responses

Response samples

Content type
application/json
{
  • "credentials": [
    ]
}

Remove a passkey

Authorizations:
sessionCookie
path Parameters
id
required
string
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Begin passwordless passkey sign-in (returns assertion options)

Responses

Response samples

Content type
application/json
{ }

Finish passkey sign-in — starts a console session

Same cookie-not-body session delivery as POST /api/auth/exchange (see its description) — the console has one session model, not two.

Request Body schema: application/json
required
object

the browser's assertion PublicKeyCredential

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
{
  • "email": "string",
  • "tenant": "string"
}

zones

List zones

Authorizations:
sessionCookiescopedToken

Responses

Response samples

Content type
application/json
{
  • "zones": [
    ]
}

Create a zone

Authorizations:
sessionCookiescopedToken
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
required
origin
required
string

Responses

Request samples

Content type
application/json
{
  • "origin": "example.com"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "tenant_id": "string",
  • "origin": "string",
  • "status": "PENDING_VERIFICATION",
  • "ns": [
    ],
  • "serial": 0,
  • "published_serial": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "negative_ttl": 60
}

Get a zone

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "tenant_id": "string",
  • "origin": "string",
  • "status": "PENDING_VERIFICATION",
  • "ns": [
    ],
  • "serial": 0,
  • "published_serial": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "negative_ttl": 60
}

Update zone settings

Change a zone's settings. Fields left out are unchanged. A change bumps the zone's serial, so it reaches the edge on the next publish, like a record edit. Setting the value a zone already has changes nothing. Accepts a session, zone-admin (its own zone) or tenant-admin.

negative_ttl is the SOA MINIMUM: how long resolvers cache NXDOMAIN and NODATA answers ("this name has no AAAA") from the zone. Negative answers carry min(SOA TTL 3600, negative_ttl), per RFC 2308, and for signed zones so do the NSEC3 proofs. Tradeoff: a name created right after a resolver cached its absence stays invisible to that resolver for up to this long, so raise it only for zones whose names rarely appear.

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
required
negative_ttl
required
integer [ 60 .. 86400 ]

Negative-caching TTL in seconds (SOA MINIMUM). Default 300.

Responses

Request samples

Content type
application/json
{
  • "negative_ttl": 3600
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "tenant_id": "string",
  • "origin": "string",
  • "status": "PENDING_VERIFICATION",
  • "ns": [
    ],
  • "serial": 0,
  • "published_serial": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "negative_ttl": 60
}

Delete a zone

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

Check parent NS delegation (activates the zone when delegated)

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70

Responses

Response samples

Content type
application/json
{
  • "delegation": {
    },
  • "status": "PENDING_VERIFICATION"
}

Prove domain ownership via the `_dnscove-challenge` TXT and activate the zone

Checks for the _dnscove-challenge.<origin> TXT record whose value is dnscove-site-verification=<zone id> on the domain's current public DNS. On success the zone advances PENDING_VERIFICATION → ACTIVE and is published immediately — so the zone starts serving on ns1/ns2 before you move nameservers (a no-downtime cutover). The exact record to publish is returned by zone create, Route 53 import, and any unverified response (verification). Session, zone-admin (this zone), or tenant-admin.

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "status": "PENDING_VERIFICATION",
  • "verified": true,
  • "served": true,
  • "publish_error": "string",
  • "verification": {
    },
  • "challenge": { }
}

Compare served records against public DNS ("safe to delete the old zone")

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70

Responses

Response samples

Content type
application/json
{
  • "parity": {
    },
  • "safe_to_delete": true,
  • "status": "PENDING_VERIFICATION"
}

records

List record sets

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70

Responses

Response samples

Content type
application/json
{
  • "rrsets": [
    ]
}

Create, upsert, or delete a record set

Session, zone-admin (this zone), or tenant-admin. A record set is owned by (name, type): CREATE claims that pair and fails with 409 RRSetAlreadyExists if it is taken, while UPSERT replaces whatever is there — including every value it currently answers. Use CREATE when you mean "add a record" so a collision is reported instead of overwritten.

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
required
action
string
Default: "UPSERT"
Enum: "CREATE" "UPSERT" "DELETE"
name
required
string
type
required
string
Enum: "A" "AAAA" "CNAME" "TXT" "MX" "SRV" "CAA" "NS" "PTR" "ALIAS"

Standard RR types plus DNSCove's apex-safe ALIAS — the record other providers call ANAME and Route 53 calls an alias record. There is no separate ANAME type: ALIAS is the apex-flattening record. It takes exactly one FQDN target (a CDN, load balancer, or any hostname), flattened to A/AAAA at publish time and kept fresh. ALIAS is valid at the apex and can't coexist with A/AAAA/CNAME at the same name. The apex SOA and apex NS are managed and can't be edited.

ttl
integer
Default: 300
records
Array of strings

Responses

Request samples

Content type
application/json
{
  • "action": "CREATE",
  • "name": "www.example.com.",
  • "type": "A",
  • "ttl": 300,
  • "records": [
    ]
}

Response samples

Content type
application/json
{
  • "status": "PENDING",
  • "serial": 0
}

dnssec

Read signing state and the DS to publish at your registrar

Returns the zone's signing state, the DS record to hand to the registrar, and whether the parent already publishes a matching one. The DS is offered in three forms (digest fields, a full record line, and dnskey) because registrars disagree about which they ask for. Reading also advances the lifecycle: this is the call that promotes PENDING_DS to ACTIVE once a matching DS appears at the parent, so a zone does not sit in PENDING_DS forever no matter what the registrar published. Readable by any credential that may read the zone. ds_present is null when the parent could not be reached — render that as "unknown", never as "no". "No" is the answer that makes disabling look safe.

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70

Responses

Response samples

Content type
application/json
{
  • "enabled": true,
  • "status": "DISABLED",
  • "ds_present": true,
  • "ds_checked_at": "2019-08-24T14:15:22Z",
  • "ds_error": "string",
  • "ds": [
    ],
  • "keys": [
    ],
  • "algorithm": 13,
  • "enabled_at": "2019-08-24T14:15:22Z",
  • "sig_expiry": "2019-08-24T14:15:22Z",
  • "sig_days_left": 0,
  • "nsec3": {
    },
  • "roll": {
    }
}

Enable DNSSEC on a zone (session or tenant-admin)

Generates a KSK/ZSK pair (ECDSA P-256, algorithm 13), signs the zone, and publishes it to the edge. The zone starts carrying DNSKEYs and RRSIGs immediately, but no validator acts on them until you publish the returned DS at your registrar — so enabling is a safe, reversible step in practice, and a tenant who changes their mind before publishing the DS has broken nothing. Requires the zone to be ACTIVE: signing a zone the edge does not yet compile would leave the DS you published pointing at nothing. Tenant-scoped deliberately. A zone-admin token may read this endpoint but not enable or disable, because signing changes how the entire domain resolves for every validating resolver on the internet — not a call a zone-bound automation credential should make on its own.

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "dnssec": {
    }
}

Disable DNSSEC on a zone (session or tenant-admin)

Removes signing and republishes the zone unsigned. Refused while the parent still publishes a DS, and that guard is the point of this endpoint. Unsigning a zone whose DS is live does not degrade it, it breaks it: every validating resolver sees a DS pointing at a key we no longer publish, concludes the answers are forged, and SERVFAILs the domain. Recovery is bounded by the parent's DS TTL and by resolver caches — not by how fast we can deploy. There is no rolling it back. The correct order is: remove the DS at your registrar, wait for it to expire from caches, then call this. A ?force=true query parameter exists but is refused for every credential the API accepts (409 ForceNotPermitted); it is reserved for an out-of-band operator path, rather than quietly granting the most dangerous action in the product to every tenant-admin token.

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "dnssec": {
    }
}

tokens

List a zone's tokens (session or tenant-admin; never returns secrets)

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70

Responses

Response samples

Content type
application/json
{
  • "tokens": [
    ]
}

Mint a per-zone token (session or tenant-admin)

Mints an acme-dns01 or zone-admin token bound to this zone. Returns the plaintext token exactly once — store it securely; it is unrecoverable afterward. tenant-admin is not a per-zone scope; mint it at POST /api/tokens.

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
name
string
scope
string
Default: "acme-dns01"
Enum: "acme-dns01" "zone-admin"
expires_in_days
integer

0 = no expiry

Responses

Request samples

Content type
application/json
{
  • "name": "cert-manager webhook",
  • "scope": "acme-dns01",
  • "expires_in_days": 0
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "zone_id": "string",
  • "scope": "acme-dns01",
  • "name": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "revoked": true,
  • "token": "dnsc_1a2b3c4d5e6f7a8b_…"
}

Revoke a per-zone token (session or tenant-admin)

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
tid
required
string
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

List every token in the tenant (session or tenant-admin; no secrets)

Authorizations:
sessionCookiescopedToken

Responses

Response samples

Content type
application/json
{
  • "tokens": [
    ]
}

Mint a token of any scope (session or tenant-admin)

Mints tenant-admin (default, tenant-wide) or a zone-bound scope when a zone_id in the caller's tenant is supplied. Returns the plaintext token exactly once.

Authorizations:
sessionCookiescopedToken
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
name
string
scope
string
Default: "tenant-admin"
Enum: "tenant-admin" "zone-admin" "acme-dns01"
zone_id
string

required for zone-bound scopes; ignored for tenant-admin

expires_in_days
integer

0 = no expiry

Responses

Request samples

Content type
application/json
{
  • "name": "terraform",
  • "scope": "tenant-admin",
  • "zone_id": "string",
  • "expires_in_days": 0
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "zone_id": "string",
  • "scope": "acme-dns01",
  • "name": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "revoked": true,
  • "token": "dnsc_1a2b3c4d5e6f7a8b_…"
}

Revoke any token in the tenant by id (session or tenant-admin)

Authorizations:
sessionCookiescopedToken
path Parameters
tid
required
string
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "error": {
    }
}

acme

Present or clean up an ACME DNS-01 challenge TXT

Adds (PRESENT) or removes (CLEANUP) one value on the _acme-challenge TXT record and republishes to the edge. Accepts a session or an acme-dns01 / zone-admin token bound to this zone, or a tenant-admin token. Values merge, so multiple challenges at the same name (SAN/wildcard) coexist.

Authorizations:
sessionCookiescopedToken
path Parameters
id
required
string
Example: Z1a2b3c4d5e6f70
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
required
action
required
string
Enum: "PRESENT" "CLEANUP"
name
required
string
value
required
string

base64url key authorization

Responses

Request samples

Content type
application/json
{
  • "action": "PRESENT",
  • "name": "_acme-challenge.canary.lab.dnscove.com.",
  • "value": "string"
}

Response samples

Content type
application/json
{
  • "status": "ok",
  • "action": "string",
  • "changed": true,
  • "published": true,
  • "serial": 0
}

billing

Read the tenant's plan, zone usage, subscription, and the plan catalog

The one read the console billing page needs. Session or tenant-admin. If Stripe Checkout returned before its webhook was applied, this call does one best-effort refresh first, so reloading the page repairs a stale plan display rather than showing the old tier until the webhook lands.

Authorizations:
sessionCookiescopedToken

Responses

Response samples

Content type
application/json
{
  • "plan": {
    },
  • "usage": {
    },
  • "catalog": [
    ],
  • "billing_enabled": true,
  • "has_customer": true,
  • "subscription": {
    }
}

Open a Stripe Checkout session for a plan (session or tenant-admin)

Returns the URL of a Stripe Checkout session for (plan, period). Redirect the customer to it; DNSCove never sees card details. Only sellable plans from the catalog can be purchased.

Authorizations:
sessionCookiescopedToken
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
required
plan
required
string
Enum: "free" "solo" "pro"
period
required
string
Enum: "monthly" "annual"

Responses

Request samples

Content type
application/json
{
  • "plan": "pro",
  • "period": "monthly"
}

Response samples

Content type
application/json

Reconcile a completed checkout immediately (session or tenant-admin)

A synchronous refresh for the moment Stripe redirects back from Checkout. Webhooks still own long-term reconciliation; this exists so a completed purchase does not render as the old plan while the webhook is still in flight. session_id is the Checkout session Stripe appended to the return URL; it may be omitted to reconcile whatever Stripe currently reports for the tenant.

Authorizations:
sessionCookiescopedToken
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
session_id
string

the Stripe Checkout session id from the return URL

Responses

Request samples

Content type
application/json
{
  • "session_id": "string"
}

Response samples

Content type
application/json
{
  • "synced": true
}

Open a Stripe Billing Portal session (session or tenant-admin)

Returns the URL of a Stripe Billing Portal session for the tenant's existing customer, where they can change payment method, view invoices, or cancel. Requires a customer to exist — start a checkout first.

Authorizations:
sessionCookiescopedToken
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json

ops

Liveness probe

Responses

Response samples

Content type
application/json
{
  • "status": "ok"
}

Readiness probe

Reports whether this instance can reach its backing store. Unlike /api/healthz this one touches a dependency, which is why Kubernetes uses it to pull a pod out of the Service rather than to kill it. Within the startup grace window a failing dependency still answers 200 ready: the pod has not been serving long enough for removal to help. The cause of a failure is deliberately absent from the body — an unauthenticated caller has no business reading our dependency topology — and is logged instead.

Responses

Response samples

Content type
application/json
{
  • "status": "ready"
}

Compile and ship a full snapshot to every edge node

Session, zone-admin, or tenant-admin. A zone-admin uses this to make its bound-zone record changes live; the publish operation compiles and ships the full snapshot. Responses to zone-admin tokens report only the bound zone's confirmation state and do not expose other zone origins. If another active zone is already unpublished when the request starts, it returns 409 PublishBlocked.

Authorizations:
sessionCookiescopedToken
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Responses

Response samples

Content type
application/json
{
  • "published": true,
  • "zones": 0,
  • "nodes": [
    ]
}

Import a zone from `aws route53 list-resource-record-sets` JSON

Creates a zone from a pasted Route 53 export and imports every convertible record set (apex SOA/NS are dropped and managed by DNSCove; ALIAS records convert to DNSCove ALIAS; routing-policy record sets are skipped). AWS credentials are never sent — you run the CLI locally and post the JSON. The new zone is PENDING_VERIFICATION and not served yet; the response returns the _dnscove-challenge TXT to publish (verification), which you prove via POST /api/zones/{id}/verify to go live. Session or tenant-admin.

Authorizations:
sessionCookiescopedToken
header Parameters
X-CSRF-Token
string

Required on this mutating request only when it is authenticated by the sessionCookie cookie — echo the value of the non-HttpOnly dnscove.csrf cookie set alongside the session (double-submit; see API.md#authentication). Not marked required: true here because a scopedToken (machine bearer) caller never sends this header and is exempt from the check entirely — see the scopedToken security scheme description. A session-cookie request missing or mismatching this header gets 401; see the Unauthorized response and POST /api/auth/logout's 401 for the concrete shape. POST /api/stripe/webhook and /blog/* are exempt from this requirement even though they are mutating, because neither is ever a browser request carrying our cookies (HMAC signature and static API key respectively — see API.md#authentication).

Request Body schema: application/json
required
json
required
string

raw Route53 JSON

Responses

Request samples

Content type
application/json
{
  • "json": "string"
}

Response samples

Content type
application/json
{
  • "zone": {
    },
  • "imported": 0,
  • "skipped": [
    ],
  • "ns": [
    ],
  • "verification": {
    }
}