Base URL
http://localhost:3333/api/· Authentication · Conventions
Schedule Routes
Base path: /api/schedules
The durable cron scheduler (PRD-091 Layer 1). Use when the user wants recurring execution of a goal. Survives backend restart, uses in-zone DST-correct timing, idempotent on last_run. Hangs on HeartbeatService — no separate process.
Schedule shape
{
"id": "uuid",
"user_id": "user-uuid",
"target_type": "goal",
"target_id": "goal-uuid",
"cron": "0 9 * * MON-FRI",
"timezone": "America/New_York",
"next_run": "2026-06-22T13:00:00.000Z",
"last_run": "2026-06-19T13:00:00.000Z",
"enabled": true,
"on_missed": "fire_once",
"created_at": "..."
}Supported cron syntax
5-field cron (minute hour dom month dow) plus macros:
- Macros:
@hourly,@daily,@midnight,@weekly,@monthly,@yearly,@annually - Fields:
*,*/N,A-B,A,B,C, day-of-week names (MON–SUN),7aliases to0(Sunday) - Dom/dow OR semantics: when both restricted, the schedule fires when either matches (standard cron)
- Timezone: IANA name (e.g.
America/New_York,Europe/London). Defaults toUTC.
on_missed values
| Value | Behavior on backend restart |
|---|---|
fire_once (default) |
If next_run is in the past, fire once then resume |
fire_all |
Fire once for each missed slot (use sparingly — can cascade) |
skip |
Skip missed firings; only resume forward |
List Schedules
GET /
- Authentication: Required
- Response:
{ "success": true, "schedules": [ { ... } ] }Get Schedules by Target
GET /target/:targetType/:targetId
- Authentication: Required
- Parameters:
targetType(path):goal(MVP currently only supports goal)targetId(path): the goal ID
- Description: Useful for the Goals UI to show "this goal is scheduled."
- Response:
{ "success": true, "schedules": [ { ... } ] }Preview Cron Firings (No Persist)
POST /preview
- Authentication: Required
- Body:
{
"cron": "0 9 * * MON-FRI",
"timezone": "America/New_York",
"count": 5
}- Description: Validates the cron expression and returns the next
countfiring times (max 25). Persists nothing. Use this when surfacing "this schedule will next fire on..." in the UI before the user clicks Create. - Response:
{
"success": true,
"previews": [
"2026-06-22T13:00:00.000Z",
"2026-06-23T13:00:00.000Z",
"2026-06-24T13:00:00.000Z"
]
}- Errors:
400whencronis missing or invalid.
Create Schedule
POST /
- Authentication: Required
- Body:
{
"targetType": "goal",
"targetId": "goal-uuid",
"cron": "0 9 * * MON-FRI",
"timezone": "America/New_York",
"enabled": true,
"onMissed": "fire_once"
}- Description: Creates a schedule.
next_runis computed fromcron+timezone.enableddefaults totrue.onMisseddefaults tofire_once. - Response (
201):
{ "success": true, "schedule": { ... } }- Errors:
400whentargetType,targetId, orcronis missing400whencronis invalid (perisValidCron)
Update Schedule
PATCH /:id
- Authentication: Required
- Body (any subset):
{
"cron": "0 10 * * MON-FRI",
"timezone": "Europe/London",
"enabled": false,
"onMissed": "skip"
}- Description: Updates schedule fields. When
cron,timezone, oronMissedchange,next_runis recomputed. Settingenabled: falsepauses without deleting. - Response:
{ "success": true, "schedule": { ... } }- Errors:
404not found,403forbidden,400invalid cron
Fire Schedule Now
POST /:id/fire-now
- Authentication: Required
- Description: Manually trigger the schedule's target (currently invokes
TaskOrchestrator.executeGoalAutonomous). Does NOT updatenext_run— the regular cadence continues unaffected. Useful for "test run" or "I want it now." - Response:
{ "success": true, "result": { "executionId": "...", "status": "running" } }Get Run History
GET /:id/runs
- Authentication: Required
- Parameters:
limit(query, optional): max500, default50
- Response:
{
"success": true,
"runs": [
{
"id": "run-uuid",
"schedule_id": "schedule-uuid",
"fired_at": "2026-06-19T13:00:00.000Z",
"execution_id": "exec-uuid",
"status": "completed",
"duration_ms": 4823
}
]
}Delete Schedule
DELETE /:id
- Authentication: Required
- Response:
{ "success": true, "deleted": true }Email Listener Routes
Base path: /api/email-listeners
Get Email Listeners
GET /
- Authentication: Required
- Description: Get all workflows with
receive-emailtrigger nodes for the authenticated user - Response:
{
"success": true,
"listeners": [
{
"id": "workflow-id",
"workflow_id": "workflow-id",
"workflow_name": "Email Handler Workflow",
"workflow_status": "active",
"email_address": "workflow-123@agnt.gg",
"email_config": "Built-in Email",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]
}