API Reference

339 endpoints · v1.0.0
Authentication — All endpoints require Authorization: Bearer <api_key_or_jwt>. Scopes control access: read, write, schema, files, auth, ai, * (all).
Standard response format — All endpoints return: { "success": true|false, "data": ..., "request_id": "..." }. Errors include: { "success": false, "error": { "code": "...", "message": "..." }, "request_id": "..." }.
Secure deletion (409 Dependency Exists) — DELETE endpoints that manage parent records return 409 Conflict when dependent records exist, instead of silently cascade-deleting. The response includes a DEPENDENCY_EXISTS error with dependency counts and a one-time confirm_token:
{ "success": false, "error": { "code": "DEPENDENCY_EXISTS", "message": "Cannot delete: dependent records exist", "dependencies": [{ "type": "objects", "count": 12, "label": "Objects" }], "confirm_token": "abc123..." } }
To force cascade-delete, retry the request with ?force=true&confirm_token=<token>. Tokens are single-use and expire after 5 minutes.
Rate limits & constraints — Batch operations: max 100 items. File upload: max 25MB direct (use presigned URL for larger). Import: max 10,000 rows. Export: max 100,000 records. Search: max 100 results. File search: max 200 results. MFA attempts: 5 failures → 15 min lockout. Signed URL TTL: 60s–86,400s. Image transform: max 4096px. SQL: max 10,000 chars. Password max length: 1024 chars.

Public7

Health checks, docs, and landing pages. No authentication required.

GET /docs API documentation UI +

Returns the interactive HTML API documentation.

Try it
GET /health Health check +

Returns service status, version, deployment region, and timestamp.

Response
{
  "success": true,
  "data": {
    "status": "...",
    "service": "...",
    "version": "...",
    "timestamp": "...",
    "region": "...",
    "uptime": "..."
  },
  "request_id": "..."
}
Try it
GET / Landing page +

Returns the HTML landing page for the API.

Try it
GET /docs/openapi.json OpenAPI specification +

Returns this OpenAPI 3.1 JSON specification.

Response
{}
Try it
GET /ready Readiness probe +

Lightweight probe for load balancer health checks.

Response
{
  "success": true,
  "data": {
    "status": "ready",
    "service": "...",
    "timestamp": "..."
  },
  "request_id": "..."
}
Try it
GET /v1/tenant-config Get tenant config (public) +

Returns public-facing tenant configuration (branding, auth config). No auth required but tenant must be identifiable.

Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/tenants/lookup Lookup tenants by email +

Find tenants associated with an email address.

Request
{
  "email": "..."
}
Response
{
  "success": true,
  "data": [
    {
      "tenant_id": "...",
      "brand_name": "..."
    }
  ],
  "request_id": "..."
}
Try it

Billing1

Stripe billing integration and webhooks.

POST /webhooks/stripe Stripe webhook +

Receives Stripe webhook events. Verified using Stripe-Signature header. Handles checkout.session.completed, customer.subscription.updated, customer.subscription.deleted.

Try it

Tenants1

Multi-tenant provisioning, configuration, migration, quota management, and suspension.

GET /v1/usage Get tenant usage Bearer +

Get tenant usage

Response
{
  "success": true,
  "data": {
    "tenant_id": "...",
    "plan_tier": {},
    "used_storage_bytes": 0,
    "plan_limits": {}
  },
  "request_id": "..."
}
Try it

API Keys5

API key lifecycle management — create, revoke, rotate, and update.

GET /v1/keys List API keys Bearer +

List API keys

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/keys Create API key Bearer +

Create API key

Request
{
  "label": "...",
  "scopes": [
    {}
  ],
  "ip_allowlist": [
    "..."
  ],
  "expires_at": null,
  "rate_limit": null
}
Response 201
{
  "success": true,
  "data": {
    "key": {},
    "token": "..."
  },
  "request_id": "..."
}
Try it
PATCH /v1/keys/:key_id Update API key Bearer +

Update API key

Parameters
NameInTypeDescription
key_id*pathstring
Request
{
  "label": "...",
  "scopes": [
    {}
  ],
  "ip_allowlist": [
    "..."
  ],
  "rate_limit": null
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/keys/:key_id Revoke API key Bearer +

Revoke API key

Parameters
NameInTypeDescription
key_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/keys/:key_id/rotate Rotate API key Bearer +

Rotate API key

Parameters
NameInTypeDescription
key_id*pathstring
Request
{
  "label": "...",
  "scopes": [
    {}
  ]
}
Response
{
  "success": true,
  "data": {
    "old_key": {},
    "new_key": {},
    "token": "..."
  },
  "request_id": "..."
}
Try it

Users6

Admin management of tenant auth users.

GET /v1/users List users Bearer +

List users

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
searchquerystring
rolequerystring
Response
{
  "success": true,
  "data": {
    "users": [
      null
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/users Create user Bearer +

Create user

Request
{
  "email": "...",
  "password": "...",
  "phone": "...",
  "role": "...",
  "email_verified": true,
  "user_metadata": {}
}
Response 201
{
  "success": true,
  "data": null,
  "request_id": "..."
}
Try it
GET /v1/users/:user_id Get user Bearer +

Get user

Parameters
NameInTypeDescription
user_id*pathstring
Response
{
  "success": true,
  "data": null,
  "request_id": "..."
}
Try it
PATCH /v1/users/:user_id Update user Bearer +

Update user

Parameters
NameInTypeDescription
user_id*pathstring
Request
{
  "email": "...",
  "phone": "...",
  "role": "...",
  "banned": true,
  "ban_reason": "...",
  "email_verified": true,
  "user_metadata": {}
}
Response
{
  "success": true,
  "data": null,
  "request_id": "..."
}
Try it
DELETE /v1/users/:user_id Delete user Bearer +

Delete user

Parameters
NameInTypeDescription
user_id*pathstring
forcequeryboolean
confirm_tokenquerystring
Response
{
  "success": true,
  "data": {
    "user_id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Errors
  • 409 — Dependency exists — dependent records must be removed first
Try it
GET /v1/users/:user_id/mfa List user MFA factors Bearer +

List user MFA factors

Parameters
NameInTypeDescription
user_id*pathstring
Response
{
  "success": true,
  "data": [
    null
  ],
  "request_id": "..."
}
Try it

Auth Config2

Tenant authentication configuration — providers, password policy, branding, templates.

GET /v1/auth-config Get auth config Bearer +

Get auth config

Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/auth-config Update auth config Bearer +

Update auth config

Request
{}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Webhooks7

Webhook endpoint management — create, test, replay, and configure event subscriptions.

GET /v1/webhooks List webhooks Bearer +

List webhooks

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/webhooks Create webhook Bearer +

Create webhook

Request
{
  "url": "...",
  "events": [
    "..."
  ],
  "object_types": [
    "..."
  ],
  "status": {}
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/webhooks/:webhook_id Update webhook Bearer +

Update webhook

Parameters
NameInTypeDescription
webhook_id*pathstring
Request
{
  "url": "...",
  "events": [
    "..."
  ],
  "status": {}
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/webhooks/:webhook_id Delete webhook Bearer +

Delete webhook

Parameters
NameInTypeDescription
webhook_id*pathstring
forcequeryboolean
confirm_tokenquerystring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "..."
}
Errors
  • 409 — Dependency exists — dependent records must be removed first
Try it
POST /v1/webhooks/:webhook_id/replay Replay webhook Bearer +

Replay webhook

Parameters
NameInTypeDescription
webhook_id*pathstring
Request
{
  "event": "...",
  "payload": {}
}
Response
{
  "success": true,
  "data": {
    "status_code": 0
  },
  "request_id": "..."
}
Try it
POST /v1/webhooks/:webhook_id/rotate-secret Rotate webhook secret Bearer +

Rotate webhook secret

Parameters
NameInTypeDescription
webhook_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/webhooks/:webhook_id/test Test webhook Bearer +

Test webhook

Parameters
NameInTypeDescription
webhook_id*pathstring
Response
{
  "success": true,
  "data": {
    "status_code": 0
  },
  "request_id": "..."
}
Try it

Webhook Deliveries2

Webhook delivery logs and retry.

GET /v1/webhook-deliveries List webhook deliveries Bearer +

List webhook deliveries

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "deliveries": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/webhook-deliveries/:delivery_id/retry Retry webhook delivery Bearer +

Retry webhook delivery

Parameters
NameInTypeDescription
delivery_id*pathstring
Response
{
  "success": true,
  "data": {
    "retried": true
  },
  "request_id": "..."
}
Try it

Policies4

Row-level security policy management for object types.

GET /v1/object-types/:object_type_id/policies List access policies Bearer +

List access policies

Parameters
NameInTypeDescription
object_type_id*pathstring
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/object-types/:object_type_id/policies Create access policy Bearer +

Create access policy

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "name": "...",
  "action": "select",
  "role": null,
  "condition_json": {},
  "enabled": true
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/object-types/:object_type_id/policies/:policy_id Update access policy Bearer +

Update access policy

Parameters
NameInTypeDescription
object_type_id*pathstring
policy_id*pathstring
Request
{
  "name": "...",
  "action": "...",
  "role": null,
  "condition_json": {},
  "enabled": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/object-types/:object_type_id/policies/:policy_id Delete access policy Bearer +

Delete access policy

Parameters
NameInTypeDescription
object_type_id*pathstring
policy_id*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "..."
}
Try it

Analytics2

Tenant and global analytics dashboards.

GET /v1/analytics Get tenant analytics Bearer +

Get tenant analytics

Parameters
NameInTypeDescription
periodquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/analytics/engine Analytics engine query Bearer +

Analytics engine query

Parameters
NameInTypeDescription
periodquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Audit1

Tenant audit log queries.

GET /v1/audit-logs List audit logs Bearer +

List audit logs

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
actionquerystring
resource_typequerystring
Response
{
  "success": true,
  "data": {
    "logs": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it

SQL1

Direct SQL query execution against tenant D1 shards.

POST /v1/sql Execute SQL query Bearer +

Execute SQL query

Request
{
  "sql": "...",
  "params": [
    null
  ]
}
Response
{
  "success": true,
  "data": {
    "columns": [
      "..."
    ],
    "rows": [
      {}
    ],
    "row_count": 0,
    "duration_ms": 0
  },
  "request_id": "..."
}
Try it

DLQ3

Dead-letter queue message management.

DELETE /v1/dlq/:msg_id Discard DLQ message Bearer +

Discard DLQ message

Parameters
NameInTypeDescription
msg_id*pathstring
Response
{
  "success": true,
  "data": {
    "discarded": true
  },
  "request_id": "..."
}
Try it
GET /v1/dlq List DLQ messages Bearer +

List DLQ messages

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "messages": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/dlq/:msg_id/retry Retry DLQ message Bearer +

Retry DLQ message

Parameters
NameInTypeDescription
msg_id*pathstring
Response
{
  "success": true,
  "data": {
    "retried": true
  },
  "request_id": "..."
}
Try it

Realtime2

WebSocket connection and channel statistics.

GET /v1/realtime/stats Get realtime stats Bearer +

Get realtime stats

Response
{
  "success": true,
  "data": {
    "total_connections": 0,
    "channels": {},
    "channel_count": 0
  },
  "request_id": "..."
}
Try it
GET /v1/realtime WebSocket upgrade +

Upgrades to a WebSocket connection for real-time event subscriptions. Uses Durable Objects with WebSocket Hibernation. Channels: objects:<type_id>, files, files:<folder>.

Parameters
NameInTypeDescription
token*querystring
tenant_id*querystring
Errors
  • 101 — WebSocket upgrade
  • 426 — Not a WebSocket upgrade request
Try it

Forms8

Public form builder management.

GET /v1/forms List forms Bearer +

List forms

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/forms Create form Bearer +

Create form

Request
{
  "name": "...",
  "object_type_id": "...",
  "fields": [
    {}
  ],
  "settings": {}
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/forms/:form_id Update form Bearer +

Update form

Parameters
NameInTypeDescription
form_id*pathstring
Request
{
  "name": "...",
  "fields": [
    {}
  ],
  "settings": {},
  "status": "active"
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/forms/:form_id Delete form Bearer +

Delete form

Parameters
NameInTypeDescription
form_id*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "..."
}
Try it
POST /v1/forms/:form_id/duplicate Duplicate form Bearer +

Duplicate form

Parameters
NameInTypeDescription
form_id*pathstring
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/forms/:form_id/submissions/export Export form submissions Bearer +

Export form submissions

Parameters
NameInTypeDescription
form_id*pathstring
formatquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/forms/:form_id/analytics Get form analytics Bearer +

Get form analytics

Parameters
NameInTypeDescription
form_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/forms/:form_id/submissions List form submissions Bearer +

List form submissions

Parameters
NameInTypeDescription
form_id*pathstring
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "submissions": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it

Automations7

Event-driven automation rule management.

GET /v1/automations List automations Bearer +

List automations

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/automations Create automation Bearer +

Create automation

Request
{
  "name": "...",
  "trigger_event": "...",
  "conditions": [
    {}
  ],
  "actions": [
    {}
  ],
  "enabled": true
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/automations/:automation_id Get automation Bearer +

Get automation

Parameters
NameInTypeDescription
automation_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/automations/:automation_id Update automation Bearer +

Update automation

Parameters
NameInTypeDescription
automation_id*pathstring
Request
{
  "name": "...",
  "trigger_event": "...",
  "conditions": [
    {}
  ],
  "actions": [
    {}
  ],
  "enabled": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/automations/:automation_id Delete automation Bearer +

Delete automation

Parameters
NameInTypeDescription
automation_id*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/automations/:automation_id/runs List automation runs Bearer +

List automation runs

Parameters
NameInTypeDescription
automation_id*pathstring
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "runs": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/automations/:automation_id/trigger Trigger automation Bearer +

Trigger automation

Parameters
NameInTypeDescription
automation_id*pathstring
Request
{
  "data": {}
}
Response
{
  "success": true,
  "data": {
    "run_id": "..."
  },
  "request_id": "..."
}
Try it

Roles9

Role-based access control — create roles, assign permissions, manage user-role assignments.

PUT /v1/roles/:role_id/permissions Assign permissions to role Bearer +

Assign permissions to role

Parameters
NameInTypeDescription
role_id*pathstring
Request
{
  "permissions": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/roles/assign Assign role to user Bearer +

Assign role to user

Request
{
  "user_id": "...",
  "role_id": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/roles List roles Bearer +

List roles

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/roles Create role Bearer +

Create role

Request
{
  "name": "...",
  "description": "...",
  "parent_role_id": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/roles/:role_id Get role Bearer +

Get role

Parameters
NameInTypeDescription
role_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/roles/:role_id Update role Bearer +

Update role

Parameters
NameInTypeDescription
role_id*pathstring
Request
{
  "name": "...",
  "description": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/roles/:role_id Delete role Bearer +

Delete role

Parameters
NameInTypeDescription
role_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/users/:user_id/roles List user roles Bearer +

List user roles

Parameters
NameInTypeDescription
user_id*pathstring
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
DELETE /v1/roles/:role_id/users/:user_id Remove role from user Bearer +

Remove role from user

Parameters
NameInTypeDescription
role_id*pathstring
user_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Governance3

Tenant governance settings — security policies, session rules, password requirements, IP allowlists.

GET /v1/governance Get governance settings Bearer +

Get governance settings

Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/governance Update governance settings Bearer +

Update governance settings

Request
{
  "audit_retention_days": 0,
  "session_duration_secs": 0,
  "password_min_length": 0,
  "ip_allowlist": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/policies/simulate Simulate RLS policy Bearer +

Simulate RLS policy

Request
{
  "policy": {},
  "auth_context": {},
  "sample_data": [
    {}
  ]
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Dashboards9

Custom dashboard management with configurable widgets.

GET /v1/dashboards/public/:share_token Get public dashboard +

Access a publicly shared dashboard. No authentication required.

Parameters
NameInTypeDescription
share_token*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/dashboards/:dashboard_id/widgets Add widget to dashboard Bearer +

Add widget to dashboard

Parameters
NameInTypeDescription
dashboard_id*pathstring
Request
{
  "type": "...",
  "title": "...",
  "config_json": {},
  "position_json": {}
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/dashboards List dashboards Bearer +

List dashboards

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/dashboards Create dashboard Bearer +

Create dashboard

Request
{
  "name": "...",
  "description": "...",
  "layout_json": {},
  "is_public": true
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/dashboards/:dashboard_id Get dashboard Bearer +

Get dashboard

Parameters
NameInTypeDescription
dashboard_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/dashboards/:dashboard_id Update dashboard Bearer +

Update dashboard

Parameters
NameInTypeDescription
dashboard_id*pathstring
Request
{
  "name": "...",
  "description": "...",
  "layout_json": {},
  "is_public": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/dashboards/:dashboard_id Delete dashboard Bearer +

Delete dashboard

Parameters
NameInTypeDescription
dashboard_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
PATCH /v1/dashboards/:dashboard_id/widgets/:widget_id Update widget Bearer +

Update widget

Parameters
NameInTypeDescription
dashboard_id*pathstring
widget_id*pathstring
Request
{
  "type": "...",
  "title": "...",
  "config_json": {},
  "position_json": {}
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/dashboards/:dashboard_id/widgets/:widget_id Delete widget Bearer +

Delete widget

Parameters
NameInTypeDescription
dashboard_id*pathstring
widget_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it

Scheduled Jobs6

Scheduled job management — cron-based or one-time execution tasks.

GET /v1/scheduled-jobs List scheduled jobs Bearer +

List scheduled jobs

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/scheduled-jobs Create scheduled job Bearer +

Create scheduled job

Request
{
  "name": "...",
  "description": "...",
  "cron_expression": "...",
  "run_at": "...",
  "action_type": "...",
  "action_config": {},
  "enabled": true
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/scheduled-jobs/:job_id Get scheduled job Bearer +

Get scheduled job

Parameters
NameInTypeDescription
job_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/scheduled-jobs/:job_id Update scheduled job Bearer +

Update scheduled job

Parameters
NameInTypeDescription
job_id*pathstring
Request
{
  "name": "...",
  "description": "...",
  "cron_expression": "...",
  "action_type": "...",
  "action_config": {},
  "enabled": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/scheduled-jobs/:job_id Delete scheduled job Bearer +

Delete scheduled job

Parameters
NameInTypeDescription
job_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
POST /v1/scheduled-jobs/:job_id/execute Execute scheduled job Bearer +

Execute scheduled job

Parameters
NameInTypeDescription
job_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Saved Reports7

Saved report definitions with scheduling and export capabilities.

GET /v1/saved-reports List saved reports Bearer +

List saved reports

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/saved-reports Create saved report Bearer +

Create saved report

Request
{
  "name": "...",
  "description": "...",
  "type": "...",
  "config_json": {},
  "schedule": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/saved-reports/:report_id Get saved report Bearer +

Get saved report

Parameters
NameInTypeDescription
report_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/saved-reports/:report_id Update saved report Bearer +

Update saved report

Parameters
NameInTypeDescription
report_id*pathstring
Request
{
  "name": "...",
  "description": "...",
  "config_json": {},
  "schedule": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/saved-reports/:report_id Delete saved report Bearer +

Delete saved report

Parameters
NameInTypeDescription
report_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/saved-reports/:report_id/export Export saved report Bearer +

Export saved report

Parameters
NameInTypeDescription
report_id*pathstring
formatquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/saved-reports/:report_id/run Run saved report Bearer +

Run saved report

Parameters
NameInTypeDescription
report_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Integrations7

Third-party integration management with sync capabilities.

GET /v1/integrations List integrations Bearer +

List integrations

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/integrations Create integration Bearer +

Create integration

Request
{
  "provider": "...",
  "name": "...",
  "config_json": {},
  "sync_direction": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/integrations/:integration_id Get integration Bearer +

Get integration

Parameters
NameInTypeDescription
integration_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/integrations/:integration_id Update integration Bearer +

Update integration

Parameters
NameInTypeDescription
integration_id*pathstring
Request
{
  "name": "...",
  "config_json": {},
  "status": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/integrations/:integration_id Delete integration Bearer +

Delete integration

Parameters
NameInTypeDescription
integration_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/integrations/:integration_id/logs List sync logs Bearer +

List sync logs

Parameters
NameInTypeDescription
integration_id*pathstring
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/integrations/:integration_id/sync Sync integration Bearer +

Sync integration

Parameters
NameInTypeDescription
integration_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Plugins12

Plugin and custom function management — install, configure, execute.

GET /v1/functions List custom functions Bearer +

List custom functions

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/functions Create custom function Bearer +

Create custom function

Request
{
  "name": "...",
  "description": "...",
  "trigger_type": "...",
  "code": "...",
  "runtime": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/functions/:function_id Get function Bearer +

Get function

Parameters
NameInTypeDescription
function_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/functions/:function_id Update function Bearer +

Update function

Parameters
NameInTypeDescription
function_id*pathstring
Request
{
  "name": "...",
  "code": "...",
  "enabled": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/functions/:function_id Delete function Bearer +

Delete function

Parameters
NameInTypeDescription
function_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
POST /v1/functions/:function_id/execute Execute function Bearer +

Execute function

Parameters
NameInTypeDescription
function_id*pathstring
Request
{
  "input": {}
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/plugins/:plugin_id Get plugin Bearer +

Get plugin

Parameters
NameInTypeDescription
plugin_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/plugins/:plugin_id Update plugin Bearer +

Update plugin

Parameters
NameInTypeDescription
plugin_id*pathstring
Request
{
  "name": "...",
  "config_json": {},
  "enabled": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/plugins/:plugin_id Uninstall plugin Bearer +

Uninstall plugin

Parameters
NameInTypeDescription
plugin_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/plugins List plugins Bearer +

List plugins

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/plugins Install plugin Bearer +

Install plugin

Request
{
  "name": "...",
  "version": "...",
  "manifest_json": {},
  "config_json": {},
  "enabled": true
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/functions/:function_id/logs List function logs Bearer +

List function logs

Parameters
NameInTypeDescription
function_id*pathstring
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it

Branding2

Tenant branding customization — logos, colors, domain, CSS.

GET /v1/branding Get branding settings Bearer +

Get branding settings

Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/branding Update branding Bearer +

Update branding

Request
{
  "custom_domain": "...",
  "logo_url": "...",
  "favicon_url": "...",
  "primary_color": "...",
  "brand_name": "...",
  "footer_text": "...",
  "custom_css": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

AI Providers6

AI provider configuration and usage monitoring.

GET /v1/ai-providers List AI providers Bearer +

List AI providers

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/ai-providers Create AI provider Bearer +

Create AI provider

Request
{
  "name": "...",
  "provider_type": "...",
  "api_key": "...",
  "config_json": {}
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/ai-providers/:provider_id Get AI provider Bearer +

Get AI provider

Parameters
NameInTypeDescription
provider_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/ai-providers/:provider_id Update AI provider Bearer +

Update AI provider

Parameters
NameInTypeDescription
provider_id*pathstring
Request
{
  "name": "...",
  "api_key": "...",
  "config_json": {}
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/ai-providers/:provider_id Delete AI provider Bearer +

Delete AI provider

Parameters
NameInTypeDescription
provider_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/ai-usage Get AI usage stats Bearer +

Get AI usage stats

Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Object Types5

Define your data schema. Object types are like database tables.

GET /v1/object-types List object types Bearer +

List all object types for the authenticated tenant.

Response
{
  "success": true,
  "data": [
    {
      "id": "ot_abc123",
      "tenant_id": "tn_xyz789",
      "name": "contacts",
      "display_name": "Contacts",
      "created_at": "2026-01-01T00:00:00Z",
      "updated_at": "2026-01-15T12:00:00Z"
    }
  ],
  "request_id": "req_abc123"
}
Try it
POST /v1/object-types Create object type schemaBearer +

Create a new object type (schema). Requires "schema" scope.

Request
{
  "name": "contacts"
}
Response 201
{
  "success": true,
  "data": {
    "id": "ot_abc123",
    "tenant_id": "tn_xyz789",
    "name": "contacts",
    "display_name": "Contacts",
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-15T12:00:00Z"
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/object-types/:object_type_id Get object type Bearer +

Get a single object type by ID.

Parameters
NameInTypeDescription
object_type_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "ot_abc123",
    "tenant_id": "tn_xyz789",
    "name": "contacts",
    "display_name": "Contacts",
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-15T12:00:00Z"
  },
  "request_id": "req_abc123"
}
Try it
PATCH /v1/object-types/:object_type_id Update object type schemaBearer +

Rename an object type. Requires "schema" scope.

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "name": "customers"
}
Response
{
  "success": true,
  "data": {
    "id": "ot_abc123",
    "tenant_id": "tn_xyz789",
    "name": "contacts",
    "display_name": "Contacts",
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-15T12:00:00Z"
  },
  "request_id": "req_abc123"
}
Try it
DELETE /v1/object-types/:object_type_id Delete object type Bearer +

Permanently deletes the object type, all its properties, objects, and associated data. This is destructive and cannot be undone.

Parameters
NameInTypeDescription
object_type_id*pathstring
forcequerystring
confirm_tokenquerystring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "req_abc123"
}
Try it

Properties4

Typed fields on object types — 22 data types with indexing and validation.

GET /v1/object-types/:object_type_id/properties List properties Bearer +

List all properties defined on an object type.

Parameters
NameInTypeDescription
object_type_id*pathstring
Response
{
  "success": true,
  "data": [
    {
      "id": "prop_abc123",
      "object_type_id": "ot_abc123",
      "name": "email",
      "data_type": "email",
      "is_indexed": false,
      "is_sortable": false,
      "is_unique": false,
      "is_required": false,
      "enum_values": null,
      "description": "Contact email address",
      "created_at": "2026-01-01T00:00:00Z"
    }
  ],
  "request_id": "req_abc123"
}
Try it
POST /v1/object-types/:object_type_id/properties Create property schemaBearer +

Add a typed field to an object type. Requires "schema" scope.

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "name": "email",
  "data_type": "string",
  "is_indexed": false,
  "is_sortable": false,
  "is_unique": false,
  "is_required": false,
  "default_value": null,
  "enum_values": [
    "..."
  ],
  "description": "..."
}
Response 201
{
  "success": true,
  "data": {
    "id": "prop_abc123",
    "object_type_id": "ot_abc123",
    "name": "email",
    "data_type": "email",
    "is_indexed": false,
    "is_sortable": false,
    "is_unique": false,
    "is_required": false,
    "default_value": null,
    "enum_values": null,
    "description": "Contact email address",
    "created_at": "2026-01-01T00:00:00Z"
  },
  "request_id": "req_abc123"
}
Try it
PATCH /v1/object-types/:object_type_id/properties/:property_id Update property Bearer +

Update property settings. Name and data_type cannot be changed.

Parameters
NameInTypeDescription
object_type_id*pathstring
property_id*pathstring
Request
{
  "is_indexed": true,
  "is_sortable": true,
  "is_unique": true,
  "is_required": true,
  "default_value": null,
  "description": "..."
}
Response
{
  "success": true,
  "data": {
    "id": "prop_abc123",
    "object_type_id": "ot_abc123",
    "name": "email",
    "data_type": "email",
    "is_indexed": false,
    "is_sortable": false,
    "is_unique": false,
    "is_required": false,
    "default_value": null,
    "enum_values": null,
    "description": "Contact email address",
    "created_at": "2026-01-01T00:00:00Z"
  },
  "request_id": "req_abc123"
}
Try it
DELETE /v1/object-types/:object_type_id/properties/:property_id Delete property Bearer +

Delete a property from an object type. Existing values become untyped.

Parameters
NameInTypeDescription
object_type_id*pathstring
property_id*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "req_abc123"
}
Try it

Objects10

CRUD on data records with versioning, batch operations, and soft-delete/restore.

POST /v1/objects/:object_type_id/batch/create Batch create objects writeBearer +

Create up to 100 objects in a single request. Requires "write" scope.

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "objects": [
    {
      "properties": {
        "name": "Acme Corp",
        "email": "info@acme.com"
      }
    }
  ]
}
Response 201
{
  "success": true,
  "data": {
    "created": 0,
    "ids": [
      "..."
    ]
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/objects/:object_type_id Create object writeBearer +

Create a new object of the given type. Requires "write" scope.

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "properties": {
    "name": "Acme Corp",
    "email": "info@acme.com"
  }
}
Response 201
{
  "success": true,
  "data": {
    "id": "obj_abc123",
    "object_type_id": "ot_abc123",
    "tenant_id": "tn_xyz789",
    "properties": {
      "name": "Acme Corp",
      "email": "info@acme.com"
    },
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-15T12:00:00Z",
    "created_by": "usr_abc123",
    "version": 1,
    "is_deleted": false
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/objects/:object_type_id/:object_id Get object Bearer +

Retrieve a single object by type and ID.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "obj_abc123",
    "object_type_id": "ot_abc123",
    "tenant_id": "tn_xyz789",
    "properties": {
      "name": "Acme Corp",
      "email": "info@acme.com"
    },
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-15T12:00:00Z",
    "created_by": "usr_abc123",
    "version": 1,
    "is_deleted": false
  },
  "request_id": "req_abc123"
}
Try it
PATCH /v1/objects/:object_type_id/:object_id Update object writeBearer +

Update properties on an existing object. Requires "write" scope.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
Request
{
  "properties": {
    "name": "Updated Name"
  }
}
Response
{
  "success": true,
  "data": {
    "id": "obj_abc123",
    "object_type_id": "ot_abc123",
    "tenant_id": "tn_xyz789",
    "properties": {
      "name": "Acme Corp",
      "email": "info@acme.com"
    },
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-15T12:00:00Z",
    "created_by": "usr_abc123",
    "version": 1,
    "is_deleted": false
  },
  "request_id": "req_abc123"
}
Try it
DELETE /v1/objects/:object_type_id/:object_id Delete object Bearer +

Soft-delete an object (moves to trash). Use force=true for permanent deletion.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
forcequerystring
confirm_tokenquerystring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/objects/:object_type_id/list List objects Bearer +

List objects of a given type with pagination, filtering, and sorting.

Parameters
NameInTypeDescription
object_type_id*pathstring
limitqueryinteger Default: 20
cursorquerystring
sortquerystring
orderquerystring
Response
{
  "success": true,
  "data": {
    "results": [
      {
        "id": "...",
        "object_type_id": "...",
        "tenant_id": "...",
        "properties": "...",
        "created_at": "...",
        "updated_at": "...",
        "created_by": "...",
        "version": "...",
        "is_deleted": "..."
      }
    ],
    "next_cursor": "eyJpZCI6...",
    "total": 42
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/objects/:object_type_id/batch/read Batch read objects Bearer +

Retrieve multiple objects by ID in a single request. Max 100 IDs.

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "object_ids": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/objects/:object_type_id/batch/update Batch update objects Bearer +

Update multiple objects in a single request. Max 100 items.

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "updates": [
    {
      "object_id": "...",
      "properties": {}
    }
  ]
}
Response
{
  "success": true,
  "data": [
    {
      "object_id": "...",
      "version": 0
    }
  ],
  "request_id": "..."
}
Try it
GET /v1/objects/:object_type_id/trash List trashed objects Bearer +

List soft-deleted objects that can be restored.

Parameters
NameInTypeDescription
object_type_id*pathstring
limitqueryinteger
cursorquerystring
Response
{
  "success": true,
  "data": {
    "results": [
      {}
    ],
    "next_cursor": null,
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/objects/:object_type_id/:object_id/restore Restore deleted object Bearer +

Restore a soft-deleted object from trash.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Views4

Saved filter/sort/column presets for object types.

GET /v1/object-types/:object_type_id/views List saved views Bearer +

List saved views (filter presets) for an object type.

Parameters
NameInTypeDescription
object_type_id*pathstring
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/object-types/:object_type_id/views Create saved view Bearer +

Create a saved view with filters, sort, and column configuration.

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "name": "...",
  "filters": [
    {}
  ],
  "sort": {},
  "columns": [
    "..."
  ]
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/object-types/:object_type_id/views/:view_id Update saved view Bearer +

Update an existing saved view.

Parameters
NameInTypeDescription
object_type_id*pathstring
view_id*pathstring
Request
{
  "name": "...",
  "filters": [
    {}
  ],
  "sort": {},
  "columns": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/object-types/:object_type_id/views/:view_id Delete saved view Bearer +

Delete a saved view.

Parameters
NameInTypeDescription
object_type_id*pathstring
view_id*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "..."
}
Try it

Associations3

Typed relationships between objects across types.

PUT /v1/objects/:from_type/:from_id/associations/:association_type/:to_type/:to_id Create or update association Bearer +

Create or replace an association between two objects. Optionally include a meta object (max 10KB).

Parameters
NameInTypeDescription
from_type*pathstring
from_id*pathstring
association_type*pathstring
to_type*pathstring
to_id*pathstring
Request
{
  "meta": {}
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/objects/:from_type/:from_id/associations/:association_type/:to_type/:to_id Delete association Bearer +

Remove an association between two objects.

Parameters
NameInTypeDescription
from_type*pathstring
from_id*pathstring
association_type*pathstring
to_type*pathstring
to_id*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/objects/:type/:id/associations List associations Bearer +

List associations for an object, optionally filtering by type and direction.

Parameters
NameInTypeDescription
type*pathstring
id*pathstring
directionquerystring
association_typequerystring
limitqueryinteger
cursorquerystring
Response
{
  "success": true,
  "data": {
    "results": [
      {}
    ],
    "next_cursor": null,
    "total": 0
  },
  "request_id": "..."
}
Try it

Files20

File storage on Cloudflare R2 with variants, signed URLs, versioning, and batch ops.

POST /v1/files/batch/delete Batch delete files Bearer +

Delete multiple files in a single request. Max 100.

Request
{
  "file_ids": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": {
    "deleted": [
      "..."
    ],
    "count": 0
  },
  "request_id": "..."
}
Try it
POST /v1/files/batch/read Batch read file metadata Bearer +

Retrieve metadata for multiple files by ID. Max 100.

Request
{
  "file_ids": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/files/batch/update Batch update file metadata Bearer +

Update access or folder for multiple files. Max 100.

Request
{
  "file_ids": [
    "..."
  ],
  "access": {},
  "folder": "..."
}
Response
{
  "success": true,
  "data": {
    "updated": 0
  },
  "request_id": "..."
}
Try it
POST /v1/files/:file_id/upload-complete Confirm presigned upload Bearer +

Marks a presigned upload as complete. Status changes from "pending" to "ready".

Parameters
NameInTypeDescription
file_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/files/:file_id/signed-url Generate signed URL Bearer +

Creates a time-limited, HMAC-signed URL for accessing private files without authentication.

Parameters
NameInTypeDescription
file_id*pathstring
Request
{
  "expires_in": 0
}
Response
{
  "success": true,
  "data": {
    "url": "...",
    "expires_at": "...",
    "ttl": 0
  },
  "request_id": "..."
}
Try it
GET /v1/files/:file_id Get file metadata Bearer +

Get metadata for a single file.

Parameters
NameInTypeDescription
file_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/files/:file_id Update file metadata Bearer +

Update filename, access level, folder, meta, or linked object. Triggers file.updated webhook.

Parameters
NameInTypeDescription
file_id*pathstring
Request
{
  "filename": "...",
  "access": {},
  "folder": "...",
  "meta": {},
  "object_type_id": null,
  "object_id": null
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/files/:file_id Delete file Bearer +

Soft-delete a file. R2 object is cleaned up asynchronously. Triggers file.deleted webhook.

Parameters
NameInTypeDescription
file_id*pathstring
Response
{
  "success": true,
  "data": {
    "file_id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/files/:file_id/content Download file content Bearer +

Returns raw binary content. Also accessible via signed URLs without Bearer auth when token/expires/t query params are present.

Parameters
NameInTypeDescription
file_id*pathstring
tokenquerystring
expiresquerynumber
tquerystring
Try it
GET /v1/files/:file_id/variants/:variant Get image variant Bearer +

On-the-fly image transformation. Only for image files. Results are cached.

Parameters
NameInTypeDescription
file_id*pathstring
variant*pathstring
wqueryinteger
hqueryinteger
fitquerystring
formatquerystring
Try it
GET /v1/files/stats Storage statistics Bearer +

Get file storage usage and quota information.

Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/files/upload-url Get presigned upload URL Bearer +

Returns a presigned URL for direct client-side upload to R2, bypassing the Worker size limit.

Request
{
  "filename": "...",
  "mime_type": "...",
  "size_bytes": 0,
  "access": {},
  "folder": "...",
  "meta": {}
}
Response 201
{
  "success": true,
  "data": {
    "file_id": "...",
    "r2_key": "...",
    "upload_endpoint": "...",
    "expires_at": "..."
  },
  "request_id": "..."
}
Try it
GET /v1/files/trash List trashed files Bearer +

List soft-deleted files that can be restored.

Parameters
NameInTypeDescription
limitqueryinteger
cursorquerystring
Response
{
  "success": true,
  "data": {
    "results": [
      {}
    ],
    "next_cursor": null,
    "total": 0
  },
  "request_id": "..."
}
Try it
GET /v1/files/:file_id/versions List file versions Bearer +

Get the version history for a file.

Parameters
NameInTypeDescription
file_id*pathstring
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
GET /v1/files/folders List folders Bearer +

List all file folders with counts and sizes.

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/files/:file_id/restore Restore deleted file Bearer +

Restore a soft-deleted file from trash.

Parameters
NameInTypeDescription
file_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/files/search Search files Bearer +

Filter files by MIME type, access level, folder, filename, date range, and linked objects.

Request
{
  "mime_type": "...",
  "mime_category": "...",
  "access": {},
  "status": {},
  "folder": "...",
  "filename": "...",
  "object_type_id": "...",
  "object_id": "...",
  "created_after": "...",
  "created_before": "...",
  "sort": "size_bytes",
  "sort_dir": {},
  "limit": 0,
  "cursor": null
}
Response
{
  "success": true,
  "data": {
    "results": [
      {}
    ],
    "next_cursor": null,
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/files/:file_id/stale-cleanup Clean stale uploads Bearer +

Remove pending files older than 24 hours that were never completed.

Parameters
NameInTypeDescription
file_id*pathstring
Response
{
  "success": true,
  "data": {
    "cleaned": 0
  },
  "request_id": "..."
}
Try it
POST /v1/files/upload Upload file Bearer +

Direct multipart upload. Max 25MB per file. For larger files, use the presigned URL flow.

Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/files/:file_id/upload-put Upload file content to presigned slot Bearer +

Upload raw file content for a presigned upload slot.

Parameters
NameInTypeDescription
file_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Events4

Custom event tracking for analytics and automation.

GET /events/stream Server-sent events stream Bearer +

Real-time SSE stream of object and file events.

Try it
GET /events/types List available event types Bearer +

List available event types

Response
{
  "success": true,
  "data": [
    "..."
  ],
  "request_id": "..."
}
Try it
POST /v1/events Track custom event Bearer +

Track a custom event for analytics and automation triggers.

Request
{
  "event_type": "...",
  "data": {}
}
Response
{
  "success": true,
  "data": {
    "tracked": true
  },
  "request_id": "..."
}
Try it
GET /v1/events/list List custom events Bearer +

List custom events

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "events": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it

Errors1

Client-side error reporting.

POST /v1/errors/report Report client error Bearer +

Report a client-side error for tracking and alerting.

Request
{
  "message": "...",
  "stack": "...",
  "source": "...",
  "level": "error",
  "path": "...",
  "metadata": {}
}
Response
{
  "success": true,
  "data": {
    "error_id": "..."
  },
  "request_id": "..."
}
Try it

Versions1

Object version history.

GET /v1/objects/:object_type_id/:object_id/versions List object version history Bearer +

Returns all previous versions of an object, newest first.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
limitqueryinteger
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it

Import / Export3

Bulk data import (CSV/JSON) and async export.

GET /v1/data/export/:export_id Download export Bearer +

Download the exported data file.

Parameters
NameInTypeDescription
export_id*pathstring
Response
"..."
Try it
POST /v1/data/import Import data Bearer +

Bulk import up to 10,000 rows from CSV, JSON file, or inline JSON body.

Request
{
  "object_type_id": "...",
  "format": "json",
  "data": [
    {}
  ]
}
Response
{
  "success": true,
  "data": {
    "imported": 0,
    "errors": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/data/export Start data export Bearer +

Initiate an async export of all objects of a type. Max 100,000 records.

Request
{
  "object_type_id": "...",
  "format": "json"
}
Response
{
  "success": true,
  "data": {
    "export_id": "...",
    "format": "...",
    "record_count": 0,
    "download_path": "..."
  },
  "request_id": "..."
}
Try it

Comments4

Activity feed comments on objects.

GET /v1/objects/:object_type_id/:object_id/comments List comments Bearer +

List comments on an object, newest first.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
limitqueryinteger
cursorquerystring
Response
{
  "success": true,
  "data": {
    "results": [
      {}
    ],
    "next_cursor": null,
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/objects/:object_type_id/:object_id/comments Create comment Bearer +

Add a comment to an object (activity feed). Requires authenticated user.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
Request
{
  "body": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/objects/:object_type_id/:object_id/comments/:comment_id Update comment Bearer +

Edit a comment. Only the author can edit their own comments.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
comment_id*pathstring
Request
{
  "body": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/objects/:object_type_id/:object_id/comments/:comment_id Delete comment Bearer +

Delete a comment. Only the author can delete their own comments.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
comment_id*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "..."
}
Try it

Workflows8

Object approval workflow operations — submit, approve, reject.

POST /v1/objects/:object_type_id/:object_id/approve Approve object Bearer +

Approve an object in the current workflow stage.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
Request
{
  "comment": "..."
}
Response
{
  "success": true,
  "data": {
    "approved": true,
    "stage": "..."
  },
  "request_id": "..."
}
Try it
GET /v1/objects/:object_type_id/:object_id/workflow-status Get workflow status Bearer +

Get the current approval workflow status for an object.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
Response
{
  "success": true,
  "data": {
    "status": "...",
    "stage": "...",
    "history": [
      {}
    ]
  },
  "request_id": "..."
}
Try it
POST /v1/objects/:object_type_id/:object_id/reject Reject object Bearer +

Reject an object in the current workflow stage.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
Request
{
  "reason": "..."
}
Response
{
  "success": true,
  "data": {
    "rejected": true,
    "stage": "..."
  },
  "request_id": "..."
}
Try it
POST /v1/objects/:object_type_id/:object_id/submit-for-review Submit for review Bearer +

Submit an object for approval workflow review.

Parameters
NameInTypeDescription
object_type_id*pathstring
object_id*pathstring
Response
{
  "success": true,
  "data": {
    "submitted": true,
    "stage": "..."
  },
  "request_id": "..."
}
Try it
GET /v1/object-types/:object_type_id/workflows List workflows Bearer +

List workflows

Parameters
NameInTypeDescription
object_type_id*pathstring
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/object-types/:object_type_id/workflows Create workflow Bearer +

Create workflow

Parameters
NameInTypeDescription
object_type_id*pathstring
Request
{
  "name": "...",
  "stages": [
    {}
  ],
  "enabled": true
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/object-types/:object_type_id/workflows/:workflow_id Update workflow Bearer +

Update workflow

Parameters
NameInTypeDescription
object_type_id*pathstring
workflow_id*pathstring
Request
{
  "name": "...",
  "stages": [
    {}
  ],
  "enabled": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/object-types/:object_type_id/workflows/:workflow_id Delete workflow Bearer +

Delete workflow

Parameters
NameInTypeDescription
object_type_id*pathstring
workflow_id*pathstring
forcequeryboolean
confirm_tokenquerystring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "..."
}
Errors
  • 409 — Dependency exists — dependent records must be removed first
Try it

Reports4

Pipeline, time series, leaderboard, and funnel reports.

POST /v1/reports/funnel Funnel report Bearer +

Generate a multi-step funnel conversion report.

Request
{
  "object_type_id": "...",
  "steps": [
    {
      "name": "...",
      "filters": [
        "..."
      ]
    }
  ]
}
Response
{
  "success": true,
  "data": {
    "steps": [
      {}
    ]
  },
  "request_id": "..."
}
Try it
POST /v1/reports/leaderboard Leaderboard report Bearer +

Generate a ranked leaderboard by a property value.

Request
{
  "object_type_id": "...",
  "group_by": "...",
  "aggregation": "count",
  "value_property": "...",
  "limit": 0,
  "filters": [
    {}
  ]
}
Response
{
  "success": true,
  "data": {
    "entries": [
      {}
    ]
  },
  "request_id": "..."
}
Try it
POST /v1/reports/pipeline Pipeline report Bearer +

Generate a pipeline/funnel stage breakdown report.

Request
{
  "object_type_id": "...",
  "stage_property": "...",
  "filters": [
    {}
  ]
}
Response
{
  "success": true,
  "data": {
    "stages": [
      {}
    ]
  },
  "request_id": "..."
}
Try it
POST /v1/reports/timeseries Time series report Bearer +

Generate a time series report with configurable intervals.

Request
{
  "object_type_id": "...",
  "date_property": "...",
  "interval": "hour",
  "aggregation": "count",
  "value_property": "...",
  "filters": [
    {}
  ],
  "start_date": "...",
  "end_date": "..."
}
Response
{
  "success": true,
  "data": {
    "series": [
      {}
    ]
  },
  "request_id": "..."
}
Try it

Email1

Transactional email sending through configured providers.

POST /v1/email/send Send email Bearer +

Send a transactional email using the tenant's configured email provider.

Request
{
  "to": "...",
  "subject": "...",
  "html": "...",
  "text": "...",
  "from": "...",
  "reply_to": "..."
}
Response
{
  "success": true,
  "data": {
    "sent": true,
    "message_id": "..."
  },
  "request_id": "..."
}
Try it

AI16

Cloudflare Workers AI — chat, generation, embeddings, vector search, moderation, image description.

POST /v1/ai/auto-tag Auto-tag content Bearer +

Automatically generate tags for an object based on its properties.

Request
{
  "object_type_id": "...",
  "object_id": "..."
}
Response
{
  "success": true,
  "data": {
    "tags": [
      "..."
    ]
  },
  "request_id": "..."
}
Try it
POST /v1/ai/chat Chat completion Bearer +

Generate a chat response with optional conversation history. Max 20 history messages, 50KB combined.

Request
{
  "message": "...",
  "history": [
    {
      "role": "user",
      "content": "..."
    }
  ],
  "model": "..."
}
Response
{
  "success": true,
  "data": {
    "response": "...",
    "model": "..."
  },
  "request_id": "..."
}
Try it
POST /v1/ai/conversations/:conversation_id/chat Chat with conversation history Bearer +

Chat with conversation history

Parameters
NameInTypeDescription
conversation_id*pathstring
Request
{
  "message": "...",
  "model": "..."
}
Response
{
  "success": true,
  "data": {
    "response": "...",
    "model": "..."
  },
  "request_id": "..."
}
Try it
POST /v1/ai/describe Describe image Bearer +

Generate a text description of an image file stored in R2. Supports JPEG, PNG, WebP, GIF (max 10MB).

Request
{
  "file_id": "...",
  "model": "..."
}
Response
{
  "success": true,
  "data": {
    "description": "...",
    "filename": "...",
    "model": "..."
  },
  "request_id": "..."
}
Try it
POST /v1/ai/generate Text generation Bearer +

Generate text from a prompt.

Request
{
  "prompt": "...",
  "model": "...",
  "max_tokens": 0
}
Response
{
  "success": true,
  "data": {
    "text": "...",
    "model": "..."
  },
  "request_id": "..."
}
Try it
POST /v1/ai/index Index objects for vector search Bearer +

Generate embeddings for objects and insert them into the Vectorize index. Max 100 per request.

Request
{
  "object_type_id": "...",
  "object_ids": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": {
    "indexed": 0,
    "model": "...",
    "object_type_id": "..."
  },
  "request_id": "..."
}
Try it
POST /v1/ai/moderate Content moderation Bearer +

Classify text content for policy violations.

Request
{
  "text": "..."
}
Response
{
  "success": true,
  "data": {
    "results": [
      {}
    ],
    "model": "..."
  },
  "request_id": "..."
}
Try it
POST /v1/ai/summarise Summarise content Bearer +

Generate a summary of an object's text content.

Request
{
  "object_type_id": "...",
  "object_id": "...",
  "max_length": 0
}
Response
{
  "success": true,
  "data": {
    "summary": "..."
  },
  "request_id": "..."
}
Try it
POST /v1/ai/search Vector similarity search Bearer +

Search the Vectorize index for objects semantically similar to the query.

Request
{
  "query": "...",
  "limit": 0,
  "object_type_id": "..."
}
Response
{
  "success": true,
  "data": {
    "results": [
      {}
    ],
    "model": "...",
    "dimensions": 0
  },
  "request_id": "..."
}
Try it
GET /v1/ai/conversations List AI conversations Bearer +

List AI conversations

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/ai/conversations Create AI conversation Bearer +

Create AI conversation

Request
{
  "title": "...",
  "model": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/ai/conversations/:conversation_id Get AI conversation Bearer +

Get AI conversation

Parameters
NameInTypeDescription
conversation_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/ai/conversations/:conversation_id Update AI conversation Bearer +

Update AI conversation

Parameters
NameInTypeDescription
conversation_id*pathstring
Request
{
  "title": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/ai/conversations/:conversation_id Delete AI conversation Bearer +

Delete AI conversation

Parameters
NameInTypeDescription
conversation_id*pathstring
Response
{
  "success": true,
  "data": {
    "conversation_id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
POST /v1/ai/embeddings Generate embeddings Bearer +

Generate vector embeddings for one or more text inputs. Max 100 texts.

Request
{
  "text": null,
  "model": "..."
}
Response
{
  "success": true,
  "data": {
    "embeddings": [
      [
        0
      ]
    ],
    "model": "...",
    "dimensions": 0
  },
  "request_id": "..."
}
Try it
GET /v1/ai/models List available AI models Bearer +

List available Cloudflare Workers AI models grouped by capability.

Response
{
  "success": true,
  "data": {
    "text_generation": [
      "..."
    ],
    "text_embedding": [
      "..."
    ],
    "image_to_text": [
      "..."
    ],
    "text_classification": [
      "..."
    ]
  },
  "request_id": "..."
}
Try it

Authentication18

End-user auth: email/password, magic links, OAuth, phone OTP, anonymous sessions.

POST /v1/auth/anonymous Create anonymous session Bearer +

Create an anonymous user with a session. Can be linked to a real account later.

Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/me/export Export user data Bearer +

Export all data associated with the authenticated user (GDPR-style). Rate-limited to once per hour.

Response
{
  "success": true,
  "data": {
    "_meta": {
      "user_id": "...",
      "tenant_id": "...",
      "export_type": "user_data_export",
      "exported_at": "..."
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/forgot-password Request password reset Bearer +

Send a password reset email. Always returns 200 for security (anti-enumeration).

Request
{
  "email": "user@example.com",
  "redirect_to": "...",
  "turnstile_token": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/user Get current user Bearer +

Returns the currently authenticated user profile.

Response
{
  "success": true,
  "data": {
    "id": "usr_abc123",
    "email": "user@example.com",
    "phone": "+15551234567",
    "role": "authenticated",
    "email_verified": true,
    "phone_verified": false,
    "user_metadata": {
      "name": "Jane Doe"
    },
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-15T12:00:00Z",
    "last_sign_in_at": "2026-03-20T10:00:00Z"
  },
  "request_id": "req_abc123"
}
Try it
PATCH /v1/auth/user Update current user Bearer +

Update email, phone, password, or metadata for the authenticated user.

Request
{
  "email": "user@example.com",
  "phone": "...",
  "password": "...",
  "user_metadata": {}
}
Response
{
  "success": true,
  "data": {
    "id": "usr_abc123",
    "email": "user@example.com",
    "phone": "+15551234567",
    "role": "authenticated",
    "email_verified": true,
    "phone_verified": false,
    "user_metadata": {
      "name": "Jane Doe"
    },
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-15T12:00:00Z",
    "last_sign_in_at": "2026-03-20T10:00:00Z"
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/login Log in Bearer +

Authenticate with email and password. Returns session tokens or MFA challenge.

Request
{
  "email": "user@example.com",
  "password": "...",
  "turnstile_token": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/logout Log out Bearer +

Revoke the current refresh token.

Request
{
  "refresh_token": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/oauth/:provider/callback OAuth callback +

Handle OAuth provider callback. Creates or links user account.

Parameters
NameInTypeDescription
provider*pathstring
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Errors
  • 302 — Redirect to app
Try it
GET /v1/auth/oauth/:provider OAuth redirect Bearer +

Redirect to OAuth provider (Google, GitHub, etc.) for authentication.

Parameters
NameInTypeDescription
provider*pathstring
redirect_toquerystring
Errors
  • 302 — Redirect to OAuth provider
Try it
POST /v1/auth/refresh Refresh tokens Bearer +

Exchange a refresh token for new access and refresh tokens.

Request
{
  "refresh_token": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/reset-password Reset password Bearer +

Reset password using token from email. Revokes all refresh tokens.

Request
{
  "token": "...",
  "password": "..."
}
Response
{
  "success": true,
  "data": {
    "password_reset": true
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/magic-link Send magic link Bearer +

Send a passwordless magic-link login email.

Request
{
  "email": "user@example.com",
  "redirect_to": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/otp/send Send SMS OTP Bearer +

Send a one-time password via SMS to an E.164 phone number.

Request
{
  "phone": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/signup Sign up Bearer +

Create a new user account with email and password. Sends verification email.

Request
{
  "email": "user@example.com",
  "password": "...",
  "phone": "...",
  "user_metadata": {},
  "turnstile_token": "..."
}
Response 201
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/verify Verify email (GET) Bearer +

Verify email via link from verification email.

Parameters
NameInTypeDescription
token*querystring
typequerystring
Response
{
  "success": true,
  "data": {
    "verified": true
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/verify Verify email Bearer +

Verify email address with token from signup email.

Request
{
  "token": "...",
  "type": "..."
}
Response
{
  "success": true,
  "data": {
    "verified": true
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/magic-link/verify Verify magic link Bearer +

Exchange magic-link token for an auth session.

Request
{
  "token": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/otp/verify Verify OTP Bearer +

Verify the one-time password and create an auth session.

Request
{
  "phone": "...",
  "code": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it

MFA7

TOTP-based multi-factor authentication enrollment, verification, and recovery.

POST /v1/auth/mfa/challenge Challenge MFA Bearer +

Verify an MFA code during login. Returns user_id and verified status.

Request
{
  "factor_id": "...",
  "code": "...",
  "user_id": "..."
}
Response
{
  "success": true,
  "data": {
    "user_id": "...",
    "verified": true
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/mfa/complete Complete MFA login +

Complete MFA-gated login with a TOTP code and MFA ticket.

Request
{
  "mfa_ticket": "...",
  "factor_id": "...",
  "code": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/mfa/enroll Enroll TOTP factor Bearer +

Begin TOTP MFA enrollment. Returns secret and QR code URI.

Request
{
  "friendly_name": "..."
}
Response 201
{
  "success": true,
  "data": {
    "factor_id": "...",
    "type": "totp",
    "totp": {
      "secret": "...",
      "uri": "...",
      "qr_uri": "..."
    }
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/mfa/factors List MFA factors Bearer +

List all enrolled MFA factors for the current user.

Response
{
  "success": true,
  "data": [
    {
      "id": "mfa_abc123",
      "type": "totp",
      "friendly_name": "Work authenticator",
      "created_at": "2026-01-01T00:00:00Z",
      "verified_at": "2026-01-01T00:05:00Z"
    }
  ],
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/mfa/recover MFA recovery +

Bypass MFA using a recovery code. Consumes the recovery code.

Request
{
  "mfa_ticket": "...",
  "recovery_code": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
DELETE /v1/auth/mfa/:factor_id Unenroll MFA factor Bearer +

Remove an MFA factor from the current user.

Parameters
NameInTypeDescription
factor_id*pathstring
Response
{
  "success": true,
  "data": {
    "unenrolled": true
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/mfa/verify Verify TOTP code Bearer +

Verify a TOTP code to complete MFA factor enrollment.

Request
{
  "factor_id": "...",
  "code": "..."
}
Response
{
  "success": true,
  "data": {
    "verified": true
  },
  "request_id": "req_abc123"
}
Try it

Sessions3

User session listing and revocation.

GET /v1/auth/sessions List active sessions Bearer +

List all active sessions for the authenticated user.

Response
{
  "success": true,
  "data": [
    {
      "id": "sess_abc123",
      "user_id": "usr_abc123",
      "ip": "203.0.113.1",
      "user_agent": "Mozilla/5.0...",
      "created_at": "2026-01-01T00:00:00Z",
      "last_active_at": "2026-03-20T10:00:00Z"
    }
  ],
  "request_id": "req_abc123"
}
Try it
DELETE /v1/auth/sessions Revoke all sessions Bearer +

Revoke all active sessions for the authenticated user.

Response
{
  "success": true,
  "data": {
    "revoked": 0
  },
  "request_id": "req_abc123"
}
Try it
DELETE /v1/auth/sessions/:session_id Revoke session Bearer +

Revoke a specific session by ID.

Parameters
NameInTypeDescription
session_id*pathstring
Response
{
  "success": true,
  "data": {
    "revoked": true
  },
  "request_id": "req_abc123"
}
Try it

Notifications7

In-app notification management.

DELETE /v1/auth/notifications/preferences/:channel Delete notification preference Bearer +

Remove a notification channel preference.

Parameters
NameInTypeDescription
channel*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/notifications/preferences Get notification preferences Bearer +

Get notification channel preferences for the authenticated user.

Response
{
  "success": true,
  "data": [
    {
      "channel": "...",
      "enabled": true,
      "categories": [
        "..."
      ]
    }
  ],
  "request_id": "req_abc123"
}
Try it
PUT /v1/auth/notifications/preferences Update notification preferences Bearer +

Update notification channel preferences.

Request
{
  "channel": "...",
  "enabled": true,
  "categories": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": {
    "updated": true
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/notifications List notifications Bearer +

List notifications for the authenticated user with pagination.

Response
{
  "success": true,
  "data": {
    "results": [
      {
        "id": "...",
        "user_id": "...",
        "type": "...",
        "title": "...",
        "body": "...",
        "is_read": "...",
        "metadata": "...",
        "created_at": "..."
      }
    ],
    "next_cursor": "eyJpZCI6...",
    "total": 42
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/notifications/read-all Mark all as read Bearer +

Mark all notifications as read for the authenticated user.

Response
{
  "success": true,
  "data": {
    "updated": 0
  },
  "request_id": "req_abc123"
}
Try it
PATCH /v1/auth/notifications/:notification_id/read Mark notification read Bearer +

Mark a single notification as read.

Parameters
NameInTypeDescription
notification_id*pathstring
Response
{
  "success": true,
  "data": {
    "read": true
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/notifications/count Get unread count Bearer +

Get the number of unread notifications.

Response
{
  "success": true,
  "data": {
    "count": 0
  },
  "request_id": "req_abc123"
}
Try it

Passkeys6

WebAuthn/FIDO2 passkey registration and authentication.

DELETE /v1/auth/passkeys/:credential_id Delete passkey Bearer +

Remove a registered passkey.

Parameters
NameInTypeDescription
credential_id*pathstring
Response
{
  "success": true,
  "data": {
    "deleted": true
  },
  "request_id": "req_abc123"
}
Try it
GET /v1/auth/passkeys List passkeys Bearer +

List all passkeys registered for the authenticated user.

Response
{
  "success": true,
  "data": [
    {
      "id": "pk_abc123",
      "user_id": "usr_abc123",
      "credential_id": "cred_abc123...",
      "friendly_name": "MacBook Touch ID",
      "created_at": "2026-01-01T00:00:00Z",
      "last_used_at": "2026-03-20T10:00:00Z"
    }
  ],
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/passkeys/authenticate/begin Begin passkey authentication Bearer +

Get WebAuthn credential request options for passkey authentication.

Response
{
  "success": true,
  "data": {
    "options": {}
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/passkeys/authenticate/complete Complete passkey authentication Bearer +

Complete passkey authentication and receive a session.

Request
{
  "credential": {}
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/passkeys/register/begin Begin passkey registration Bearer +

Get WebAuthn credential creation options for passkey registration.

Response
{
  "success": true,
  "data": {
    "options": {}
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/passkeys/register/complete Complete passkey registration Bearer +

Complete passkey registration with the credential from the browser.

Request
{
  "credential": {},
  "friendly_name": "..."
}
Response
{
  "success": true,
  "data": {
    "id": "pk_abc123",
    "user_id": "usr_abc123",
    "credential_id": "cred_abc123...",
    "friendly_name": "MacBook Touch ID",
    "created_at": "2026-01-01T00:00:00Z",
    "last_used_at": "2026-03-20T10:00:00Z"
  },
  "request_id": "req_abc123"
}
Try it

Public Forms2

Public-facing form access and submission (no auth).

GET /v1/forms/:form_id Get public form +

Retrieve a published form definition including fields, settings, and branding.

Parameters
NameInTypeDescription
form_id*pathstring
tenant_id*querystring
Response
{
  "success": true,
  "data": {
    "form_id": "...",
    "name": "...",
    "description": "...",
    "object_type_id": "...",
    "fields": [
      {}
    ],
    "settings": {},
    "branding": {},
    "require_captcha": true
  },
  "request_id": "..."
}
Try it
POST /v1/forms/:form_id/submit Submit public form +

Submit data through a public form. Creates an object in the linked type. Rate-limited.

Parameters
NameInTypeDescription
form_id*pathstring
Request
{}
Response
{
  "success": true,
  "data": {
    "submitted": true,
    "object_id": "..."
  },
  "request_id": "..."
}
Try it

SAML / SSO3

SAML 2.0 single sign-on integration.

POST /v1/auth/saml/:provider/acs SAML ACS +

Assertion Consumer Service endpoint. Receives SAML response from IdP, creates/links user, and redirects with session.

Parameters
NameInTypeDescription
provider*pathstring
Errors
  • 302 — Redirect to app with session tokens
Try it
GET /v1/auth/saml/:provider/login SAML login redirect +

Initiate SAML SSO by redirecting to the IdP.

Parameters
NameInTypeDescription
provider*pathstring
Errors
  • 302 — Redirect to SAML IdP
Try it
GET /v1/auth/saml/:provider/metadata SAML metadata +

Returns SAML SP metadata XML for configuring the IdP.

Parameters
NameInTypeDescription
provider*pathstring
Try it

Short URLs5

URL shortener service via obfy.uk — create, manage, and track short links.

GET /v1/short-urls List short URLs Bearer +

List short URLs

Parameters
NameInTypeDescription
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "results": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/short-urls Create a short URL Bearer +

Create a short URL

Request
{}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Errors
  • 409 — Slug already taken
Try it
GET /v1/short-urls/:slug Get short URL details Bearer +

Get short URL details

Parameters
NameInTypeDescription
slug*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/short-urls/:slug Update a short URL Bearer +

Update a short URL

Parameters
NameInTypeDescription
slug*pathstring
Request
{}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/short-urls/:slug Delete a short URL Bearer +

Delete a short URL

Parameters
NameInTypeDescription
slug*pathstring
Response
{
  "success": true,
  "data": {
    "slug": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it

Accounting68

Double-entry accounting via tenant API: chart of accounts, journal entries, invoices, payments, bank reconciliation, tax codes, financial reports.

GET /v1/accounting/reports/aged-payables Aged payables report Bearer +

Aged payables report

Parameters
NameInTypeDescription
as_ofquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/reports/aged-receivables Aged receivables report Bearer +

Aged receivables report

Parameters
NameInTypeDescription
as_ofquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/invoices/:invoice_id/approve Approve invoice Bearer +

Approve invoice

Parameters
NameInTypeDescription
invoice_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/reports/balance-sheet Balance sheet report Bearer +

Balance sheet report

Parameters
NameInTypeDescription
as_ofquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/reports/cash-flow Cash flow statement Bearer +

Cash flow statement

Parameters
NameInTypeDescription
fromquerystring
toquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/periods/:period_id/close Close period Bearer +

Close period

Parameters
NameInTypeDescription
period_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/accounts List chart of accounts Bearer +

List chart of accounts

Parameters
NameInTypeDescription
typequerystring
activequerystring
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/accounting/accounts Create account Bearer +

Create account

Request
{
  "code": "...",
  "name": "...",
  "type": "...",
  "sub_type": "...",
  "parent_id": "...",
  "description": "...",
  "currency": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/bank-accounts List bank accounts Bearer +

List bank accounts

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/accounting/bank-accounts Create bank account Bearer +

Create bank account

Request
{
  "name": "...",
  "account_number": "...",
  "bank_name": "...",
  "currency": "...",
  "gl_account_id": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/currencies List currencies Bearer +

List currencies

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/accounting/currencies Create currency Bearer +

Create currency

Request
{
  "code": "...",
  "name": "...",
  "symbol": "...",
  "decimal_places": 0
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/exchange-rates List exchange rates Bearer +

List exchange rates

Parameters
NameInTypeDescription
from_currencyquerystring
to_currencyquerystring
Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/accounting/exchange-rates Create exchange rate Bearer +

Create exchange rate

Request
{
  "from_currency": "...",
  "to_currency": "...",
  "rate": 0,
  "effective_date": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/invoices List invoices Bearer +

List invoices

Parameters
NameInTypeDescription
typequerystring
statusquerystring
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "invoices": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/accounting/invoices Create invoice Bearer +

Create invoice

Request
{
  "type": "sales",
  "contact_name": "...",
  "date": "...",
  "due_date": "...",
  "lines": [
    {}
  ],
  "currency": "...",
  "notes": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/journal-entries List journal entries Bearer +

List journal entries

Parameters
NameInTypeDescription
statusquerystring
fromquerystring
toquerystring
account_idquerystring
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "entries": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/accounting/journal-entries Create journal entry Bearer +

Create journal entry

Request
{
  "date": "...",
  "description": "...",
  "reference": "...",
  "lines": [
    {}
  ],
  "currency": "...",
  "post": true
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/payments List payments Bearer +

List payments

Parameters
NameInTypeDescription
typequerystring
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {
    "payments": [
      {}
    ],
    "total": 0
  },
  "request_id": "..."
}
Try it
POST /v1/accounting/payments Create payment Bearer +

Create payment

Request
{
  "type": "receipt",
  "contact_name": "...",
  "date": "...",
  "amount": 0,
  "method": "...",
  "bank_account_id": "...",
  "reference": "...",
  "allocations": [
    {}
  ]
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/periods List accounting periods Bearer +

List accounting periods

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/accounting/periods Create period Bearer +

Create period

Request
{
  "name": "...",
  "start_date": "...",
  "end_date": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/recurring List recurring entries Bearer +

List recurring entries

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/accounting/recurring Create recurring entry Bearer +

Create recurring entry

Request
{
  "name": "...",
  "type": "journal_entry",
  "template": {},
  "frequency": "...",
  "next_run": "...",
  "end_date": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/tax-codes List tax codes Bearer +

List tax codes

Response
{
  "success": true,
  "data": [
    {}
  ],
  "request_id": "..."
}
Try it
POST /v1/accounting/tax-codes Create tax code Bearer +

Create tax code

Request
{
  "code": "...",
  "name": "...",
  "rate": 0,
  "type": "inclusive",
  "category": "..."
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/accounts/:account_id Get account Bearer +

Get account

Parameters
NameInTypeDescription
account_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/accounting/accounts/:account_id Update account Bearer +

Update account

Parameters
NameInTypeDescription
account_id*pathstring
Request
{
  "name": "...",
  "sub_type": "...",
  "description": "...",
  "is_active": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/accounts/:account_id Delete account Bearer +

Delete account

Parameters
NameInTypeDescription
account_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/accounting/bank-accounts/:bank_account_id Get bank account Bearer +

Get bank account

Parameters
NameInTypeDescription
bank_account_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/accounting/bank-accounts/:bank_account_id Update bank account Bearer +

Update bank account

Parameters
NameInTypeDescription
bank_account_id*pathstring
Request
{
  "name": "...",
  "account_number": "...",
  "bank_name": "...",
  "is_active": true
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/bank-accounts/:bank_account_id Delete bank account Bearer +

Delete bank account

Parameters
NameInTypeDescription
bank_account_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/accounting/currencies/:currency_id Get currency Bearer +

Get currency

Parameters
NameInTypeDescription
currency_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/accounting/currencies/:currency_id Update currency Bearer +

Update currency

Parameters
NameInTypeDescription
currency_id*pathstring
Request
{
  "name": "...",
  "symbol": "...",
  "decimal_places": 0
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/currencies/:currency_id Delete currency Bearer +

Delete currency

Parameters
NameInTypeDescription
currency_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/accounting/exchange-rates/:rate_id Get exchange rate Bearer +

Get exchange rate

Parameters
NameInTypeDescription
rate_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/exchange-rates/:rate_id Delete exchange rate Bearer +

Delete exchange rate

Parameters
NameInTypeDescription
rate_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/accounting/invoices/:invoice_id Get invoice Bearer +

Get invoice

Parameters
NameInTypeDescription
invoice_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/accounting/invoices/:invoice_id Update invoice Bearer +

Update invoice

Parameters
NameInTypeDescription
invoice_id*pathstring
Request
{
  "contact_name": "...",
  "date": "...",
  "due_date": "...",
  "notes": "...",
  "lines": [
    {}
  ]
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/invoices/:invoice_id Delete invoice Bearer +

Delete invoice

Parameters
NameInTypeDescription
invoice_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/accounting/journal-entries/:entry_id Get journal entry Bearer +

Get journal entry

Parameters
NameInTypeDescription
entry_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/accounting/journal-entries/:entry_id Update journal entry Bearer +

Update journal entry

Parameters
NameInTypeDescription
entry_id*pathstring
Request
{
  "date": "...",
  "description": "...",
  "reference": "...",
  "lines": [
    {}
  ]
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/journal-entries/:entry_id Delete journal entry Bearer +

Delete journal entry

Parameters
NameInTypeDescription
entry_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/accounting/periods/:period_id Get period Bearer +

Get period

Parameters
NameInTypeDescription
period_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/accounting/periods/:period_id Update period Bearer +

Update period

Parameters
NameInTypeDescription
period_id*pathstring
Request
{
  "name": "...",
  "start_date": "...",
  "end_date": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/periods/:period_id Delete period Bearer +

Delete period

Parameters
NameInTypeDescription
period_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/accounting/recurring/:recurring_id Get recurring entry Bearer +

Get recurring entry

Parameters
NameInTypeDescription
recurring_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/accounting/recurring/:recurring_id Update recurring entry Bearer +

Update recurring entry

Parameters
NameInTypeDescription
recurring_id*pathstring
Request
{
  "name": "...",
  "template": {},
  "frequency": "...",
  "next_run": "...",
  "end_date": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/recurring/:recurring_id Delete recurring entry Bearer +

Delete recurring entry

Parameters
NameInTypeDescription
recurring_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
GET /v1/accounting/tax-codes/:tax_code_id Get tax code Bearer +

Get tax code

Parameters
NameInTypeDescription
tax_code_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
PATCH /v1/accounting/tax-codes/:tax_code_id Update tax code Bearer +

Update tax code

Parameters
NameInTypeDescription
tax_code_id*pathstring
Request
{
  "name": "...",
  "rate": 0,
  "type": "...",
  "category": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
DELETE /v1/accounting/tax-codes/:tax_code_id Delete tax code Bearer +

Delete tax code

Parameters
NameInTypeDescription
tax_code_id*pathstring
Response
{
  "success": true,
  "data": {
    "id": "...",
    "deleted": true
  },
  "request_id": "..."
}
Try it
POST /v1/accounting/recurring/:recurring_id/execute Execute recurring entry now Bearer +

Execute recurring entry now

Parameters
NameInTypeDescription
recurring_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/reports/general-ledger General ledger report Bearer +

General ledger report

Parameters
NameInTypeDescription
fromquerystring
toquerystring
account_idquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/bank-transactions/:transaction_id Get bank transaction Bearer +

Get bank transaction

Parameters
NameInTypeDescription
transaction_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/payments/:payment_id Get payment Bearer +

Get payment

Parameters
NameInTypeDescription
payment_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/bank-accounts/:bank_account_id/import Import bank transactions Bearer +

Import bank transactions

Parameters
NameInTypeDescription
bank_account_id*pathstring
Request
{
  "transactions": [
    {
      "date": "...",
      "description": "...",
      "amount": 0,
      "type": "debit"
    }
  ]
}
Response 201
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/bank-accounts/:bank_account_id/transactions List bank transactions Bearer +

List bank transactions

Parameters
NameInTypeDescription
bank_account_id*pathstring
statusquerystring
fromquerystring
toquerystring
limitqueryinteger
offsetqueryinteger
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/bank-transactions/:transaction_id/match Match bank transaction Bearer +

Match bank transaction

Parameters
NameInTypeDescription
transaction_id*pathstring
Request
{
  "entry_id": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/journal-entries/:entry_id/post Post journal entry Bearer +

Post journal entry

Parameters
NameInTypeDescription
entry_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/reports/profit-and-loss Profit and loss report Bearer +

Profit and loss report

Parameters
NameInTypeDescription
fromquerystring
toquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/bank-accounts/:bank_account_id/reconcile Reconcile bank account Bearer +

Reconcile bank account

Parameters
NameInTypeDescription
bank_account_id*pathstring
Request
{
  "transaction_ids": [
    "..."
  ]
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/periods/:period_id/reopen Reopen period Bearer +

Reopen period

Parameters
NameInTypeDescription
period_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/journal-entries/:entry_id/reverse Reverse journal entry Bearer +

Reverse journal entry

Parameters
NameInTypeDescription
entry_id*pathstring
Request
{
  "date": "...",
  "description": "..."
}
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/reports/tax Tax report Bearer +

Tax report

Parameters
NameInTypeDescription
fromquerystring
toquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
GET /v1/accounting/reports/trial-balance Trial balance report Bearer +

Trial balance report

Parameters
NameInTypeDescription
as_ofquerystring
period_idquerystring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/invoices/:invoice_id/void Void invoice Bearer +

Void invoice

Parameters
NameInTypeDescription
invoice_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it
POST /v1/accounting/payments/:payment_id/void Void payment Bearer +

Void payment

Parameters
NameInTypeDescription
payment_id*pathstring
Response
{
  "success": true,
  "data": {},
  "request_id": "..."
}
Try it

Portal Auth10

Public portal authentication endpoints — login, signup, password reset, magic links, OTP, and email verification. No Bearer token required.

POST /v1/auth/portal-forgot-password Portal password reset request +

Request a password reset email via the public portal.

Request
{
  "email": "user@example.com",
  "redirect_to": "...",
  "turnstile_token": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-identify Identify tenant by email +

Look up which tenant(s) an email belongs to for portal login.

Request
{
  "email": "user@example.com"
}
Response
{
  "success": true,
  "data": {
    "tenant_id": "...",
    "multiple_tenants": true,
    "tenants": [
      {
        "id": "...",
        "name": "..."
      }
    ]
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-login Portal login +

Authenticate via the public portal with email, password, and tenant ID.

Request
{
  "email": "user@example.com",
  "password": "...",
  "tenant_id": "...",
  "turnstile_token": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-magic-link Portal send magic link +

Send a passwordless magic-link email via the portal.

Request
{
  "email": "user@example.com",
  "redirect_to": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-magic-link-verify Portal verify magic link +

Exchange a portal magic-link token for an auth session.

Request
{
  "token": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-otp-send Portal send OTP +

Send a one-time password via SMS for portal authentication.

Request
{
  "phone": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-otp-verify Portal verify OTP +

Verify portal OTP and create a session.

Request
{
  "phone": "...",
  "code": "..."
}
Response
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-reset-password Portal password reset +

Reset password using a token received via email.

Request
{
  "token": "...",
  "password": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-signup Portal signup +

Create a new account via the public portal.

Request
{
  "email": "user@example.com",
  "password": "...",
  "phone": "...",
  "user_metadata": {},
  "turnstile_token": "..."
}
Response 201
{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "refresh_token": "rt_abc123...",
    "token_type": "bearer",
    "expires_in": 3600,
    "user": {
      "id": "usr_abc123",
      "email": "user@example.com",
      "role": "authenticated"
    }
  },
  "request_id": "req_abc123"
}
Try it
POST /v1/auth/portal-verify-email Portal verify email +

Verify email address via portal authentication flow.

Request
{
  "token": "..."
}
Response
{
  "success": true,
  "data": {
    "message": "..."
  },
  "request_id": "req_abc123"
}
Try it