Authenticate your public API calls
The CaptainDNS public API authenticates requests through an API key sent in the HTTP Authorization header. No OAuth, no session, no cookies. This guide covers the key format, their lifecycle and storage best practices.
Sending the key
POST /public/v1/resolve HTTP/1.1
Host: api.captaindns.com
Authorization: Bearer cdns_live_a3f2XK7mN9QrVtZ4yP1sH6eL8cF2dB5aR3gW7kJxM
Content-Type: application/json
{"qname":"captaindns.com","qtype":"A"}
The scheme is always Bearer. Any other scheme triggers 401 INVALID_API_KEY. Keys are case-sensitive.
Key format
A key has three segments:
cdns_<environment>_<36 lowercase alphanumeric characters>
| Segment | Value | Usage |
|---|---|---|
cdns_ | Constant prefix | Visual recognition and GitHub scan pattern |
live or test | Environment | Isolation between production and experimentation |
| 36 chars | Base32 secret | 180 bits of entropy, unique per key |
The prefix shown in the dashboard is cdns_<env>_ followed by 8 characters. The full secret is never stored in the database; CaptainDNS keeps only its peppered HMAC-SHA256 hash.
Environments
cdns_test_* keys are technically identical to cdns_live_* keys: same endpoints, same scopes, same credit consumption. They exist so you can distinguish development traffic from production traffic in your logs and dashboards. We recommend creating one key per environment (dev, staging, CI).
Scopes
Each key carries one or several scopes. The scope guide lists them all; in short:
dns:read: DNS resolution, propagation, DNSSEC, IP WHOIS.mail:read: SPF, DKIM, DMARC, BIMI, MTA-STS, TLS-RPT, DANE, blacklist, SMTP, email header audit.mail:write: deliverability score (currently the only endpoint behind this scope).web:read: URL checks, page crawl, phishing detection.
A call to an endpoint whose scope is not present on the key returns 403 INSUFFICIENT_SCOPE.
Zero-downtime rotation
Do not swap a compromised or stale key in place. The supported flow is rotation:
- From the CaptainDNS dashboard, trigger a rotation on the target key.
- CaptainDNS generates a new key with the same scopes, limits and environment.
- The old key stays valid for 7 days. During this window, your services can migrate progressively.
- At the end of the grace period, the old key is automatically revoked.
Update your secrets manager before the grace period ends. After that, any request with the old key returns 401 REVOKED_API_KEY.
Immediate revocation
If a key leaks in public (Git repository, log, coworker leaving), two options:
- From the dashboard: revoke button on the key, confirmation click. Immediate effect, no grace period.
Requests in flight at the moment of revocation complete; new requests return 401 REVOKED_API_KEY.
IP allowlist
Business and Enterprise plans can restrict a key to a list of CIDR ranges. The check is applied upstream of the handler, so zero credits are consumed when the IP is not allowed. The response is 403 IP_NOT_ALLOWED, with the detected IP in details.
Example of a key restricted to a GitHub Actions runner range and a prod backend:
{
"ip_allowlist": [
"4.175.114.0/23",
"52.237.144.10/32"
]
}
Updating the list does not require rotation: edit the key from the dashboard and the new list takes effect within a minute.
Key storage best practices
- Secrets manager: 1Password, Doppler, AWS Secrets Manager, Vault. Never inline in committed
.envfiles or CI YAML. - Runtime environment variable: inject the key as an environment variable when the process starts. Avoid plaintext mounted files.
- Periodic rotation: 90 days for critical workloads, 180 days otherwise. Schedule it with a calendar reminder or, better, a CI job.
- No cross-team sharing: one key per service, not a master key shared across the SRE team. Incident revocation becomes surgical.
- Minimal scopes: if your integration only runs DMARC checks, do not grant
web:readnormail:write. Limit the blast radius.
Leak detection
CaptainDNS is registered with the GitHub secret scanning program. If you accidentally push a live key to a public repository, the cdns_live_* pattern is detected and the owner is notified. The key is automatically revoked. You will receive an email with the offending commit SHA and next steps to issue a new key.
Troubleshooting auth issues
401 INVALID_API_KEY: missing or wrong prefix, key absent afterBearer, tampered secret. Verify that no whitespace or newline slipped into your client.401 REVOKED_API_KEY: the key was revoked manually or automatically. Generate a new one.401 EXPIRED_API_KEY: you setexpires_atat creation and the date has passed. Create a new key or rotate this one beforehand.403 IP_NOT_ALLOWED: your source IP is not in the allowlist. Also verify that theX-Forwarded-Forheader is correctly forwarded through your proxy (private RFC1918 IPs are ignored and the immediate hop is used).500 INTERNAL_ERROR: indicates a CaptainDNS-side issue; open a support ticket with therequest_id.
Next, jump to the scope guide to pick the right permissions, or to rate limiting if you are preparing a high-frequency client.