saidworth auth
DEVELOPERS / API V1

Connect the dots.

One project. Two ways in.

Create a project, publish your pages, add your exact callback URL, then create an API key with the Authentication permission. Use hosted sign-in for the quickest integration, or build your own interface against the server API.

Secret keys belong on your server. Use HTTPS. Store tokens in your server session, never in URLs or browser localStorage.

Base URL: https://auth.saidworth.com/api/v1. All timestamps use UTC.

Hosted sign-in

  1. Your server generates a cryptographically random state and a PKCE verifier (43–128 characters). Store both in your own session.
  2. Redirect the browser to the URL below. The callback must match a URL in Project settings exactly.
  3. At your callback, compare the returned state with your session using a constant-time comparison. Consume the state once.
  4. Exchange the returned code from your server within 60 seconds, using the same callback URL and original verifier.
  5. Keep the resulting access and refresh tokens in your application’s server session.
GET /authorize
  ?project=swp_YOUR_PROJECT_ID
  &redirect_uri=https%3A%2F%2Fyour-app.com%2Fcallback
  &state=YOUR_RANDOM_STATE
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256

The included resources/integration-example.php implements the complete server-side flow with state checking, PKCE and session storage.

POST /api/v1/token
X-API-Key: swsk_YOUR_SECRET_KEY
Content-Type: application/json

{
  "code": "swc_RETURNED_CODE",
  "redirect_uri": "https://your-app.com/callback",
  "code_verifier": "YOUR_ORIGINAL_VERIFIER"
}

The standalone login URL is useful for viewing your page. To connect a login to your application, always start at /authorize.

Bring your own interface

Call these endpoints from your application’s server. User accounts are isolated by project.

POST /api/v1/register
X-API-Key: swsk_YOUR_SECRET_KEY
Content-Type: application/json

{"name":"Alex","email":"alex@example.com","password":"a-long-unique-password"}

POST /api/v1/login
X-API-Key: swsk_YOUR_SECRET_KEY
Content-Type: application/json

{"email":"alex@example.com","password":"a-long-unique-password"}

Both return this shape. Registration returns HTTP 201.

{
  "token_type": "Bearer",
  "access_token": "swa_...",
  "refresh_token": "swr_...",
  "expires_in": 900,
  "user": {
    "id": 1,
    "name": "Alex",
    "email": "alex@example.com",
    "email_verified": false,
    "created_at": "2026-10-16 08:00:00"
  }
}

If verified email is required, registration creates the account and sends a verification link instead of issuing tokens. The response is HTTP 403. After verification, sign in normally.

Short access. Explicit control.

Access tokens last 15 minutes. Refresh tokens last 30 days and rotate on use. A refresh invalidates both old tokens; replace both atomically in your application. Revoking an API key blocks new server requests with that key. To end existing user access too, revoke their sessions or suspend the project.

GET /api/v1/me
Authorization: Bearer swa_ACCESS_TOKEN

POST /api/v1/refresh
X-API-Key: swsk_YOUR_SECRET_KEY
Content-Type: application/json

{"refresh_token":"swr_REFRESH_TOKEN"}

POST /api/v1/logout
Authorization: Bearer swa_ACCESS_TOKEN

For browser calls (including published configuration), add ?project=swp_YOUR_PROJECT_ID and allow the exact browser origin in project settings. Authentication, token exchange, refresh and user management remain server-only.

API reference

MethodEndpointPermission
GET/healthPublic
GET/config/{project_id}Public · published design
POST/registerauth
POST/loginauth
POST/tokenauth
POST/refreshauth
POST/password/resetauth
GET/meBearer access token
POST/logoutBearer access token
GET/users?page=1users:read
PATCH/users/{id}users:write
DELETE/users/{id}users:write

PATCH /users/{id} accepts {"name":"Alex","status":"suspended"}. Allowed statuses: active, suspended. The users list returns 50 users per page. Deletion is permanent. Password reset accepts {"email":"alex@example.com"} and returns a generic message.

Predictable errors

{"error":"A human-readable message."}

400 invalid flow or JSON · 401 invalid credentials/token · 403 permissions, suspended access or email verification · 404 missing resource · 405 wrong method · 409 conflict · 422 validation · 429 rate limited · 503 email unavailable.

Authentication attempts are limited per project and IP. Server keys allow up to 240 requests per minute per IP; access tokens allow 180. Honor the Retry-After header on 429 responses.