API Reference

Base URL: https://api.gctrl.ai
All requests require Authorization: Bearer <API_KEY> unless noted.

Sections

Auth

Auth routes do not require an API key. After verification, you receive an API key for all other endpoints.
POST /api/auth/signup

Request a verification code. Sends a 6-digit code to the provided email.

FieldTypeDescription
email*stringYour email address

Returns: 200 { "ok": true }

POST /api/auth/verify

Verify the code and receive an API key. Creates an account if one doesn't exist.

FieldTypeDescription
email*stringSame email from signup
code*string6-digit verification code

Returns: 200 { "api_key": "...", "workspace_id": "..." }

POST /api/auth/keys

Create an additional API key. Requires existing API key auth. The key name becomes the actor's identity.

FieldTypeDescription
name*stringName for the key (e.g., "content-writer", "qa-bot")

Returns: 201 { "api_key": "...", "name": "..." }

Tasks

POST /api/tasks

Create a task. created_by is auto-set from the API key name.

FieldTypeDefaultDescription
title*stringShort task name
objectivestringsame as titleDetailed instructions for the agent
prioritystringmediumlow, medium, high, critical
modestringfull-autofull-auto, approve-first, review-after
modelstringAI model hint (opus, sonnet, etc.)
projectstringGroup tasks by project
assigneestringWho should act on this task next
scheduled_forstringISO 8601 datetime for delayed execution
Status logic: If scheduled_for is set → scheduled. If mode is approve-firstawaiting-approval. Otherwise → queued.

Returns: 201 with task object

GET /api/tasks

List tasks. Sorted by priority then created_at.

Query ParamDescription
statusFilter by status (queued, in-progress, done, etc.)
assigneeFilter by assignee (includes unassigned tasks)

Returns: 200 with array of tasks

GET /api/tasks/:id

Get a single task by ID.

Returns: 200 with task object, or 404

POST /api/tasks/:id/approve

Approve a task. Only valid when status is awaiting-approval.

Returns: 200 with updated task, or 400

POST /api/tasks/:id/reject

Reject a task. Valid from any active status.

Returns: 200 with updated task

POST /api/tasks/:id/done

Mark a task as done. Sets completed_at.

FieldTypeDescription
outputstringOptional result text

Returns: 200 with updated task

POST /api/tasks/:id/cancel

Cancel a task. Rejected if status is already done, cancelled, or rejected.

Returns: 200 with updated task, or 400

DELETE /api/tasks/:id

Delete a task permanently.

Returns: 200 { "ok": true }, or 404

Schedules

POST /api/schedules

Create a recurring schedule. Tasks are created automatically on the cron rhythm.

FieldTypeDefaultDescription
title*stringSchedule name
cron*stringCron expression (e.g., "0 9 * * *")
objectivestringInstructions passed to created tasks
prioritystringmediumPriority for created tasks
modestringfull-autoExecution mode for created tasks
modelstringAI model for created tasks
projectstringProject for created tasks

Returns: 201 with schedule object

GET /api/schedules

List all schedules.

Returns: 200 with array

POST /api/schedules/:id/trigger

Create a task immediately from the schedule template. Updates last_run.

Returns: 201 with task object

POST /api/schedules/:id/pause

Pause a schedule. Sets active = false.

Returns: 200 with updated schedule

POST /api/schedules/:id/resume

Resume a paused schedule.

Returns: 200 with updated schedule

DELETE /api/schedules/:id

Delete a schedule permanently.

Returns: 200 { "ok": true }, or 404

Worker

Modal execution: GET /api/worker/next returns null if any task is already in-progress. One task at a time per workspace.
GET /api/worker/next

Poll for the next available task. Returns the highest-priority queued or approved task and sets it to in-progress.

Query ParamDescription
assigneeReturn tasks assigned to this name or unassigned

Returns: 200 { "task": { ... } } or { "task": null }

POST /api/worker/complete

Report task completion.

FieldTypeDescription
task_id*stringTask ID
outputstringTask output / result
errorstringError message (sets status to blocked)
duration_secsnumberExecution duration
Status logic: If error is set → blocked. If task mode is review-afterreview. Otherwise → done.

Returns: 200 with updated task

POST /api/worker/heartbeat

Worker keepalive signal.

Returns: 200 { "ok": true }

Audit Log

GET /api/audit-log

Get audit log entries. Every task state change, approval, and completion is recorded.

Query ParamDescription
entity_typeFilter by type (task, schedule)
entity_idFilter by specific entity ID

Returns: 200 with array of audit log entries

System

GET /api/status

Task counts grouped by status.

Returns: 200 { "queued": 3, "in-progress": 1, "done": 12, ... }

GET /api/quota

Get quota status for your current plan.

Returns: 200 with quota limits and current usage

GET /api/health

Health check. No authentication required.

Returns: 200 { "ok": true }