REST API Reference
Complete reference for all ezAuth API endpoints. All endpoints are prefixed with /v1 unless noted.
Authentication
Endpoints use one of two auth modes:
- Publishable — send
X-Publishable-Key: pk_...header. For frontend/user-facing operations. - Secret — send
Authorization: Bearer sk_...header. For backend/admin operations.
User-scoped endpoints (with publishable key) also require Authorization: Bearer <access_token>.
Authentication Endpoints
POST /v1/challenges
Request a hashcash proof-of-work challenge (required before signup when HASHCASH_ENABLED=true).
Response
{
"challenge": "random-hex-string",
"difficulty": 5,
"algorithm": "argon2id",
"params": {
"time_cost": 2,
"memory_cost": 19456,
"parallelism": 1,
"hash_len": 32
},
"expires_in": 300
}
POST /v1/signups
Register a new user. Sends a verification email.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User's email address |
password | string | No | Password (if app has passwords enabled) |
redirect_url | string | No | URL to redirect after email verification |
hashcash | object | Conditional | Required when hashcash is enabled: { challenge, nonce } |
Response 200
{ "status": "verification_sent", "user_id": "uuid" }
POST /v1/signins
Sign in a user. Strategy determines the flow.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User's email address |
password | string | No | Required for strategy: "password" |
strategy | string | No | "magic_link" (default) or "password" |
redirect_url | string | No | URL to redirect after magic link verification |
Response (magic_link) 200
{ "status": "verification_sent" }
Response (password) 200
{
"access_token": "eyJhbG...",
"refresh_token": "rt_...",
"user_id": "uuid",
"session_id": "uuid"
}
POST /v1/verify-code
Verify a 6-digit code sent to the user's email.
Request Body
| Field | Type | Required |
|---|---|---|
email | string | Yes |
code | string | Yes |
Response 200
{
"access_token": "eyJhbG...",
"refresh_token": "rt_...",
"user_id": "uuid",
"session_id": "uuid"
}
GET /v1/email/verify
Verify an email via magic link token. Sets __session cookie and redirects to redirect_url.
GET /v1/me
Get the currently authenticated user. Reads from __session cookie or Authorization: Bearer <jwt>.
Response 200
{
"user_id": "uuid",
"email": "[email protected]",
"email_verified": true,
"is_bot": false
}
POST /v1/tokens/session
Refresh an expired access token.
Request Body
{ "refresh_token": "rt_..." }
Response 200
{
"access_token": "eyJhbG...",
"refresh_token": "new_rt_...",
"user_id": "uuid",
"session_id": "uuid"
}
POST /v1/sessions/logout
Sign out the current session. Revokes the session and clears the cookie.
Response 200
{ "status": "logged_out" }
OAuth Endpoints
GET /v1/oauth/{provider}/authorize
Get the OAuth authorization URL. Supported providers: google, apple.
Response 200
{ "authorization_url": "https://accounts.google.com/..." }
GET /v1/oauth/{provider}/callback
OAuth redirect callback. Handles code exchange, token verification, user upsert, and redirect. Used by Google.
POST /v1/oauth/{provider}/callback
OAuth callback for the form_post response mode. Used by Apple.
GET /v1/oauth/providers
List configured OAuth providers (secrets redacted).
PUT /v1/oauth/providers/{provider}
Configure an OAuth provider. Supported providers: google, apple.
DELETE /v1/oauth/providers/{provider}
Remove an OAuth provider configuration.
SSO Endpoints
GET /v1/sso/bridge
Generate a one-time SSO token and redirect to the target domain. Token expires in 60 seconds.
POST /v1/sso/exchange
Exchange a one-time SSO token for a session. Both apps must belong to the same tenant.
Request Body
{ "token": "sso_token_string" }
Bot Endpoints
POST /v1/bot/signup
Register a bot with a confirmed donation challenge and Ed25519 public key.
Request Body
| Field | Type | Description |
|---|---|---|
challenge_id | string | Confirmed challenge ID from confirmations.info |
public_key | string | Base64-encoded Ed25519 public key |
POST /v1/bot/auth
Authenticate a bot by verifying an Ed25519 signature.
Request Body
| Field | Type | Description |
|---|---|---|
bot_id | string | The bot's user ID |
timestamp | integer | Current Unix timestamp (seconds) |
signature | string | Base64-encoded Ed25519 signature of ezauth:bot_auth:{app_id}:{bot_id}:{timestamp} |
User Management
GET /v1/users
List users for this application.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit | int | 50 | Max results per page |
offset | int | 0 | Pagination offset |
email | string | — | Filter by email (case-insensitive) |
Response 200
{
"users": [
{
"id": "uuid",
"email": "[email protected]",
"email_verified": true,
"is_bot": false,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}
],
"total": 1
}
POST /v1/users
Create a user server-side (skips email verification).
Request Body
| Field | Type | Required |
|---|---|---|
email | string | Yes |
password | string | No |
GET /v1/users/{user_id}
Get a specific user by ID.
Session Management
POST /v1/sessions/revoke
Revoke a session by its ID.
POST /v1/sign_in_tokens
Create a short-lived sign-in token for server-to-server auth.
Request Body
| Field | Type | Default | Description |
|---|---|---|---|
user_id | string | — | User ID to create token for |
expires_in_seconds | int | 300 | Token lifetime in seconds, capped at MAX_SIGNIN_TOKEN_LIFETIME_SECONDS |
Response 200
{
"token": "eyJhbG...",
"refresh_token": "rt_...",
"user_id": "uuid",
"session_id": "uuid",
"expires_at": "2025-01-01T00:05:00Z"
}
Custom Tables
POST /v1/tables
Create a new custom table with optional column definitions.
Request Body
{
"name": "contacts",
"columns": [
{ "name": "name", "type": "text", "required": true },
{ "name": "age", "type": "int" }
]
}
GET /v1/tables
List all tables for this application.
GET /v1/tables/{table_id}
Get a table with its column definitions.
DELETE /v1/tables/{table_id}
Delete a table and all its columns and rows.
POST /v1/tables/{table_id}/columns
Add a column to a table.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Column name |
type | string | Yes | Column type: text, int, bool, float, date, json |
required | bool | No | Whether the column is required (default: false) |
default_value | any | No | Default value for the column |
position | int | No | Column position/order |
PATCH /v1/tables/{table_id}/columns/{column_id}
Update a column's properties.
DELETE /v1/tables/{table_id}/columns/{column_id}
POST /v1/tables/{table_id}/rows
Insert a row.
Request Body
{
"data": { "name": "Alice", "age": 30 },
"user_id": "optional-uuid" // for user-scoped rows
}
GET /v1/tables/{table_id}/rows/{row_id}
PATCH /v1/tables/{table_id}/rows/{row_id}
Partial update of a row's data.
DELETE /v1/tables/{table_id}/rows/{row_id}
POST /v1/tables/{table_id}/rows/query
Query rows with filtering, sorting, and pagination.
Request Body
{
"filter": { "field": "age", "op": "gte", "value": 18 },
"sort": { "field": "name", "dir": "asc" },
"limit": 50,
"cursor": null
}
GET /v1/tables/storage
Get table storage usage for this application.
Response 200
{ "used_bytes": 1048576, "limit_bytes": 104857600, "used_percent": 1.0 }
Object Storage
POST /v1/buckets
Create a storage bucket.
Request Body
{ "name": "avatars" }
GET /v1/buckets
List all buckets.
GET /v1/buckets/{bucket_id}
PATCH /v1/buckets/{bucket_id}
Update a bucket's size limits. Send either field on its own; omit a field to leave it unchanged, or send null to remove the limit.
Request Body
| Field | Type | Description |
|---|---|---|
max_size_bytes | int | null | Total size cap for the bucket |
max_size_bytes_per_user | int | null | Per-user size cap within the bucket |
DELETE /v1/buckets/{bucket_id}
PUT /v1/buckets/{bucket_id}/objects/{key}
Upload an object. Send raw bytes with the appropriate Content-Type header.
GET /v1/buckets/{bucket_id}/objects/{key}
Download an object. Returns raw bytes with the stored content type.
DELETE /v1/buckets/{bucket_id}/objects/{key}
GET /v1/buckets/{bucket_id}/objects
List objects in a bucket.
GET /v1/buckets/storage
Get object storage usage for this application.
Public Endpoints
GET /.well-known/jwks.json
Returns the JSON Web Key Set for verifying JWTs. Resolves the application from the app_id query parameter or from the Host header (via domain lookup).
Response 200
{
"keys": [
{
"kty": "RSA",
"kid": "key-id",
"use": "sig",
"alg": "RS256",
"n": "...",
"e": "AQAB"
}
]
}
Billing
These tenant-scoped routes require an application's secret key and remain available while paused. See Billing for request and response examples.
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/billing | Balance, pause status, usage, and available payment methods. |
| POST | /v1/billing/topups | Create a top-up with amount_usd, method, and optional crypto chain. |
| GET | /v1/billing/topups/{payment_id} | Read status; crypto requests also check the provider and apply confirmed credit. |
| GET | /v1/billing/transactions?limit=50 | Newest ledger rows (maximum limit 200). |