API reference
The ZeroDrop control plane is a JSON HTTP API. It's OpenAPI-first — api/openapi.yaml is the source of truth, and this page is generated from it.
Base URL
In production the API is served under /api, so every path below is prefixed with it — e.g. POST /api/v1/http-checks. The paths shown here are as the backend sees them (/v1/...).
Authentication
Two schemes are accepted:
- Bearer token — send
Authorization: Bearer <token> from scripts and automation. Create tokens on the API tokens page (see the user guide). This is the right choice for anything non-interactive, and bearer requests are exempt from CSRF.
- Session cookie (
zd_session) — set by the browser sign-in flow and used by the console. Cookie-authenticated mutations must carry a matching Origin.
Endpoints marked Public need no authentication.
Conventions
- Request and response bodies are
application/json.
- Errors use a consistent shape — an
Error object with a single human-readable, actionable error string — and the matching HTTP status.
- Mutating requests are rate-limited per organisation; exceeding the limit returns
429. Reads are not throttled.
Managing checks as code
PUT /v1/tenants/{org}/checks reconciles your entire set of checks against the request body in one transaction: checks are created or updated by name, and any check absent from the body is deleted. Keep the desired set in version control and apply it idempotently.
Authentication
POST
/v1/auth/signup
Public
Create an account
Request body — JSON — Credentials
Responses
| Status | Description | Body |
201 | Account created (no session is started) | |
400 | Error | Error |
403 | Error | Error |
409 | Error | Error |
422 | Error | Error |
POST
/v1/auth/login
Public
Sign in with email and password
Returns 204 and sets the session cookie when the account has no second factor. When two-factor authentication is enabled it returns 200 with {"totp_required": true} and sets a short-lived pending cookie; complete the sign-in via POST /v1/auth/login/totp.
Request body — JSON — Credentials
Responses
| Status | Description | Body |
200 | Password accepted; a TOTP code is required to finish | TOTPRequired |
204 | Signed in; sets the zd_session cookie | |
400 | Error | Error |
401 | Error | Error |
403 | Error | Error |
POST
/v1/auth/login/totp
Public
Complete a two-factor sign-in with a TOTP code
Request body — JSON — TOTPCode
Responses
| Status | Description | Body |
204 | Signed in; sets the zd_session cookie | |
400 | Error | Error |
401 | Error | Error |
POST
/v1/auth/logout
Session or bearer token
Sign out and clear the session
Responses
| Status | Description | Body |
204 | Signed out; clears the zd_session cookie | |
GET
/v1/auth/config
Public
Public client configuration for the auth flows
Returns configuration the SPA needs before authenticating, currently the Cloudflare Turnstile site key. The key is empty when Turnstile is disabled.
Responses
POST
/v1/auth/password/forgot
Public
Request a password-reset link
Always returns 204, whether or not the email is registered, to avoid revealing which addresses have accounts.
Request body — JSON — object: email, turnstile_token
Responses
| Status | Description | Body |
204 | Accepted | |
400 | Error | Error |
403 | Error | Error |
POST
/v1/auth/password/reset
Public
Set a new password using a reset token
Request body — JSON — object: token, password
Responses
| Status | Description | Body |
204 | Password updated; existing sessions are invalidated | |
400 | Error | Error |
410 | Error | Error |
422 | Error | Error |
POST
/v1/auth/password/change
Session or bearer token
Change the signed-in user's password
Verifies the current password and sets a new one. Other sessions are invalidated; this session is refreshed (new cookie).
Request body — JSON — object: current_password, new_password
Responses
| Status | Description | Body |
204 | Password changed; session refreshed | |
400 | Error | Error |
401 | Error | Error |
409 | Error | Error |
422 | Error | Error |
POST
/v1/auth/email/verify
Public
Confirm an email address using a verification token
Consumes the single-use token from the confirmation link and marks the account's email verified. Public, since the user may not be signed in when they click the link.
Request body — JSON — object: token
Responses
| Status | Description | Body |
204 | Email verified | |
400 | Error | Error |
410 | Error | Error |
POST
/v1/auth/email/resend
Session or bearer token
Resend the signed-in user's verification email
Re-issues and emails a fresh confirmation link for the authenticated user. Always returns 204; already-verified accounts are a no-op, and the send is rate-limited per account.
Responses
| Status | Description | Body |
204 | Accepted | |
401 | Error | Error |
POST
/v1/early-access
Public
Unlock the pre-launch early-access gate
Validates the shared early-access password. On success sets the zd_early_access cookie (HttpOnly, ~30 days) that the edge proxy checks before serving the marketing site and console. The attempt is rate-limited per client IP. Only mounted when the server is configured with an early-access password; otherwise the site is fully open and this endpoint is absent.
Request body — JSON — object: password
Responses
| Status | Description | Body |
204 | Accepted; sets the zd_early_access cookie | |
400 | Error | Error |
401 | Error | Error |
429 | Error | Error |
GET
/v1/auth/totp
Session or bearer token
Report whether two-factor authentication is enabled
Responses
| Status | Description | Body |
200 | OK | object: enabled |
401 | Error | Error |
POST
/v1/auth/totp/setup
Session or bearer token
Begin TOTP enrollment
Generates a pending secret and the otpauth:// URL for an authenticator app.
Responses
| Status | Description | Body |
200 | OK | object: secret, otpauth_url |
401 | Error | Error |
409 | Error | Error |
503 | Error | Error |
POST
/v1/auth/totp/enable
Session or bearer token
Confirm TOTP enrollment with a code
Request body — JSON — TOTPCode
Responses
| Status | Description | Body |
204 | Two-factor authentication enabled | |
401 | Error | Error |
422 | Error | Error |
POST
/v1/auth/totp/disable
Session or bearer token
Disable TOTP after verifying a current code
Request body — JSON — TOTPCode
Responses
| Status | Description | Body |
204 | Two-factor authentication disabled | |
401 | Error | Error |
422 | Error | Error |
GET
/v1/auth/passkey
Session or bearer token
List the current user's passkeys
Responses
DELETE
/v1/auth/passkey/{id}
Session or bearer token
Remove one of the current user's passkeys
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
204 | Passkey removed | |
401 | Error | Error |
404 | Error | Error |
Account
GET
/v1/api-tokens
Session or bearer token
List the org's API tokens
Responses
POST
/v1/api-tokens
Session or bearer token
Issue a new API token
The raw token secret is returned only once, in this response.
Request body — JSON — object: name
Responses
DELETE
/v1/api-tokens/{id}
Session or bearer token
Revoke an API token
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
204 | Token revoked | |
401 | Error | Error |
404 | Error | Error |
GET
/v1/me
Session or bearer token
Get the authenticated identity
Responses
| Status | Description | Body |
200 | OK | object: user_id, org_id, email, email_verified |
401 | Error | Error |
GET
/v1/settings
Session or bearer token
Get the org's settings
Responses
PUT
/v1/settings
Session or bearer token
Update the org's settings
Request body — JSON — SettingsUpdate
Responses
Checks
POST
/v1/http-checks
Session or bearer token
Create an HTTP check
Request body — JSON — HTTPCheckRequest
Responses
GET
/v1/http-checks/{id}
Session or bearer token
Get an HTTP check
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
PUT
/v1/http-checks/{id}
Session or bearer token
Update an HTTP check
Parameters
| Name | In | Type | Description |
id required | path | string | |
Request body — JSON — HTTPCheckRequest
Responses
DELETE
/v1/http-checks/{id}
Session or bearer token
Delete an HTTP check
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
204 | Deleted | |
401 | Error | Error |
404 | Error | Error |
POST
/v1/smtp-checks
Session or bearer token
Create an SMTP check
Request body — JSON — SMTPCheckRequest
Responses
GET
/v1/smtp-checks/{id}
Session or bearer token
Get an SMTP check
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
PUT
/v1/smtp-checks/{id}
Session or bearer token
Update an SMTP check
Parameters
| Name | In | Type | Description |
id required | path | string | |
Request body — JSON — SMTPCheckRequest
Responses
DELETE
/v1/smtp-checks/{id}
Session or bearer token
Delete an SMTP check
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
204 | Deleted | |
401 | Error | Error |
404 | Error | Error |
PUT
/v1/tenants/{org}/checks
Session or bearer token
Declaratively reconcile all checks for an org
Replaces the org's full set of checks with the request body, in one transaction: items are created or updated (keyed by name), and any check absent from the body is deleted. The whole set is validated and quota-checked before anything is committed.
Parameters
| Name | In | Type | Description |
org required | path | string | |
Request body — JSON — object: http, smtp
Responses
| Status | Description | Body |
200 | Reconciled | object: created, updated, deleted |
401 | Error | Error |
403 | Error | Error |
422 | Error | Error |
GET
/v1/checks
Session or bearer token
List all checks in the caller's org with their current status
Responses
GET
/v1/locations
Session or bearer token
List active probe locations a check can target
Responses
| Status | Description | Body |
200 | OK | object: locations |
401 | Error | Error |
GET
/v1/checks/{id}/status
Session or bearer token
Get a check's current alert status and per-location results
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
200 | OK | object: check_id, status, opened_at, locations |
404 | Error | Error |
GET
/v1/checks/metrics
Session or bearer token
Range-query one averaged-per-check series for every check (dashboard sparklines)
Parameters
| Name | In | Type | Description |
metric | query | string | Metric to aggregate per check (zerodrop_* only). Defaults to zerodrop_request_latency_ms. |
range | query | string | Lookback window (Go duration, also d/w), e.g. 24h. Defaults to 24h. |
step | query | string | Sample step (Go duration, also d/w), e.g. 30m. Defaults to 30m. |
Responses
| Status | Description | Body |
200 | VictoriaMetrics range-query JSON | |
422 | Error | Error |
503 | Error | Error |
GET
/v1/checks/{id}/metrics
Session or bearer token
Range-query a check's metrics (forced to the caller's tenant)
Parameters
| Name | In | Type | Description |
id required | path | string | |
metric | query | string | Defaults to zerodrop_probe_success. |
range | query | string | Lookback window as a Go duration, also accepting d (days) and w (weeks), e.g. 1h, 24h, 7d. Defaults to 1h. |
step | query | string | Sample step as a Go duration (d/w also accepted), e.g. 1m, 10m, 1h. Defaults to 1m. |
Responses
| Status | Description | Body |
200 | VictoriaMetrics range-query JSON | |
404 | Error | Error |
422 | Error | Error |
503 | Error | Error |
GET
/v1/checks/{id}/channels
Session or bearer token
List the channels notified for a check
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
200 | OK | object: channel_ids |
PUT
/v1/checks/{id}/channels
Session or bearer token
Replace the channels notified for a check
Parameters
| Name | In | Type | Description |
id required | path | string | |
Request body — JSON — object: channel_ids
Responses
| Status | Description | Body |
204 | Updated | |
404 | Error | Error |
GET
/v1/checks/{id}/badge.svg
Public
Public status badge (shields.io-style SVG)
Unauthenticated SVG badge showing the check name and current status (up/down/unknown) in an appropriate color. Available only for checks with public_badge enabled; a non-opted-in or unknown check returns 404. Cached for 60s.
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
200 | SVG badge | |
404 | Error | Error |
GET
/v1/checks/{id}/uptime.svg
Public
Public uptime badge (shields.io-style SVG)
Unauthenticated SVG badge showing the check name and its 30-day success ratio, colored by threshold. Available only for checks with public_badge enabled; a non-opted-in or unknown check returns 404. Cached for 60s.
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
200 | SVG badge | |
404 | Error | Error |
GET
/v1/checks/{id}/ssl.svg
Public
Public SSL-expiry badge (shields.io-style SVG)
Unauthenticated SVG badge showing the check name and the number of days until its TLS certificate expires (soonest across locations), colored by threshold. Available only for checks with public_badge enabled; a non-opted-in or unknown check returns 404. Cached for 60s.
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
200 | SVG badge | |
404 | Error | Error |
GET
/v1/checks/{id}/incidents
Session or bearer token
List one check's incidents (newest first, paged)
Parameters
| Name | In | Type | Description |
id required | path | string | |
limit | query | integer | Defaults to 50. |
offset | query | integer | Defaults to 0. |
Responses
Notifications
GET
/v1/notification-channels
Session or bearer token
List notification channels
Responses
| Status | Description | Body |
200 | OK | Channel array |
POST
/v1/notification-channels
Session or bearer token
Create a notification channel
Request body — JSON — object: type, config
Responses
GET
/v1/notification-channels/{id}
Session or bearer token
Get a notification channel
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
DELETE
/v1/notification-channels/{id}
Session or bearer token
Delete a notification channel
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
204 | Deleted | |
404 | Error | Error |
POST
/v1/notification-channels/{id}/verify
Session or bearer token
Start (or re-send) channel confirmation
Email channels get double opt-in: a confirmation link is mailed to the address and the channel stays unverified until the recipient clicks it. Webhook channels (and email channels when no mailer is configured) are marked verified immediately.
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
204 | Verified | |
404 | Error | Error |
500 | Error | Error |
POST
/v1/notification-channels/verify/confirm
Public
Confirm an email channel using a confirmation token
Consumes the single-use token from the confirmation link mailed to the channel's address and marks the channel verified. Public, since the link is clicked from the recipient's inbox.
Request body — JSON — object: token
Responses
| Status | Description | Body |
204 | Channel confirmed | |
400 | Error | Error |
410 | Error | Error |
Maintenance
GET
/v1/maintenance-windows
Session or bearer token
List maintenance windows
Responses
POST
/v1/maintenance-windows
Session or bearer token
Create a maintenance window
Request body — JSON — object: check_id, starts_at, ends_at, reason
Responses
DELETE
/v1/maintenance-windows/{id}
Session or bearer token
Delete a maintenance window
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
| Status | Description | Body |
204 | Deleted | |
404 | Error | Error |
Incidents
GET
/v1/incidents
Session or bearer token
List incidents (newest first, paged)
Parameters
| Name | In | Type | Description |
limit | query | integer | Defaults to 50. |
offset | query | integer | Defaults to 0. |
Responses
| Status | Description | Body |
200 | OK | Incident array |
GET
/v1/incidents/{id}
Session or bearer token
Get an incident with its notification timeline
Parameters
| Name | In | Type | Description |
id required | path | string | |
Responses
Public
GET
/v1/public/dashboard
Public
Public "Global Dashboard" snapshot (unauthenticated, heavily cached)
Pre-rendered, periodically-refreshed view of the reserved public showcase tenant's checks, grouped into categories. Unauthenticated and scoped server-side to the showcase org. Sends Cache-Control and ETag for edge and conditional caching; 503 until the first snapshot is built (or if metrics are disabled).
Responses
| Status | Description | Body |
200 | The full dashboard payload. | object: generated_at, locations, categories |
304 | Not Modified | |
503 | Error | Error |
Other
GET
/v1/audit-events
Session or bearer token
List the org's audit log (newest first, paged)
Parameters
| Name | In | Type | Description |
limit | query | integer | Defaults to 50. |
offset | query | integer | Defaults to 0. |
Responses
Schemas
Error
| Field | Type | Description |
error required | string | Human-readable |
Credentials
| Field | Type | Description |
email required | string (email) | |
password required | string | |
turnstile_token | string | Cloudflare Turnstile token; required when Turnstile is enabled (see GET /v1/auth/config). |
AuthConfig
| Field | Type | Description |
turnstile_site_key required | string | Cloudflare Turnstile site key for the SPA to render the widget; empty when Turnstile is disabled. |
Settings
| Field | Type | Description |
org_name required | string | Account/organization display name |
timezone required | string | IANA timezone name for displaying times, e.g. Europe/Copenhagen |
max_checks required read-only | integer | Maximum number of checks the org may create |
min_interval_seconds required read-only | integer | Minimum allowed check interval in seconds |
notify_repeat_interval_seconds required | integer | Re-notify cadence for ongoing incidents, in seconds; 0 disables reminders |
SettingsUpdate
Fields are optional; only those present are updated.
| Field | Type | Description |
org_name | string | Account/organization display name (1–80 chars) |
timezone | string | IANA timezone name for displaying times, e.g. Europe/Copenhagen |
notify_repeat_interval_seconds | integer | Re-notify cadence for ongoing incidents, in seconds; 0 (off) or 300–604800 |
TOTPRequired
| Field | Type | Description |
totp_required required | boolean | True when a TOTP code is needed to finish sign-in |
TOTPCode
| Field | Type | Description |
code required | string | Six-digit code from the authenticator app |
Passkey
| Field | Type | Description |
id required | string | |
name required | string | |
created_at required | string (date-time) | |
ApiToken
| Field | Type | Description |
id required | string | |
name required | string | |
hint | string | Non-sensitive fingerprint of the token (prefix + a few chars, e.g. zd_a1b2…9z0f). Empty for tokens created before this was captured. |
created_at required | string (date-time) | |
last_used_at | string (date-time) | |
expires_at | string (date-time) | |
ApiTokenSecret
All fields of ApiToken, plus:
| Field | Type | Description |
token required | string | The raw secret, shown only once at creation |
Channel
| Field | Type | Description |
id | string | |
type | string (webhook | email) | |
config | object | |
verified | boolean | |
created_at | string (date-time) | |
AuditEvent
| Field | Type | Description |
id required | string | |
user_id | string | The acting user (empty for unattributed events) |
user_email | string | The acting user's email (empty for unattributed events or a since-deleted user) |
event_type required | string | Dot-namespaced event id, e.g. auth.login.success |
ip | string | |
geo_country | string | ISO country code |
geo_city | string | |
user_agent | string | |
method | string | HTTP method of the API request |
path | string | API endpoint |
ui_path | string | Console route the action came from |
detail | object | Event-specific extra fields |
created_at required | string (date-time) | |
MaintenanceWindow
| Field | Type | Description |
id | string | |
check_id | string | |
starts_at | string (date-time) | |
ends_at | string (date-time) | |
reason | string | |
Incident
| Field | Type | Description |
id | string | |
check_id | string | |
check_name | string | |
opened_at | string (date-time) | |
resolved_at | string (date-time) | |
cause | string | |
failing_locations | string[] | |
IncidentNotification
One notification delivery recorded for an incident.
| Field | Type | Description |
id | string | |
event | string | The transition that triggered it, e.g. fired or resolved |
channel_type | string (webhook | email) | |
target | string | The channel's destination (email address or webhook URL) |
sent_at | string (date-time) | |
status | string | sent or failed |
response | string | Delivery detail — an HTTP status code or an error message |
IncidentDetail
All fields of Incident, plus:
| Field | Type | Description |
notifications | IncidentNotification[] | |
HTTPCheckRequest
| Field | Type | Description |
name required | string | Unique per org |
enabled | boolean | |
interval_seconds | integer | Defaults to 60s (1 minute), the minimum |
timeout_ms | integer | |
consensus_fraction | number | Fraction of live locations that must fail (0, 1] |
consensus_floor | integer | Minimum number of locations that must report down simultaneously to alert |
fire_evals | integer | Consecutive breaching evals before firing |
resolve_evals | integer | Consecutive healthy evals before resolving |
url required | string | |
method | string | |
expected_status | integer | |
body_pattern | string | Substring/regex expected in the body |
follow_redirects | boolean | |
max_redirects | integer | |
verify_cert | boolean | Whether the server's TLS certificate must validate against the trust store |
min_cert_days | integer | Fail the check when the TLS certificate has fewer than this many days of validity left; 0 disables the check |
public_badge | boolean | Expose public status/uptime/SSL badges for this check at /v1/checks/{id}/badge.svg, /uptime.svg and /ssl.svg (unauthenticated SVG) |
locations read-only | string[] | Assigned by the server — every check probes from all active locations |
HTTPCheck
All fields of HTTPCheckRequest, plus:
| Field | Type | Description |
id required | string | |
type required | string (http) | |
created_at required | string (date-time) | |
updated_at required | string (date-time) | |
SMTPCheckRequest
| Field | Type | Description |
name required | string | Unique per org |
enabled | boolean | |
interval_seconds | integer | Defaults to 60s (1 minute), the minimum |
timeout_ms | integer | |
consensus_fraction | number | Fraction of live locations that must fail (0, 1] |
consensus_floor | integer | Minimum number of locations that must report down simultaneously to alert |
fire_evals | integer | Consecutive breaching evals before firing |
resolve_evals | integer | Consecutive healthy evals before resolving |
host required | string | |
port | integer | |
starttls | boolean | |
expected_welcome_pattern | string | Substring/regex expected in the 220 banner |
verify_cert | boolean | Whether the STARTTLS certificate must validate against the trust store |
min_cert_days | integer | Fail the check when the STARTTLS certificate has fewer than this many days of validity left; 0 disables the check |
public_badge | boolean | Expose public status/uptime/SSL badges for this check at /v1/checks/{id}/badge.svg, /uptime.svg and /ssl.svg (unauthenticated SVG) |
locations read-only | string[] | Assigned by the server — every check probes from all active locations |
SMTPCheck
All fields of SMTPCheckRequest, plus:
| Field | Type | Description |
id required | string | |
type required | string (smtp) | |
created_at required | string (date-time) | |
updated_at required | string (date-time) | |
CheckSummary
| Field | Type | Description |
id required | string | |
name required | string | |
type required | string (http | smtp) | |
status required | string (ok | firing | unknown) | Current alert status |
opened_at | string (date-time) | When the current incident opened |
target required | string | HTTP url, or smtp host:port |
enabled required | boolean | |
interval_seconds required | integer | |
public_badge | boolean | Whether the check exposes public status/uptime/SSL badges |
locations required | string[] | |
CheckList
| Field | Type | Description |
checks required | CheckSummary[] | |