Skip to main content

REST API Reference

CrewForm provides two API layers:
  • API v2 — Edge Functions API with versioned envelopes, rate limiting, and pagination (recommended)
  • API v1 (Legacy) — Direct Supabase PostgREST access (still supported)

API v2 (Recommended)

Base URL: https://<your-project>.supabase.co/functions/v1
The v2 API uses CrewForm Edge Functions with structured responses, per-tier rate limiting, and cursor-based pagination.

Authentication

All requests require one of:
MethodHeaderUse case
API KeyX-API-Key: cf_your_keyZapier, scripts, third-party tools
JWTAuthorization: Bearer <token>Frontend, authenticated clients
Generate API keys in Settings → API Keys.

Versioning

Set X-API-Version: 2 to opt into v2 response format. Omitting the header defaults to v1 (raw data, no envelope).
curl -H "X-API-Key: cf_..." \
     -H "X-API-Version: 2" \
     https://your-project.supabase.co/functions/v1/api-agents

Response Format

v2 Success:
{
  "data": { ... },
  "meta": {
    "api_version": 2,
    "request_id": "req_abc123def456",
    "timestamp": "2026-03-13T10:00:00.000Z"
  }
}
v2 List (paginated):
{
  "data": {
    "items": [ ... ],
    "next_cursor": "2026-03-12T08:00:00.000Z",
    "has_more": true
  },
  "meta": { ... }
}
v2 Error:
{
  "error": {
    "code": "not_found",
    "message": "Agent not found"
  },
  "meta": { ... }
}

Rate Limits

Enforced per workspace per minute:
PlanRequests/min
Free30
Pro120
Team300
Enterprise600
Every response includes:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1710324360
Exceeding the limit returns 429 Too Many Requests with a Retry-After header.

Pagination

List endpoints support cursor-based pagination:
ParamTypeDefaultDescription
limitint50Items per page
cursorstringCursor from next_cursor of previous response
# First page
curl -H "X-API-Key: cf_..." -H "X-API-Version: 2" \
  "https://.../functions/v1/api-agents?limit=10"

# Next page
curl -H "X-API-Key: cf_..." -H "X-API-Version: 2" \
  "https://.../functions/v1/api-agents?limit=10&cursor=2026-03-12T08:00:00.000Z"

Endpoints

Agents — /functions/v1/api-agents

MethodParamsDescription
GETList all agents
GET?id=<uuid>Get single agent
POSTbodyCreate agent
PATCH?id=<uuid> + bodyUpdate agent
DELETE?id=<uuid>Delete agent
Create body:
{
  "name": "Code Reviewer",
  "model": "claude-sonnet-4-20250514",
  "description": "Reviews code for bugs and best practices",
  "system_prompt": "You are a senior code reviewer...",
  "temperature": 0.3,
  "tools": [],
  "status": "idle"
}

Tasks — /functions/v1/api-tasks

MethodParamsDescription
GETList all tasks
GET?status=runningFilter by status
GET?id=<uuid>Get single task
POSTbodyCreate task (auto-dispatches if agent/team assigned)
PATCH?id=<uuid> + bodyUpdate task
DELETE?id=<uuid>Delete task
Create body:
{
  "title": "Review PR #42",
  "description": "Review the authentication changes",
  "priority": "high",
  "assigned_agent_id": "<uuid>",
  "metadata": {}
}
Task statuses: pending, dispatched, running, completed, failed, cancelled Task priorities: low, medium, high, urgent

Teams — /functions/v1/api-teams

MethodParamsDescription
GETList all teams (includes members)
GET?id=<uuid>Get single team
POSTbodyCreate team
PATCH?id=<uuid> + bodyUpdate team
DELETE?id=<uuid>Delete team
Create body:
{
  "name": "Content Pipeline",
  "description": "Research → Write → Edit",
  "mode": "pipeline",
  "config": {
    "steps": [
      {
        "agent_id": "<uuid>",
        "step_name": "Research",
        "instructions": "Research the topic thoroughly",
        "expected_output": "Detailed research notes",
        "on_failure": "retry",
        "max_retries": 2
      }
    ],
    "auto_handoff": true
  }
}
Team modes: pipeline, orchestrator, collaboration

Team Runs — /functions/v1/api-runs

MethodParamsDescription
GETList all runs
GET?team_id=<uuid>Filter by team
GET?id=<uuid>Get single run (includes messages)
POSTbodyStart a new team run
Create body:
{
  "team_id": "<uuid>",
  "input_task": "Research the latest trends in AI agent frameworks"
}

Webhook Hooks — /functions/v1/api-hooks

MethodParamsDescription
GETList active webhook subscriptions
POSTbodySubscribe (Zapier REST Hook)
DELETE?id=<uuid>Unsubscribe
Subscribe body:
{
  "target_url": "https://hooks.zapier.com/...",
  "event": "task_completed"
}

Identity — /functions/v1/api-me

MethodDescription
GETReturns current user, workspace, plan, and API version
Response:
{
  "id": "<user-uuid>",
  "email": "user@example.com",
  "name": "Vince",
  "workspace_id": "<workspace-uuid>",
  "workspace_name": "My Workspace",
  "plan": "pro",
  "api_version": 2
}

Error Codes (v2)

CodeHTTP StatusDescription
bad_request400Invalid request body or parameters
unauthorized401Missing or invalid authentication
not_found404Resource not found
method_not_allowed405HTTP method not supported
rate_limit_exceeded429Too many requests
internal_error500Server error

Example: cURL

# List agents (v2 with envelope)
curl -s \
  -H "X-API-Key: cf_abc123..." \
  -H "X-API-Version: 2" \
  "https://your-project.supabase.co/functions/v1/api-agents"

# Create a task and auto-dispatch to an agent
curl -s -X POST \
  -H "X-API-Key: cf_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"title":"Review PR","description":"...","assigned_agent_id":"<uuid>"}' \
  "https://your-project.supabase.co/functions/v1/api-tasks"

# Start a team run
curl -s -X POST \
  -H "X-API-Key: cf_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"team_id":"<uuid>","input_task":"Research AI trends"}' \
  "https://your-project.supabase.co/functions/v1/api-runs"


API v1 (Legacy)

Base URL: https://<your-project>.supabase.co/rest/v1
The v1 API provides direct Supabase PostgREST access. It is still supported but we recommend migrating to API v2 for rate limiting, structured responses, and pagination.

Authentication

All API requests require a REST API key in the Authorization header:
curl -H "Authorization: Bearer crfm_your_api_key" \
     -H "Content-Type: application/json" \
     https://your-project.supabase.co/rest/v1/agents

Creating API Keys

  1. Go to Settings → API Keys
  2. Click Generate Key
  3. Copy the key — it’s only shown once
  4. The key is hashed (SHA-256) before storage for security

Endpoints

All endpoints are accessed via the Supabase REST API at:
https://<your-project>.supabase.co/rest/v1/<table>
You also need the apikey header with your Supabase anon key:
curl -H "Authorization: Bearer crfm_your_api_key" \
     -H "apikey: your-supabase-anon-key" \
     https://your-project.supabase.co/rest/v1/agents

Agents

List Agents

GET /rest/v1/agents?select=*
Response:
[
  {
    "id": "uuid",
    "name": "Code Reviewer",
    "description": "Reviews code for bugs and best practices",
    "model": "claude-sonnet-4-20250514",
    "provider": "anthropic",
    "system_prompt": "You are a senior code reviewer...",
    "temperature": 0.3,
    "max_tokens": 4096,
    "tags": ["code", "review"],
    "workspace_id": "uuid",
    "created_at": "2026-01-15T10:00:00Z",
    "updated_at": "2026-01-15T10:00:00Z"
  }
]

Create Agent

POST /rest/v1/agents
Content-Type: application/json

{
  "name": "Code Reviewer",
  "model": "claude-sonnet-4-20250514",
  "provider": "anthropic",
  "system_prompt": "You are a senior code reviewer...",
  "workspace_id": "your-workspace-id"
}

Update Agent

PATCH /rest/v1/agents?id=eq.{agent_id}
Content-Type: application/json

{
  "name": "Updated Name",
  "temperature": 0.5
}

Delete Agent

DELETE /rest/v1/agents?id=eq.{agent_id}

Tasks

List Tasks

GET /rest/v1/tasks?select=*&order=created_at.desc
Query parameters for filtering:
ParameterExampleDescription
statuseq.runningFilter by status
priorityeq.highFilter by priority
agent_ideq.{uuid}Filter by assigned agent

Create Task

POST /rest/v1/tasks
Content-Type: application/json

{
  "title": "Review PR #42",
  "description": "Review the authentication changes",
  "agent_id": "uuid",
  "priority": "high",
  "workspace_id": "your-workspace-id"
}
Task statuses: pending, running, completed, failed, cancelled Task priorities: low, medium, high, critical

Get Task Detail

GET /rest/v1/tasks?id=eq.{task_id}&select=*

Teams

List Teams

GET /rest/v1/teams?select=*

Create Team

POST /rest/v1/teams
Content-Type: application/json

{
  "name": "Content Pipeline",
  "description": "Research → Write → Edit",
  "mode": "pipeline",
  "workspace_id": "your-workspace-id"
}

Team Runs

GET /rest/v1/team_runs?team_id=eq.{team_id}&select=*&order=created_at.desc

Usage Records

Query Usage

GET /rest/v1/usage_records?select=*&created_at=gte.2026-01-01&order=created_at.desc
Response fields:
FieldTypeDescription
task_iduuidAssociated task
agent_iduuidAgent that ran
providerstringLLM provider
modelstringModel used
prompt_tokensintegerInput tokens
completion_tokensintegerOutput tokens
estimated_cost_usddecimalEstimated cost
billing_modelstringper-token or subscription-quota

Marketplace

Browse Agents

GET /rest/v1/agents?is_marketplace=eq.true&select=*

Install Agent (RPC)

POST /rest/v1/rpc/increment_install_count
Content-Type: application/json

{
  "agent_row_id": "uuid"
}

Rate Limits (v1)

The Supabase free tier includes:
  • 500 requests/minute per API key
  • 50,000 requests/month total
For higher limits, upgrade your Supabase plan.

Error Handling (v1)

All errors follow the standard Supabase/PostgREST format:
{
  "code": "PGRST301",
  "message": "Row not found",
  "details": null,
  "hint": null
}
Common error codes:
HTTP StatusMeaning
401Missing or invalid API key
403Row-Level Security denied access
404Resource not found
409Conflict (duplicate key)
422Validation error