Skip to content

API endpoint reference

The API endpoints, grouped by area. Base URL https://<dtm-node>:8443. All endpoints need a bearer token unless marked public. See the API overview for authentication and roles. Write operations generally require editor; cluster and user operations require admin.

Method Path Role Purpose
POST /api/v1/auth/login public Log in. Sets the JWT session cookie (valid 24h) and returns a refresh token.
POST /api/v1/auth/refresh public Exchange a refresh token for a bearer JWT. Rotates the refresh token.
POST /api/v1/auth/logout public Revoke a refresh token to end that session. Any user can end their own.
GET /api/v1/auth/entra/status public Whether Entra SSO is configured.
GET /api/v1/auth/entra/login public Start the Entra sign-in redirect.
GET /api/v1/auth/entra/callback public Entra sign-in callback (sets the session cookie).
GET /api/v1/auth/entra/config admin Read Entra config (secret redacted).
PUT /api/v1/auth/entra/config admin Update Entra config.
Method Path Role Purpose
GET /api/v1/zones read List zones.
POST /api/v1/zones editor Create a zone. Optional deletion_lock overrides the cluster default.
GET /api/v1/zones/{id} read Get a zone.
PUT /api/v1/zones/{id} editor Update a zone (TTL, SOA, default lb_policy; clear_lb_policy removes the default; deletion_lock toggles the deletion lock).
DELETE /api/v1/zones/{id} editor Delete a zone and its records; 409 while the deletion lock is set.
GET /api/v1/zones/{id}/export read Export one zone (RFC 1035).
POST /api/v1/zones/{id}/import editor Import records into a zone.
GET /api/v1/zones/export read Export all zones (JSON bundle).
POST /api/v1/zones/import editor Bulk import (JSON / CSV / BIND).
GET /api/v1/zones/{zoneId}/records read List records in a zone.
POST /api/v1/zones/{zoneId}/records editor Create a record. Replaces an unprotected record of the same name and type; a protected incumbent at that name and type answers 409. Other types at the same name coexist, except that CNAME and ALIAS own a name outright. auto_populate: true creates a registration-owned record with no values.
GET /api/v1/records/{id} read Get a record.
PUT /api/v1/records/{id} editor Update a record. Renaming onto a protected name answers 409.
DELETE /api/v1/records/{id} editor Delete a record (?force=true overrides protected).
POST /api/v1/zones/{zoneId}/records/bulk-delete editor Delete many records; capped (default 100), refuses over-cap batches whole.
POST /api/v1/zones/{id}/import-azure-privatedns admin Import an Azure Private DNS zone directly over ARM (managed identity, read-only; dry_run in the body).
POST /api/v1/overrides editor Create an override record.
GET/PUT/DELETE /api/v1/overrides/{id} mixed Manage an override record.
Method Path Purpose
POST /api/v1/service-accounts Create; returns the dtmsat_ token once. Optional zone_ids confines the token’s writes to the listed zones (fail-closed; preserved across rotation).
GET /api/v1/service-accounts List (tokens redacted).
GET /api/v1/service-accounts/{id} Get one (token redacted).
POST /api/v1/service-accounts/{id}/revoke Revoke; kept in the list for audit.
POST /api/v1/service-accounts/{id}/rotate Mint a fresh secret (version-gated, so repeated calls at the same version are a no-op).
DELETE /api/v1/service-accounts/{id} Delete.

See service-account tokens.

Method Path Role Purpose
GET /api/v1/healthchecks read List health checks.
POST /api/v1/healthchecks editor Create a monitor-only check: status metrics, no DNS effect (script protocol: admin, plus the config flag).
GET/PUT/DELETE /api/v1/healthchecks/{id} mixed Manage a check (admin to set the script protocol or edit script_config; other writes, including DELETE, are editor).
GET /api/v1/healthchecks/{id}/status read Status of one check.
GET /api/v1/health/status read Status of all checks on this node.
Method Path Role Purpose
GET/PUT /api/v1/forwarders/default mixed Default forwarder.
GET/PUT /api/v1/forwarders/hardening admin Default-forwarder hardening.
GET /api/v1/forwarders read List conditional forwarders.
POST /api/v1/forwarders editor Create a conditional forwarder.
GET/PUT/DELETE /api/v1/forwarders/{id} mixed Manage a forwarder.
GET /api/v1/stub-zones read List stub zones.
POST /api/v1/stub-zones editor Create a stub zone.
GET/PUT/DELETE /api/v1/stub-zones/{id} mixed Manage a stub zone.
GET /api/v1/blocklist read Get the blocklist.
PUT /api/v1/blocklist editor Replace the blocklist.
Method Path Role Purpose
GET /api/v1/users admin List users (hashes stripped).
POST /api/v1/users admin Create a user.
GET /api/v1/users/{id} admin Get a user.
PUT /api/v1/users/{id} admin Update role / enabled / password.
DELETE /api/v1/users/{id} admin Delete a user.
Method Path Role Purpose
GET /api/v1/nodes read List cluster members.
GET /api/v1/nodes/self read This node’s info.
DELETE /api/v1/nodes/{id} admin Remove a stopped node from the cluster (cannot remove self); see removing nodes.
POST /api/v1/cluster/join admin Join an existing cluster at runtime.

The API behind the UI’s Lifecycle page; see rolling upgrades for the procedure.

Method Path Role Purpose
GET /api/v1/lifecycle/oracle read Latest published image version, as seen by the version oracle.
GET/POST /api/v1/lifecycle/swap mixed List stable-IP swap runs; start one (admin).
GET /api/v1/lifecycle/swap/{run_id} read One swap run’s state machine.
POST /api/v1/lifecycle/swap/{run_id}/retry admin Retry a failed swap step.
POST /api/v1/lifecycle/swap/{run_id}/abort admin Abort a swap run.
GET /api/v1/lifecycle/identity read Managed-identity permission probes for the swap.
Method Path Role Purpose
GET/POST/PUT/DELETE /api/v1/tsig-keys mixed Manage TSIG keys (update and delete by name).
GET/POST/DELETE /api/v1/subnet-mappings mixed Manage subnet-to-region mappings (delete by id: /api/v1/subnet-mappings/{id}). source must be manual on create; any other value is rejected.
GET /api/v1/regions read Deduplicated region IDs.
GET/POST/PUT/DELETE /api/v1/discovery/scopes admin Manage Azure discovery scopes: subscription scopes, or management-group scopes (kind: "management-group" + management_group_id + the required expanded_subscription_ids, since DTM never expands a group on its own). Reading the scope list also requires admin, matching the recon-sensitive siblings below.
GET /api/v1/discovery/available-subscriptions admin Subscriptions the identity can see.
GET /api/v1/discovery/available-management-groups admin Management groups the identity can see. ?management_group_id=<name> expands one, separating readable from unreadable member subscriptions; add &verify=true to test each with the same subscription-wide read discovery actually makes (one ARM call per subscription, opt-in).
POST /api/v1/discovery/run admin Discover and apply subnet mappings now; returns {upserted, removed, complete}. ?dry_run=true returns the diff an apply would make (additions, removals, new_regions) and writes nothing. Removals are only proposed or applied from a complete cycle. Also applies pending management-group membership drift (additions and true removals; a still-in-group subscription the identity lost access to is never dropped) before discovering.
GET /api/v1/discovery/status admin The periodic detector’s last result and pending drift, from memory (cheap to poll). {"observed": false} until a first cycle completes. Includes membership_drift per management-group scope: added / removed (proposals) and lost_access (reported, never proposed for removal).
POST /api/v1/tag-registration/run admin Run a tag-registration cycle now; returns {updated, drained, skipped, unclaimed}.
POST /api/v1/discovery/private-endpoints/run admin Run a Private Endpoint reconcile now; returns created/updated/reaped/unsupported counts.
Method Path Purpose
GET/PUT /api/v1/config/rate-limits Per-IP API rate limits in four classes (auth, write, read, upload; the upload class covers the disk-staging endpoints /api/v1/restore and /api/v1/admin/compact, with a deliberately severe default). GET reports the configured values, not what is in force: 0 means the built-in default applies, not that the limiter is off.
GET/PUT /api/v1/config/delete-guardrails Bulk-delete cap (bulk_delete_cap, default 100) and the default for new-zone deletion locks (default_zone_deletion_lock).
GET/PUT /api/v1/config/region-discovery Azure discovery backend (mode: arm-list or resource-graph).
GET/PUT /api/v1/config/axfr Zone-transfer (AXFR) settings, including outbound DNS NOTIFY (notify_targets, notify_tsig_key_name, notify_debounce_seconds); applies live, cluster-wide. See the configuration reference.
GET/PUT /api/v1/config/query-log Per-query logging (enabled, plus sample_rate to keep 1-in-N); applies live, cluster-wide.
GET/PUT /api/v1/config/dynamic-dns RFC 2136 dynamic-DNS settings.
GET/PUT /api/v1/config/cache Forwarded-response cache.
GET/PUT /api/v1/config/replication Cluster replication timing (applied on restart).
GET/PUT /api/v1/config/health-probe-policy TLS policy for authenticated probes (allow_insecure_authenticated_probes; audit-logged).
GET/PUT /api/v1/transport-config DNS-over-TLS and DNS-over-HTTPS listeners (dot_enabled, dot_listen_addr, doh_enabled, doh_listen_addr); applies live, cluster-wide. GET is readable by any authenticated role; PUT is admin.
GET/PUT /api/v1/observability/otlp OTLP metrics export.
Method Path Purpose
POST /api/v1/debug/enable Open a time-boxed debug logging window (admin).
POST /api/v1/debug/disable Close the window early (admin).
GET /api/v1/debug/status Whether the window is open (any authenticated role).
GET /api/v1/debug/tail The captured lines retained in memory on the node that answers (last 1000, with node_id, dropped and capacity); admin only. Debug capture is node-local, never replicated.
DELETE /api/v1/debug/tail Discard the answering node’s retained lines (admin).

Both /api/v1/debug/tail calls require the X-DTM-CSRF: 1 header (the GET is a sensitive read). The buffer is kept when the window closes or expires, so a capture survives the window it was taken in. See capture debug output.

Method Path Purpose
GET /api/v1/backup Stream a point-in-time snapshot, optionally passphrase-encrypted (X-DTM-Backup-Passphrase header).
POST /api/v1/restore Stage a snapshot (applied on restart); an encrypted snapshot needs the same passphrase header.
POST /api/v1/admin/compact Stage a compacted database copy.
POST /api/v1/support-bundle Build a support bundle, optionally passphrase-encrypted.

See backup and restore.

Method Path Purpose
GET /healthz Liveness.
GET /readyz Readiness state.
GET /metrics Prometheus metrics.
GET/POST /dns-query DNS-over-HTTPS (RFC 8484), opt-in. Served by a dedicated listener on its own port (443 by default), never by the API port; the DoH listener serves nothing else.
Method Path Role Purpose
GET /api/v1/audit editor Query the audit log (filters: user_id, user_name, resource, resource_id, action, from, to, limit).
GET /api/v1/audit/export editor Export the audit log as NDJSON (same filters).
GET /api/v1/stats read Zone / record / node / user counts.