Zauthy Documentation

Complete API reference for authentication, identity verification (KYC), and fraud prevention. Integrate secure user onboarding in minutes.

Quick Start

Get your first integration working in 4 steps.

1. Create an organization

Every Zauthy account starts with an organization (tenant). Sign up at the dashboard or use the API:

bash
curl -X POST https://api.zauthy.com/v1/organizations \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My App",
    "owner_email": "you@example.com",
    "owner_password": "SecureP@ss123"
  }'

Response

json
{
  "organization": {
    "id": "org_abc123",
    "name": "My App",
    "api_key": "sk_live_..."
  },
  "user": {
    "id": "usr_xyz789",
    "email": "you@example.com",
    "role": "owner"
  },
  "access_token": "eyJ...",
  "refresh_token": "eyJ..."
}

2. Install the SDK

bash
npm install @zauthy/sdk

3. Initialize the client

typescript
import { Zauthy } from '@zauthy/sdk';

const zauthy = new Zauthy({
  apiKey: process.env.ZAUTHY_SECRET_KEY,  // sk_live_...
  baseUrl: 'https://api.zauthy.com/v1'    // optional, defaults to production
});

4. Register your first user

typescript
const { user, access_token } = await zauthy.auth.signup({
  email: 'user@example.com',
  password: 'SecureP@ss123',
  name: 'Jane Doe'
});

console.log(user.id);  // usr_abc123
// Store access_token for subsequent requests

Authentication

All API requests require authentication via one of two methods:

API Key (server-side)

Use your organization API key for server-to-server calls. Never expose this in client-side code.

bash
Authorization: Bearer sk_live_your_api_key

JWT Token (user-level)

Use the access token from login/signup for user-scoped operations. Tokens expire after 15 minutes.

bash
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

API Key Security

Store API keys in environment variables. Never commit them to version control or embed in client-side code. Rotate keys immediately if compromised via the dashboard or DELETE /api-keys/{key_id}.

Error Handling

Zauthy uses standard HTTP status codes. All errors return a consistent JSON body:

json
{
  "detail": "Human-readable error message",
  "error": "error_code"       // machine-readable, when available
}
CodeMeaning
200Success
201Created
400Bad request — invalid parameters or validation failure
401Unauthorized — missing or invalid API key / token
403Forbidden — insufficient permissions or role
404Not found — resource does not exist
409Conflict — resource already exists (e.g., duplicate email)
429Rate limited — too many requests, retry after delay
500Internal error — contact support if persistent

Rate Limits

Rate limits vary by plan and endpoint category:

PlanAuth endpointsKYC endpointsGeneral
Free20/min10/min60/min
Pro100/min50/min300/min
EnterpriseCustomCustomCustom

When rate limited, you'll receive a 429 response. Implement exponential backoff in your integration.

Auth API

Base path: /api/v1

Signup & Login

POST/signup

Register a new user in your organization. Password must include uppercase, lowercase, digit, and special character (minimum 8 chars).

json
// Request
{
  "email": "user@example.com",
  "password": "SecureP@ss123",
  "name": "Jane Doe",           // optional
  "phone": "+1234567890"        // optional
}

// Response 201
{
  "user": {
    "id": "usr_abc123",
    "email": "user@example.com",
    "name": "Jane Doe",
    "role": "user",
    "is_verified": false,
    "created_at": "2026-03-07T10:00:00Z"
  },
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "bearer",
  "expires_in": 900
}
POST/login

Authenticate a user with email and password. Returns tokens for API access. Account locks after 5 failed attempts (30 min), 10 (2 hr), 15 (24 hr).

json
// Request
{
  "email": "user@example.com",
  "password": "SecureP@ss123"
}

// Response 200
{
  "user": { "id": "usr_abc123", "email": "user@example.com", "role": "user", ... },
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "bearer",
  "expires_in": 900,
  "mfa_required": false     // true if user has MFA enabled
}

// Response 200 (MFA required)
{
  "mfa_required": true,
  "mfa_token": "mfa_tmp_...",
  "mfa_methods": ["totp"]
}
POST/refresh

Exchange a refresh token for a new access token.

json
// Request
{ "refresh_token": "eyJ..." }

// Response 200
{
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",  // rotated
  "token_type": "bearer",
  "expires_in": 900
}
POST/logout

Invalidate the current session. Requires Bearer token.

json
// Response 200
{ "success": true }

Sessions & Tokens

GET/sessions

List all active sessions for the current user. Useful for 'active devices' UI.

DELETE/sessions/{session_id}

Revoke a specific session (remote logout).

DELETE/sessions

Revoke all sessions for the current user (logout everywhere).

POST/token/verify

Verify an access token is valid. Use this in your backend middleware.

json
// Request
{ "token": "eyJ..." }

// Response 200
{
  "valid": true,
  "user_id": "usr_abc123",
  "role": "user",
  "org_id": "org_xyz789",
  "expires_at": "2026-03-07T10:15:00Z"
}

Password Management

POST/password/forgot

Send a password reset email to the user.

json
// Request
{ "email": "user@example.com" }

// Response 200 (always succeeds to prevent email enumeration)
{ "message": "If an account exists, a reset link has been sent." }
POST/password/reset

Reset password using the token from the reset email.

json
// Request
{ "token": "reset_token_...", "new_password": "NewSecureP@ss123" }
POST/password/change

Change password for the authenticated user. Requires current password.

OTP Verification

POST/otp/send

Send a one-time passcode via email or SMS.

json
// Request
{
  "email": "user@example.com",    // or "phone": "+1234567890"
  "channel": "email"              // "email" or "sms"
}
POST/otp/verify

Verify an OTP code. Returns auth tokens on success.

json
// Request
{
  "email": "user@example.com",
  "code": "123456"
}

MFA / TOTP

POST/mfa/totp/setup

Generate a TOTP secret and QR code URI for the user to scan with their authenticator app.

json
// Response 200
{
  "secret": "JBSWY3DPEHPK3PXP",
  "qr_uri": "otpauth://totp/Zauthy:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Zauthy",
  "backup_codes": ["abc123", "def456", ...]
}
POST/mfa/totp/verify

Verify a TOTP code during login (when mfa_required is true) or to confirm MFA setup.

json
// Request
{
  "code": "123456",
  "mfa_token": "mfa_tmp_..."  // from login response
}
POST/mfa/disable

Disable MFA for the current user. Requires password confirmation.

Passkeys / WebAuthn

FIDO2/WebAuthn passkeys for passwordless authentication. Uses the browser's navigator.credentials API.

POST/passkey/register/start

Get WebAuthn registration options. Pass the response to navigator.credentials.create().

POST/passkey/register/finish

Complete passkey registration with the browser's credential response.

POST/passkey/authenticate/start

Get WebAuthn authentication options. Pass to navigator.credentials.get().

POST/passkey/authenticate/finish

Complete passkey authentication. Returns auth tokens on success.

GET/passkey/list

List all registered passkeys for the current user.

DELETE/passkey/{passkey_id}

Remove a registered passkey.

OAuth (Social Login)

Support for Google and Apple OAuth. Configure providers in your dashboard settings.

GET/auth/oauth/providers

List enabled OAuth providers for your organization.

POST/auth/oauth/init

Initialize an OAuth flow. Returns a redirect URL for the provider.

json
// Request
{
  "provider": "google",
  "redirect_url": "https://yourapp.com/auth/callback"
}

// Response 200
{ "authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?..." }
POST/auth/oauth/callback

Handle OAuth callback. Exchange authorization code for tokens.

POST/auth/oauth/link

Link an OAuth provider to an existing authenticated account.

DELETE/auth/oauth/unlink/{provider}

Unlink an OAuth provider from the current account.

KYC API

Base path: /api/v1/kyc

Sessions

A KYC session represents a single identity verification attempt. Create a session, upload documents, run face matching and liveness checks, then complete.

POST/kyc/sessions

Create a new KYC verification session.

json
// Request
{
  "user_id": "usr_abc123",             // optional, link to existing user
  "type": "full_kyc",                  // "full_kyc" | "document_only" | "face_only"
  "checks": ["document", "face", "liveness"],
  "metadata": { "source": "onboarding" }
}

// Response 201
{
  "id": "kyc_sess_abc123",
  "status": "pending",
  "checks": ["document", "face", "liveness"],
  "created_at": "2026-03-07T10:00:00Z",
  "expires_at": "2026-03-07T11:00:00Z"
}
GET/kyc/sessions/{session_id}

Get session details including document status and verification results.

GET/kyc/sessions/{session_id}/status

Quick status check for polling. Returns just the status and scores.

GET/kyc/sessions

List all KYC sessions with optional filters (status, user_id, date range). Paginated.

POST/kyc/sessions/{session_id}/complete

Finalize the session and trigger scoring. Returns the overall verification result.

DELETE/kyc/sessions/{session_id}

Delete a KYC session and all associated data.

Document Upload

Upload identity documents (passport, driver's license, national ID) for OCR extraction. Supports JPEG, PNG, and PDF. Max 10MB. File content is validated via magic-byte detection.

POST/kyc/sessions/{session_id}/documents

Upload an identity document image. Uses multipart/form-data.

bash
curl -X POST https://api.zauthy.com/v1/kyc/sessions/{session_id}/documents \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@passport.jpg" \
  -F "document_type=passport" \
  -F "country=US"

# Response 200
{
  "document_id": "doc_abc123",
  "status": "processed",
  "document_type": "passport",
  "extracted_data": {
    "full_name": "Jane Doe",
    "date_of_birth": "1990-01-15",
    "document_number": "AB1234567",
    "expiry_date": "2030-01-15",
    "country": "US"
  },
  "confidence": 0.97
}

Face Verification

POST/kyc/sessions/{session_id}/face/match

Compare a selfie with the face on the uploaded document. Upload as multipart/form-data.

json
// Response 200
{
  "match": true,
  "confidence": 0.94,
  "threshold": 0.80
}

Liveness Detection

POST/kyc/sessions/{session_id}/face/liveness

Verify the selfie is a live person (not a photo of a photo, mask, or screen). Upload as multipart/form-data.

json
// Response 200
{
  "is_live": true,
  "confidence": 0.98,
  "checks": {
    "texture_analysis": true,
    "depth_estimation": true,
    "blink_detection": true
  }
}

Location Verification

POST/kyc/sessions/{session_id}/location

Submit GPS coordinates for location-based verification (e.g., country matching with document).

json
// Request
{
  "latitude": 37.7749,
  "longitude": -122.4194,
  "accuracy": 10.0
}

Webhooks

Receive real-time notifications when events occur in your Zauthy account. Webhooks are HMAC-signed and retried automatically on failure.

POST/webhooks

Create a new webhook subscription.

json
// Request
{
  "url": "https://yourapp.com/webhooks/zauthy",
  "events": ["user.signup", "kyc.completed", "kyc.failed"],
  "active": true
}

// Response 201
{
  "id": "wh_abc123",
  "url": "https://yourapp.com/webhooks/zauthy",
  "secret": "whsec_...",  // for signature verification
  "events": ["user.signup", "kyc.completed", "kyc.failed"],
  "active": true
}
GET/webhooks

List all webhook subscriptions.

PATCH/webhooks/{webhook_id}

Update a webhook (URL, events, active status).

DELETE/webhooks/{webhook_id}

Delete a webhook subscription.

POST/webhooks/{webhook_id}/test

Send a test webhook event to verify your endpoint.

POST/webhooks/{webhook_id}/rotate-secret

Rotate the webhook signing secret.

GET/webhooks/{webhook_id}/deliveries

View delivery history and retry status.

Webhook Events

EventDescription
user.signupNew user registered
user.loginUser logged in
user.blockedUser account blocked
user.deletedUser account deleted
kyc.session.createdKYC session started
kyc.completedKYC verification completed (passed)
kyc.failedKYC verification failed
mfa.enabledUser enabled MFA
security.suspicious_loginSuspicious login detected

Signature Verification

Every webhook includes an X-Webhook-Signature header. Always verify this to ensure the payload is authentic.

typescript
import crypto from 'crypto';

function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler
app.post('/webhooks/zauthy', (req, res) => {
  const isValid = verifyWebhook(
    JSON.stringify(req.body),
    req.headers['x-webhook-signature'] as string,
    process.env.ZAUTHY_WEBHOOK_SECRET!
  );

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  // Process the event
  const { event, data } = req.body;
  console.log(`Received ${event}`, data);

  res.status(200).send('ok');
});

SDKs

JavaScript / TypeScript

bash
npm install @zauthy/sdk
typescript
import { Zauthy } from '@zauthy/sdk';

const zauthy = new Zauthy({ apiKey: process.env.ZAUTHY_SECRET_KEY });

// Auth
const { user, access_token } = await zauthy.auth.signup({
  email: 'user@example.com',
  password: 'SecureP@ss123'
});

// KYC
const session = await zauthy.kyc.createSession({
  userId: user.id,
  checks: ['document', 'face', 'liveness']
});

// Webhooks
const webhook = await zauthy.webhooks.create({
  url: 'https://yourapp.com/webhooks',
  events: ['kyc.completed']
});

Python

bash
pip install zauthy
python
from zauthy import Zauthy

client = Zauthy(api_key="sk_live_...")

# Auth
user = client.auth.signup(
    email="user@example.com",
    password="SecureP@ss123"
)

# KYC
session = client.kyc.create_session(
    user_id=user["id"],
    checks=["document", "face", "liveness"]
)

# Upload document
result = client.kyc.upload_document(
    session_id=session["id"],
    file_path="./passport.jpg",
    document_type="passport"
)

Flutter / Dart

yaml
# pubspec.yaml
dependencies:
  vault_kyc_sdk: ^1.0.0
dart
import 'package:vault_kyc_sdk/vault_kyc_sdk.dart';

// Initialize
final zauthy = VaultKYC();
await zauthy.initialize(
  apiKey: 'sk_live_...',
  baseUrl: 'https://api.zauthy.com/v1',
);

// Auth
final result = await zauthy.auth.signup(
  email: 'user@example.com',
  password: 'SecureP@ss123',
);

// KYC with camera capture
final session = await zauthy.kyc.startVerification(
  checks: [KYCCheck.document, KYCCheck.face, KYCCheck.liveness],
);

Security API

Base path: /api/v1/security

Device Tracking

GET/security/users/{user_id}/devices

List known devices for a user. Includes device fingerprint, OS, browser, and trust status.

PUT/security/users/{user_id}/devices/{device_id}/trust

Mark a device as trusted or untrusted.

DELETE/security/users/{user_id}/devices/{device_id}

Remove a device from the known list.

Risk Assessment

POST/security/login/assess

Assess login risk before authenticating. Returns risk score and recommended actions.

json
// Request
{
  "email": "user@example.com",
  "ip": "203.0.113.42",
  "device_fingerprint": "fp_...",
  "user_agent": "Mozilla/5.0..."
}

// Response 200
{
  "risk_score": 0.15,       // 0.0 (safe) to 1.0 (high risk)
  "risk_level": "low",      // "low" | "medium" | "high"
  "flags": [],              // ["new_device", "impossible_travel", "tor_exit_node"]
  "recommendation": "allow" // "allow" | "mfa" | "block"
}
GET/security/users/{user_id}/suspicious-activities

Get suspicious activity log for a user.

GET/security/users/{user_id}/security-summary

Security dashboard: devices, sessions, risk events, MFA status.

IP Intelligence

POST/security/check-ip

Check IP reputation (VPN, proxy, Tor, data center detection).

json
// Request
{ "ip": "203.0.113.42" }

// Response 200
{
  "ip": "203.0.113.42",
  "is_vpn": false,
  "is_proxy": false,
  "is_tor": false,
  "is_datacenter": false,
  "country": "US",
  "city": "San Francisco",
  "risk_score": 0.05
}
GET/security/geolocate

Geolocate the requesting IP address. Returns country, city, coordinates.

Need help integrating?

Our team is here to help you get up and running.