API reference

The ZeroDrop control plane is a JSON HTTP API. It's OpenAPI-firstapi/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

StatusDescriptionBody
201Account created (no session is started)
400ErrorError
403ErrorError
409ErrorError
422ErrorError
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

StatusDescriptionBody
200Password accepted; a TOTP code is required to finishTOTPRequired
204Signed in; sets the zd_session cookie
400ErrorError
401ErrorError
403ErrorError
POST /v1/auth/login/totp Public

Complete a two-factor sign-in with a TOTP code

Request body — JSON — TOTPCode

Responses

StatusDescriptionBody
204Signed in; sets the zd_session cookie
400ErrorError
401ErrorError
POST /v1/auth/logout Session or bearer token

Sign out and clear the session

Responses

StatusDescriptionBody
204Signed 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

StatusDescriptionBody
200OKAuthConfig
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

StatusDescriptionBody
204Accepted
400ErrorError
403ErrorError
POST /v1/auth/password/reset Public

Set a new password using a reset token

Request body — JSON — object: token, password

Responses

StatusDescriptionBody
204Password updated; existing sessions are invalidated
400ErrorError
410ErrorError
422ErrorError
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

StatusDescriptionBody
204Password changed; session refreshed
400ErrorError
401ErrorError
409ErrorError
422ErrorError
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

StatusDescriptionBody
204Email verified
400ErrorError
410ErrorError
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

StatusDescriptionBody
204Accepted
401ErrorError
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

StatusDescriptionBody
204Accepted; sets the zd_early_access cookie
400ErrorError
401ErrorError
429ErrorError
GET /v1/auth/totp Session or bearer token

Report whether two-factor authentication is enabled

Responses

StatusDescriptionBody
200OKobject: enabled
401ErrorError
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

StatusDescriptionBody
200OKobject: secret, otpauth_url
401ErrorError
409ErrorError
503ErrorError
POST /v1/auth/totp/enable Session or bearer token

Confirm TOTP enrollment with a code

Request body — JSON — TOTPCode

Responses

StatusDescriptionBody
204Two-factor authentication enabled
401ErrorError
422ErrorError
POST /v1/auth/totp/disable Session or bearer token

Disable TOTP after verifying a current code

Request body — JSON — TOTPCode

Responses

StatusDescriptionBody
204Two-factor authentication disabled
401ErrorError
422ErrorError
GET /v1/auth/passkey Session or bearer token

List the current user's passkeys

Responses

StatusDescriptionBody
200OKPasskey array
401ErrorError
DELETE /v1/auth/passkey/{id} Session or bearer token

Remove one of the current user's passkeys

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
204Passkey removed
401ErrorError
404ErrorError

Account

GET /v1/api-tokens Session or bearer token

List the org's API tokens

Responses

StatusDescriptionBody
200OKApiToken array
401ErrorError
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

StatusDescriptionBody
201CreatedApiTokenSecret
401ErrorError
422ErrorError
DELETE /v1/api-tokens/{id} Session or bearer token

Revoke an API token

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
204Token revoked
401ErrorError
404ErrorError
GET /v1/me Session or bearer token

Get the authenticated identity

Responses

StatusDescriptionBody
200OKobject: user_id, org_id, email, email_verified
401ErrorError
GET /v1/settings Session or bearer token

Get the org's settings

Responses

StatusDescriptionBody
200OKSettings
401ErrorError
PUT /v1/settings Session or bearer token

Update the org's settings

Request body — JSON — SettingsUpdate

Responses

StatusDescriptionBody
200OKSettings
422ErrorError

Checks

POST /v1/http-checks Session or bearer token

Create an HTTP check

Request body — JSON — HTTPCheckRequest

Responses

StatusDescriptionBody
201CreatedHTTPCheck
400ErrorError
401ErrorError
403ErrorError
409ErrorError
422ErrorError
GET /v1/http-checks/{id} Session or bearer token

Get an HTTP check

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200OKHTTPCheck
401ErrorError
404ErrorError
PUT /v1/http-checks/{id} Session or bearer token

Update an HTTP check

Parameters

NameInTypeDescription
id requiredpathstring

Request body — JSON — HTTPCheckRequest

Responses

StatusDescriptionBody
200OKHTTPCheck
401ErrorError
404ErrorError
409ErrorError
422ErrorError
DELETE /v1/http-checks/{id} Session or bearer token

Delete an HTTP check

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
204Deleted
401ErrorError
404ErrorError
POST /v1/smtp-checks Session or bearer token

Create an SMTP check

Request body — JSON — SMTPCheckRequest

Responses

StatusDescriptionBody
201CreatedSMTPCheck
400ErrorError
401ErrorError
403ErrorError
409ErrorError
422ErrorError
GET /v1/smtp-checks/{id} Session or bearer token

Get an SMTP check

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200OKSMTPCheck
401ErrorError
404ErrorError
PUT /v1/smtp-checks/{id} Session or bearer token

Update an SMTP check

Parameters

NameInTypeDescription
id requiredpathstring

Request body — JSON — SMTPCheckRequest

Responses

StatusDescriptionBody
200OKSMTPCheck
401ErrorError
404ErrorError
409ErrorError
422ErrorError
DELETE /v1/smtp-checks/{id} Session or bearer token

Delete an SMTP check

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
204Deleted
401ErrorError
404ErrorError
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

NameInTypeDescription
org requiredpathstring

Request body — JSON — object: http, smtp

Responses

StatusDescriptionBody
200Reconciledobject: created, updated, deleted
401ErrorError
403ErrorError
422ErrorError
GET /v1/checks Session or bearer token

List all checks in the caller's org with their current status

Responses

StatusDescriptionBody
200OKCheckList
401ErrorError
GET /v1/locations Session or bearer token

List active probe locations a check can target

Responses

StatusDescriptionBody
200OKobject: locations
401ErrorError
GET /v1/checks/{id}/status Session or bearer token

Get a check's current alert status and per-location results

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200OKobject: check_id, status, opened_at, locations
404ErrorError
GET /v1/checks/metrics Session or bearer token

Range-query one averaged-per-check series for every check (dashboard sparklines)

Parameters

NameInTypeDescription
metricquerystringMetric to aggregate per check (zerodrop_* only). Defaults to zerodrop_request_latency_ms.
rangequerystringLookback window (Go duration, also d/w), e.g. 24h. Defaults to 24h.
stepquerystringSample step (Go duration, also d/w), e.g. 30m. Defaults to 30m.

Responses

StatusDescriptionBody
200VictoriaMetrics range-query JSON
422ErrorError
503ErrorError
GET /v1/checks/{id}/metrics Session or bearer token

Range-query a check's metrics (forced to the caller's tenant)

Parameters

NameInTypeDescription
id requiredpathstring
metricquerystringDefaults to zerodrop_probe_success.
rangequerystringLookback window as a Go duration, also accepting d (days) and w (weeks), e.g. 1h, 24h, 7d. Defaults to 1h.
stepquerystringSample step as a Go duration (d/w also accepted), e.g. 1m, 10m, 1h. Defaults to 1m.

Responses

StatusDescriptionBody
200VictoriaMetrics range-query JSON
404ErrorError
422ErrorError
503ErrorError
GET /v1/checks/{id}/channels Session or bearer token

List the channels notified for a check

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200OKobject: channel_ids
PUT /v1/checks/{id}/channels Session or bearer token

Replace the channels notified for a check

Parameters

NameInTypeDescription
id requiredpathstring

Request body — JSON — object: channel_ids

Responses

StatusDescriptionBody
204Updated
404ErrorError
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

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200SVG badge
404ErrorError
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

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200SVG badge
404ErrorError
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

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200SVG badge
404ErrorError
GET /v1/checks/{id}/incidents Session or bearer token

List one check's incidents (newest first, paged)

Parameters

NameInTypeDescription
id requiredpathstring
limitqueryintegerDefaults to 50.
offsetqueryintegerDefaults to 0.

Responses

StatusDescriptionBody
200OKIncident array
401ErrorError
404ErrorError

Notifications

GET /v1/notification-channels Session or bearer token

List notification channels

Responses

StatusDescriptionBody
200OKChannel array
POST /v1/notification-channels Session or bearer token

Create a notification channel

Request body — JSON — object: type, config

Responses

StatusDescriptionBody
201CreatedChannel
422ErrorError
GET /v1/notification-channels/{id} Session or bearer token

Get a notification channel

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200OKChannel
404ErrorError
DELETE /v1/notification-channels/{id} Session or bearer token

Delete a notification channel

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
204Deleted
404ErrorError
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

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
204Verified
404ErrorError
500ErrorError
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

StatusDescriptionBody
204Channel confirmed
400ErrorError
410ErrorError

Maintenance

GET /v1/maintenance-windows Session or bearer token

List maintenance windows

Responses

StatusDescriptionBody
200OKMaintenanceWindow array
POST /v1/maintenance-windows Session or bearer token

Create a maintenance window

Request body — JSON — object: check_id, starts_at, ends_at, reason

Responses

StatusDescriptionBody
201CreatedMaintenanceWindow
422ErrorError
DELETE /v1/maintenance-windows/{id} Session or bearer token

Delete a maintenance window

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
204Deleted
404ErrorError

Incidents

GET /v1/incidents Session or bearer token

List incidents (newest first, paged)

Parameters

NameInTypeDescription
limitqueryintegerDefaults to 50.
offsetqueryintegerDefaults to 0.

Responses

StatusDescriptionBody
200OKIncident array
GET /v1/incidents/{id} Session or bearer token

Get an incident with its notification timeline

Parameters

NameInTypeDescription
id requiredpathstring

Responses

StatusDescriptionBody
200OKIncidentDetail
401ErrorError
404ErrorError

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

StatusDescriptionBody
200The full dashboard payload.object: generated_at, locations, categories
304Not Modified
503ErrorError

Other

GET /v1/audit-events Session or bearer token

List the org's audit log (newest first, paged)

Parameters

NameInTypeDescription
limitqueryintegerDefaults to 50.
offsetqueryintegerDefaults to 0.

Responses

StatusDescriptionBody
200OKAuditEvent array
401ErrorError

Schemas

Error

FieldTypeDescription
error requiredstringHuman-readable

Credentials

FieldTypeDescription
email requiredstring (email)
password requiredstring
turnstile_tokenstringCloudflare Turnstile token; required when Turnstile is enabled (see GET /v1/auth/config).

AuthConfig

FieldTypeDescription
turnstile_site_key requiredstringCloudflare Turnstile site key for the SPA to render the widget; empty when Turnstile is disabled.

Settings

FieldTypeDescription
org_name requiredstringAccount/organization display name
timezone requiredstringIANA timezone name for displaying times, e.g. Europe/Copenhagen
max_checks required read-onlyintegerMaximum number of checks the org may create
min_interval_seconds required read-onlyintegerMinimum allowed check interval in seconds
notify_repeat_interval_seconds requiredintegerRe-notify cadence for ongoing incidents, in seconds; 0 disables reminders

SettingsUpdate

Fields are optional; only those present are updated.

FieldTypeDescription
org_namestringAccount/organization display name (1–80 chars)
timezonestringIANA timezone name for displaying times, e.g. Europe/Copenhagen
notify_repeat_interval_secondsintegerRe-notify cadence for ongoing incidents, in seconds; 0 (off) or 300–604800

TOTPRequired

FieldTypeDescription
totp_required requiredbooleanTrue when a TOTP code is needed to finish sign-in

TOTPCode

FieldTypeDescription
code requiredstringSix-digit code from the authenticator app

Passkey

FieldTypeDescription
id requiredstring
name requiredstring
created_at requiredstring (date-time)

ApiToken

FieldTypeDescription
id requiredstring
name requiredstring
hintstringNon-sensitive fingerprint of the token (prefix + a few chars, e.g. zd_a1b2…9z0f). Empty for tokens created before this was captured.
created_at requiredstring (date-time)
last_used_atstring (date-time)
expires_atstring (date-time)

ApiTokenSecret

All fields of ApiToken, plus:

FieldTypeDescription
token requiredstringThe raw secret, shown only once at creation

Channel

FieldTypeDescription
idstring
typestring (webhook | email)
configobject
verifiedboolean
created_atstring (date-time)

AuditEvent

FieldTypeDescription
id requiredstring
user_idstringThe acting user (empty for unattributed events)
user_emailstringThe acting user's email (empty for unattributed events or a since-deleted user)
event_type requiredstringDot-namespaced event id, e.g. auth.login.success
ipstring
geo_countrystringISO country code
geo_citystring
user_agentstring
methodstringHTTP method of the API request
pathstringAPI endpoint
ui_pathstringConsole route the action came from
detailobjectEvent-specific extra fields
created_at requiredstring (date-time)

MaintenanceWindow

FieldTypeDescription
idstring
check_idstring
starts_atstring (date-time)
ends_atstring (date-time)
reasonstring

Incident

FieldTypeDescription
idstring
check_idstring
check_namestring
opened_atstring (date-time)
resolved_atstring (date-time)
causestring
failing_locationsstring[]

IncidentNotification

One notification delivery recorded for an incident.

FieldTypeDescription
idstring
eventstringThe transition that triggered it, e.g. fired or resolved
channel_typestring (webhook | email)
targetstringThe channel's destination (email address or webhook URL)
sent_atstring (date-time)
statusstringsent or failed
responsestringDelivery detail — an HTTP status code or an error message

IncidentDetail

All fields of Incident, plus:

FieldTypeDescription
notificationsIncidentNotification[]

HTTPCheckRequest

FieldTypeDescription
name requiredstringUnique per org
enabledboolean
interval_secondsintegerDefaults to 60s (1 minute), the minimum
timeout_msinteger
consensus_fractionnumberFraction of live locations that must fail (0, 1]
consensus_floorintegerMinimum number of locations that must report down simultaneously to alert
fire_evalsintegerConsecutive breaching evals before firing
resolve_evalsintegerConsecutive healthy evals before resolving
url requiredstring
methodstring
expected_statusinteger
body_patternstringSubstring/regex expected in the body
follow_redirectsboolean
max_redirectsinteger
verify_certbooleanWhether the server's TLS certificate must validate against the trust store
min_cert_daysintegerFail the check when the TLS certificate has fewer than this many days of validity left; 0 disables the check
public_badgebooleanExpose public status/uptime/SSL badges for this check at /v1/checks/{id}/badge.svg, /uptime.svg and /ssl.svg (unauthenticated SVG)
locations read-onlystring[]Assigned by the server — every check probes from all active locations

HTTPCheck

All fields of HTTPCheckRequest, plus:

FieldTypeDescription
id requiredstring
type requiredstring (http)
created_at requiredstring (date-time)
updated_at requiredstring (date-time)

SMTPCheckRequest

FieldTypeDescription
name requiredstringUnique per org
enabledboolean
interval_secondsintegerDefaults to 60s (1 minute), the minimum
timeout_msinteger
consensus_fractionnumberFraction of live locations that must fail (0, 1]
consensus_floorintegerMinimum number of locations that must report down simultaneously to alert
fire_evalsintegerConsecutive breaching evals before firing
resolve_evalsintegerConsecutive healthy evals before resolving
host requiredstring
portinteger
starttlsboolean
expected_welcome_patternstringSubstring/regex expected in the 220 banner
verify_certbooleanWhether the STARTTLS certificate must validate against the trust store
min_cert_daysintegerFail the check when the STARTTLS certificate has fewer than this many days of validity left; 0 disables the check
public_badgebooleanExpose public status/uptime/SSL badges for this check at /v1/checks/{id}/badge.svg, /uptime.svg and /ssl.svg (unauthenticated SVG)
locations read-onlystring[]Assigned by the server — every check probes from all active locations

SMTPCheck

All fields of SMTPCheckRequest, plus:

FieldTypeDescription
id requiredstring
type requiredstring (smtp)
created_at requiredstring (date-time)
updated_at requiredstring (date-time)

CheckSummary

FieldTypeDescription
id requiredstring
name requiredstring
type requiredstring (http | smtp)
status requiredstring (ok | firing | unknown)Current alert status
opened_atstring (date-time)When the current incident opened
target requiredstringHTTP url, or smtp host:port
enabled requiredboolean
interval_seconds requiredinteger
public_badgebooleanWhether the check exposes public status/uptime/SSL badges
locations requiredstring[]

CheckList

FieldTypeDescription
checks requiredCheckSummary[]