Skip to main content

Overview

The Adapt API uses bearer token authentication. All requests to /v1/* endpoints (except /v1/auth/*) require a valid authentication token in the Authorization header.

Authentication Methods

Adapt supports two authentication methods:

JWT Bearer Tokens (Primary)

JSON Web Tokens (JWTs) are issued by Supabase Auth and used by web applications. These tokens have short expiry times and can be refreshed. Usage:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Characteristics:
  • Short expiry (typically 15 minutes)
  • Issued during user login via Supabase Auth
  • Automatically refreshed by the client
  • Contains user claims and metadata

API Keys (For Integrations)

API key management endpoints are planned but not yet implemented. Currently, only JWT authentication is supported.
API keys will be long-lived tokens for integrations, CLI tools, and automated workflows. Planned usage:
Authorization: Bearer sk_live_abc123...
X-API-Key: sk_live_abc123...
Planned characteristics:
  • Long-lived (no automatic expiry)
  • Scoped permissions (e.g., jobs:read, jobs:create)
  • Managed through user dashboard
  • Suitable for server-to-server communication

Making Authenticated Requests

Include your token in the Authorization header using the Bearer scheme:
curl -X GET https://adapt.app.goodnative.co/v1/jobs \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
JavaScript example:
const response = await fetch('https://adapt.app.goodnative.co/v1/jobs', {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  }
});

const data = await response.json();
Go example:
req, _ := http.NewRequest("GET", "https://adapt.app.goodnative.co/v1/jobs", nil)
req.Header.Set("Authorization", "Bearer "+token)

client := &http.Client{}
resp, err := client.Do(req)

Authentication Flow

Web Application Flow

  1. User signs in via Supabase Auth (email/password or OAuth)
  2. Supabase returns a JWT access token and refresh token
  3. Client includes JWT in Authorization header for API requests
  4. Client refreshes token before expiry using refresh token

User Registration

New users are automatically created in Adapt’s database upon first authentication:
POST /v1/auth/register
Content-Type: application/json

{
  "user_id": "auth-provider-user-id",
  "email": "[email protected]",
  "full_name": "John Doe"
}
Response:
{
  "status": "success",
  "data": {
    "user": {
      "id": "auth-provider-user-id",
      "email": "[email protected]",
      "full_name": "John Doe",
      "organisation_id": "org_abc123",
      "created_at": "2026-03-03T12:34:56Z"
    },
    "organisation": {
      "id": "org_abc123",
      "name": "Personal Organisation",
      "created_at": "2026-03-03T12:34:56Z"
    }
  }
}
user_id
string
required
The user ID from your authentication provider (Supabase).
email
string
required
The user’s email address.
first_name
string
The user’s first name (max 80 characters).
last_name
string
The user’s last name (max 80 characters).
full_name
string
The user’s full name (max 120 characters).
org_name
string
Custom organisation name. If not provided, defaults to the email domain or “Personal Organisation”.

User Profile

Retrieve the authenticated user’s profile:
GET /v1/auth/profile
Authorization: Bearer YOUR_JWT_TOKEN
Response:
{
  "status": "success",
  "data": {
    "user": {
      "id": "user_123",
      "email": "[email protected]",
      "full_name": "John Doe",
      "organisation_id": "org_abc123",
      "created_at": "2026-03-03T12:34:56Z",
      "updated_at": "2026-03-03T12:34:56Z"
    },
    "organisation": {
      "id": "org_abc123",
      "name": "Example Organisation",
      "created_at": "2026-03-03T12:34:56Z",
      "updated_at": "2026-03-03T12:34:56Z"
    },
    "auth_methods": ["email"]
  }
}

Update Profile

Update the authenticated user’s profile information:
PATCH /v1/auth/profile
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "full_name": "John Smith"
}
first_name
string
Update first name (max 80 characters).
last_name
string
Update last name (max 80 characters).
full_name
string
Update full name (max 120 characters).

Session Validation

Validate a JWT token and retrieve session information:
POST /v1/auth/session
Content-Type: application/json

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response:
{
  "status": "success",
  "data": {
    "valid": true,
    "user_id": "user_123",
    "email": "[email protected]",
    "exp": 1709472896
  }
}

Protected vs Public Endpoints

Public Endpoints (No Authentication Required)

  • GET /health - Service health check
  • GET /health/db - Database health check
  • POST /v1/auth/register - User registration
  • POST /v1/auth/session - Session validation

Protected Endpoints (Authentication Required)

All other /v1/* endpoints require authentication:
  • /v1/jobs - Job management
  • /v1/schedulers - Recurring job schedulers
  • /v1/auth/profile - User profile
  • Future endpoints for tasks, webhooks, API keys, etc.

Authentication Errors

The API returns specific error codes for authentication failures:

Missing Authentication

{
  "status": 401,
  "message": "Authentication required",
  "code": "UNAUTHORISED",
  "request_id": "req_a1b2c3d4"
}

Invalid Token

{
  "status": 401,
  "message": "Invalid or expired token",
  "code": "UNAUTHORISED",
  "request_id": "req_a1b2c3d4"
}

Insufficient Permissions

{
  "status": 403,
  "message": "Insufficient permissions for this operation",
  "code": "FORBIDDEN",
  "request_id": "req_a1b2c3d4"
}

Security Best Practices

Never expose your JWT tokens or API keys in client-side code, public repositories, or logs.

Token Storage

  • Web applications: Store tokens in memory or httpOnly cookies
  • Mobile apps: Use secure keychain/keystore mechanisms
  • Server applications: Use environment variables or secret management systems

Token Refresh

  • Implement automatic token refresh before expiry
  • Handle 401 Unauthorized responses by refreshing and retrying
  • Redirect to login if refresh fails

Secure Communication

  • Always use HTTPS in production
  • Validate SSL/TLS certificates
  • Never send tokens in URL query parameters

Organisation-Based Access

All API resources are scoped to the authenticated user’s organisation. Users can only access resources that belong to their organisation, enforced by:
  • Database-level Row Level Security (RLS)
  • Application-level organisation ID filtering
  • JWT claims containing organisation context
This ensures complete data isolation between different organisations using Adapt.

Build docs developers (and LLMs) love