Auth1 API Documentation

Everything you need to integrate Auth1 into your application. SMS OTP, Email Magic Links, VOIP detection, risk scoring, and more.

Quick Start

Get up and running with Auth1 in under five minutes. Install the SDK, configure your API key, and send your first verification.

1. Install the SDK

npm install @auth1/sdk
yarn add @auth1/sdk
pnpm add @auth1/sdk

2. Initialize and Verify

app.js
import Auth1 from '@auth1/sdk';

// Initialize with your API key
const auth = new Auth1({
  apiKey: 'auth1_pk_...'
});

// Send a verification to the user
const result = await auth.verify('user@example.com', '+18005551234');

// result includes VOIP detection + risk score
console.log(result.isVoip);     // false
console.log(result.riskScore);  // 0.12
That's it. VOIP detection, fraud scoring, and OTP delivery are all handled automatically with a single call.

Authentication

All API requests require an API key passed in the x-api-key header. You can generate keys from your Auth1 Dashboard.

HTTP Header
x-api-key: auth1_pk_YOUR_API_KEY
Content-Type: application/json

Key Types

PrefixTypeDescription
auth1_pk_ string Production key. Full API access, rate limits applied per your plan.
auth1_sk_ string Secret key. Used for server-side webhook signature verification only. Never expose client-side.
auth1_test_ string Test key. Simulates API responses without sending real SMS/emails. Free and unlimited.
Never expose your auth1_sk_ secret key in client-side code or public repositories. Use environment variables on the server.

SMS OTP

Send a one-time verification code via SMS. Auth1 automatically detects VOIP numbers and calculates a fraud risk score before delivery.

POST https://auth-api.z101.ai/api/auth/sms/request

Headers

HeaderTypeDescription
x-api-key required string Your Auth1 API key
Content-Type required string application/json

Request Body

ParameterTypeDescription
phone required string E.164 format phone number (e.g., +18005551234)
email required string User's email address for identity binding
tenant required string Your tenant identifier

Response 200 OK

FieldTypeDescription
phoneVerificationId string UUID to pass to the verify endpoint
phoneType string Carrier-detected type: mobile, landline, or voip
isVoip boolean true if VOIP number detected
riskScore number Fraud risk score from 0.0 (safe) to 1.0 (high risk)
message string Human-readable status message
provider string Delivery provider used (twilio or sns)
curl -X POST https://auth-api.z101.ai/api/auth/sms/request \
  -H "Content-Type: application/json" \
  -H "x-api-key: auth1_pk_YOUR_KEY" \
  -d '{
    "phone": "+18005551234",
    "email": "user@example.com",
    "tenant": "your-tenant"
  }'
const res = await fetch('https://auth-api.z101.ai/api/auth/sms/request', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'auth1_pk_YOUR_KEY'
  },
  body: JSON.stringify({
    phone: '+18005551234',
    email: 'user@example.com',
    tenant: 'your-tenant'
  })
});

const data = await res.json();
console.log(data.phoneVerificationId); // uuid
console.log(data.isVoip);               // false
console.log(data.riskScore);            // 0.12
import requests

resp = requests.post(
    "https://auth-api.z101.ai/api/auth/sms/request",
    headers={
        "Content-Type": "application/json",
        "x-api-key": "auth1_pk_YOUR_KEY"
    },
    json={
        "phone": "+18005551234",
        "email": "user@example.com",
        "tenant": "your-tenant"
    }
)

data = resp.json()
print(data["phoneVerificationId"])  # uuid
print(data["isVoip"])               # False
print(data["riskScore"])            # 0.12

Example Response

JSON
{
  "phoneVerificationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "phoneType": "mobile",
  "isVoip": false,
  "riskScore": 0.12,
  "message": "Verification code sent",
  "provider": "twilio"
}

Verify Code

Verify the 6-digit OTP code entered by the user. On success, returns a JWT session token and refresh token.

POST https://auth-api.z101.ai/api/auth/sms/verify

Request Body

ParameterTypeDescription
phoneVerificationId required string UUID returned from the SMS OTP request
verificationCode required string 6-digit code entered by the user
email required string Email used in the original SMS request

Response 200 OK

FieldTypeDescription
user object Contains id, phone, and email
token string JWT access token (expires in 1 hour)
refreshToken string Refresh token (expires in 30 days)
curl -X POST https://auth-api.z101.ai/api/auth/sms/verify \
  -H "Content-Type: application/json" \
  -H "x-api-key: auth1_pk_YOUR_KEY" \
  -d '{
    "phoneVerificationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "verificationCode": "123456",
    "email": "user@example.com"
  }'
const res = await fetch('https://auth-api.z101.ai/api/auth/sms/verify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'auth1_pk_YOUR_KEY'
  },
  body: JSON.stringify({
    phoneVerificationId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
    verificationCode: '123456',
    email: 'user@example.com'
  })
});

const { user, token, refreshToken } = await res.json();
resp = requests.post(
    "https://auth-api.z101.ai/api/auth/sms/verify",
    headers={
        "Content-Type": "application/json",
        "x-api-key": "auth1_pk_YOUR_KEY"
    },
    json={
        "phoneVerificationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "verificationCode": "123456",
        "email": "user@example.com"
    }
)

data = resp.json()
token = data["token"]

Example Response

JSON
{
  "user": {
    "id": "usr_abc123",
    "phone": "+18005551234",
    "email": "user@example.com"
  },
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "rt_d4e5f6a7b8c9..."
}

Session Management

After verification, use these endpoints to manage user sessions. All session endpoints require a Bearer token in the Authorization header.

Get Current Session

GET https://auth-api.z101.ai/api/auth/session
HeaderDescription
Authorization required Bearer <token> from the verify response
cURL
curl https://auth-api.z101.ai/api/auth/session \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Refresh Token

POST https://auth-api.z101.ai/api/auth/refresh
ParameterTypeDescription
refreshToken required string The refresh token received from verify or a previous refresh
cURL
curl -X POST https://auth-api.z101.ai/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{ "refreshToken": "rt_d4e5f6a7b8c9..." }'

Logout

POST https://auth-api.z101.ai/api/auth/logout
HeaderDescription
Authorization required Bearer <token> - Invalidates the session server-side
cURL
curl -X POST https://auth-api.z101.ai/api/auth/logout \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Webhooks

Auth1 sends real-time HTTP POST notifications to your configured webhook URL when authentication events occur. Configure webhooks in your Dashboard under Settings.

Events

  • user.created Fired when a new user record is created during their first verification.
  • user.verified Fired when a user successfully completes OTP or magic link verification.
  • login.success Fired on every successful authentication (includes returning users).
  • login.failed Fired when verification fails (wrong code, expired code, max attempts).
  • fraud.detected Fired when a VOIP number is blocked or risk score exceeds your threshold.

Payload Format

JSON
{
  "id": "evt_a1b2c3d4e5f6",
  "event": "user.verified",
  "timestamp": "2026-03-23T14:30:00Z",
  "data": {
    "userId": "usr_abc123",
    "email": "user@example.com",
    "phone": "+18005551234",
    "method": "sms_otp",
    "riskScore": 0.12,
    "isVoip": false,
    "ip": "203.0.113.42"
  }
}

Signature Verification

Every webhook request includes an x-auth1-signature header containing an HMAC-SHA256 signature of the raw request body, signed with your auth1_sk_ secret key. Always verify this signature before processing.

Node.js
import { createHmac } from 'crypto';

function verifyWebhook(body, signature, secret) {
  const expected = createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return expected === signature;
}

// In your Express handler:
app.post('/webhooks/auth1', (req, res) => {
  const sig = req.headers['x-auth1-signature'];
  if (!verifyWebhook(req.rawBody, sig, process.env.AUTH1_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  // Process the event...
  res.sendStatus(200);
});
Your endpoint must return a 2xx status within 10 seconds. Auth1 retries failed deliveries with exponential backoff up to 3 times over 24 hours.

VOIP Detection

Auth1 automatically classifies every phone number before sending an OTP. VOIP numbers (Google Voice, TextNow, Burner, etc.) are flagged in real-time, letting you block or challenge suspicious signups.

How It Works

  • Every SMS request checks the phone number against carrier databases and proprietary heuristics.
  • The phoneType field returns mobile, landline, or voip.
  • The isVoip boolean provides a quick check for conditional logic.
  • By default, VOIP numbers are allowed but flagged. Configure blocking rules in your Dashboard.

Configuration Options

SettingDefaultDescription
voipAction flag flag = allow but mark, block = reject with error, challenge = require additional verification
voipBlockMessage null Custom error message shown when a VOIP number is blocked
allowedVoipProviders [] Whitelist specific VOIP providers (e.g., ["vonage_business"])
VOIP detection is included in all plans at no extra cost. Enterprise customers get access to carrier-level lookup data via the carrierInfo response field.

Risk Scoring

Auth1 assigns a fraud risk score (0.0 to 1.0) to every authentication attempt. The score combines multiple signals in real-time.

Score Breakdown

RangeRisk LevelRecommended Action
0.0 - 0.3 Low Allow through. Legitimate user.
0.3 - 0.6 Medium Allow but monitor. Consider additional verification for sensitive actions.
0.6 - 0.8 High Challenge the user with a secondary factor or manual review.
0.8 - 1.0 Critical Block the attempt. Very likely fraudulent.

Signals Used

  • Phone type -- VOIP, prepaid, and landline numbers increase the score.
  • Velocity -- Multiple attempts from the same IP or phone in a short window.
  • Geolocation mismatch -- IP country vs. phone country code discrepancy.
  • Known fraud patterns -- Number ranges and IPs associated with prior abuse across all Auth1 tenants.
  • Device fingerprint -- Browser/device anomalies when using the client-side SDK.

Custom Branding

Personalize SMS messages, emails, and magic link pages with your company branding. Configure in the Dashboard or via the API.

SMS Templates

Customize the OTP message text. Use the {{code}} placeholder for the verification code and {{appName}} for your tenant's display name.

Example SMS
Your {{appName}} verification code is {{code}}. Expires in 10 minutes.

Email Branding

  • Logo URL -- Displayed in the magic link email header.
  • Primary color -- Applied to buttons and accents in the email template.
  • From name -- The sender name shown in the user's inbox (e.g., "YourApp Security").
  • Reply-to -- Where user replies go.

SDKs

Official client libraries for the most popular platforms. All SDKs include TypeScript definitions and handle retries, error mapping, and token refresh automatically.

Node.js

Server-side SDK for Express, Fastify, Next.js, and any Node runtime.

npm install @auth1/sdk

Python

Works with Django, Flask, FastAPI. Python 3.8+ required.

pip install auth1

React

Drop-in components: <Auth1Provider>, <VerifyForm>, and useAuth1() hook.

npm install @auth1/react

Node.js Example

server.js
import Auth1 from '@auth1/sdk';

const auth = new Auth1({
  apiKey: process.env.AUTH1_API_KEY,
  tenant: 'your-tenant'
});

// Send OTP
const { phoneVerificationId, isVoip, riskScore } =
  await auth.sms.send({
    phone: '+18005551234',
    email: 'user@example.com'
  });

// Verify code
const session = await auth.sms.verify({
  phoneVerificationId,
  code: '123456',
  email: 'user@example.com'
});

console.log(session.token); // JWT access token

Python Example

app.py
from auth1 import Auth1Client

client = Auth1Client(
    api_key="auth1_pk_YOUR_KEY",
    tenant="your-tenant"
)

# Send OTP
result = client.sms.send(
    phone="+18005551234",
    email="user@example.com"
)

print(result.is_voip)      # False
print(result.risk_score)   # 0.12

# Verify code
session = client.sms.verify(
    phone_verification_id=result.phone_verification_id,
    code="123456",
    email="user@example.com"
)

React Example

App.jsx
import { Auth1Provider, VerifyForm, useAuth1 } from '@auth1/react';

function App() {
  return (
    <Auth1Provider apiKey="auth1_pk_...">
      <VerifyForm
        onSuccess={(session) => console.log('Verified!', session)}
        onVoipDetected={() => alert('VOIP numbers not allowed')}
      />
    </Auth1Provider>
  );
}

// Or use the hook directly:
function CustomLogin() {
  const { sendOTP, verifyCode, loading, session } = useAuth1();
  // Build your own UI...
}

Error Codes

All errors return a JSON body with error (machine-readable code) and message (human-readable description). HTTP status codes follow REST conventions.

Error Response Format
{
  "error": "CODE_EXPIRED",
  "message": "Verification code has expired. Please request a new one.",
  "statusCode": 400
}
CodeHTTPDescription
VALIDATION_APIKEY_NOTFOUND 401 The x-api-key header is missing or the key does not exist.
VALIDATION_APIKEY_INACTIVE 403 API key has been deactivated. Reactivate in your Dashboard.
VOIP_NOT_ALLOWED 403 The phone number was identified as VOIP and your policy is set to block.
INVALID_PHONE 400 Phone number is not in valid E.164 format.
INVALID_EMAIL 400 Email address is malformed or empty.
CODE_EXPIRED 400 Verification code has expired (10-minute TTL). Request a new one.
CODE_INVALID 400 Verification code does not match.
TOO_MANY_ATTEMPTS 429 Maximum verification attempts exceeded for this code. Request a new one.
SMS_DELIVERY_FAILED 502 SMS could not be delivered by either provider (Twilio + SNS). Phone may be invalid or unreachable.
RATE_LIMIT_EXCEEDED 429 You have exceeded the per-minute or per-hour rate limit. See Rate Limits.
TOKEN_EXPIRED 401 JWT access token has expired. Use the refresh token to obtain a new one.
TOKEN_INVALID 401 JWT is malformed or signature verification failed.
INTERNAL_ERROR 500 An unexpected server error occurred. Contact support if persistent.

Rate Limits

Auth1 enforces rate limits to protect service quality and prevent abuse. Limits vary by endpoint and plan.

SMS per phone number 5 / hour
API calls per key 100 / minute
Verification attempts per code 5 attempts
Magic link emails per address 3 / hour

Rate Limit Headers

Every response includes rate limit headers so you can proactively manage your usage:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets

429 Response

When a rate limit is exceeded, you receive a 429 Too Many Requests response:

JSON
{
  "error": "RATE_LIMIT_EXCEEDED",
  "message": "Too many requests. Please retry after 42 seconds.",
  "retryAfter": 42,
  "statusCode": 429
}
Enterprise plans include configurable rate limits. Contact sales for custom limits.