Saltar al contenido principal

API overview

The ZTXBAS public API is small on purpose. Ten endpoints across four resources, all under /v1/*, plus two unauthenticated endpoints for health and key discovery.

Machine-readable spec

The authoritative specification is openapi.yaml in the repo. It's OpenAPI 3.1 and validates in Swagger Editor, Stoplight, and every codegen tool worth using.

Endpoints at a glance

VerbPathPurpose
POST/v1/usersEnroll a user; sends the setup email.
GET/v1/usersList users in the tenant.
DELETE/v1/usersDeregister a user (email in body).
POST/v1/originsRegister an origin.
GET/v1/originsList registered origins.
DELETE/v1/origins/{id}Delete an origin.
POST/v1/auth/challengeCreate a challenge, push to phone.
GET/v1/auth/status/{challenge_id}Poll for the challenge outcome.
GET/.well-known/jwks.jsonPublic keys for JWT verification.
GET/healthLiveness probe. No auth.

Everything under /v1/* requires HMAC-SHA256 signing - see HMAC signing for the canonical form. The SDKs handle it for you.

Authentication

Four headers on every /v1/* request:

X-Application-ID: app_...
X-Timestamp: 1704067200
X-Nonce: 32-hex-chars
X-Signature: hex(HMAC-SHA256(secret, canonical))

Missing or invalid → 401 UNAUTHORIZED with a specific error code telling you which check failed.

Error envelope

All 4xx/5xx responses share the same JSON shape:

{ "error": "UNREGISTERED_ORIGIN", "message": "origin not registered for this application" }
  • error is machine-readable and stable - code your retry / branching against it.
  • message is human-readable and may change; don't parse it.

Common codes:

CodeWhere it comes from
MISSING_AUTHOne of the four HMAC headers absent.
INVALID_SIGNATUREHMAC didn't verify.
INVALID_TIMESTAMPTimestamp negative or non-integer.
TIMESTAMP_EXPIREDTimestamp outside ±300 s of server clock.
INVALID_APPLICATIONX-Application-ID unknown.
BODY_TOO_LARGERequest body over 8 KiB.
DUPLICATE_EMAILRegistering a user that already exists.
UNREGISTERED_ORIGINChallenge origin wasn't POSTed to /v1/origins first.
USER_NOT_FOUNDChallenge/deregister for an unknown user.
ENROLLMENT_FAILEDServer couldn't dispatch the enrollment email.

Rate limits

None currently enforced by ZTXBAS itself. Run behind a reverse proxy (nginx, Caddy, Cloudflare) if you need per-tenant limits - the hardening guide covers a recommended baseline.