Skip to main content

Smart Scheduling API

The Smart Scheduling API allows you to programmatically trigger scheduling and retrieve scheduling status.

Endpoints

Trigger Scheduling

Triggers the unified scheduler for a workspace, scheduling both habits and tasks.

Path Parameters

wsId
string
required
The workspace ID (UUID format)

Request Body

windowDays
number
default:30
How many days into the future to schedule events (7-90)
forceReschedule
boolean
default:false
If true, deletes existing auto-generated events and creates new ones

Response

{
  "success": true,
  "summary": {
    "habitsScheduled": 5,
    "tasksScheduled": 3,
    "eventsCreated": 12,
    "bumpedHabits": 1,
    "rescheduledHabits": 1,
    "windowDays": 30
  },
  "habits": {
    "events": [
      {
        "habitId": "uuid",
        "habitName": "Morning Meditation",
        "occurrence": "2024-01-15",
        "duration": 20,
        "event": {
          "id": "uuid",
          "start_at": "2024-01-15T07:00:00Z",
          "end_at": "2024-01-15T07:20:00Z"
        }
      }
    ],
    "warnings": []
  },
  "tasks": {
    "events": [
      {
        "taskId": "uuid",
        "taskName": "Complete report",
        "scheduledMinutes": 120,
        "warning": null,
        "events": [
          {
            "id": "uuid",
            "start_at": "2024-01-15T09:00:00Z",
            "end_at": "2024-01-15T11:00:00Z",
            "scheduled_minutes": 120
          }
        ]
      }
    ],
    "bumpedHabits": [
      {
        "habitId": "uuid",
        "habitName": "Reading",
        "occurrence": "2024-01-15",
        "originalEventId": "uuid"
      }
    ],
    "warnings": []
  },
  "rescheduledHabits": [
    {
      "habitId": "uuid",
      "habitName": "Reading",
      "occurrence": "2024-01-15",
      "duration": 30,
      "event": {
        "id": "uuid",
        "start_at": "2024-01-15T19:00:00Z",
        "end_at": "2024-01-15T19:30:00Z"
      }
    }
  ],
  "warnings": []
}

Example

curl -X POST "https://tuturuuu.com/api/v1/workspaces/{wsId}/calendar/schedule" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{"windowDays": 30, "forceReschedule": false}'

Get Scheduling Status

Retrieves the current scheduling status and statistics for a workspace.

Path Parameters

wsId
string
required
The workspace ID (UUID format)

Response

{
  "lastScheduledAt": "2024-01-15T10:30:00Z",
  "lastStatus": "success",
  "lastMessage": "Scheduled 5 habits and 3 tasks",
  "statistics": {
    "habitsScheduled": 5,
    "tasksScheduled": 3,
    "eventsCreated": 12,
    "bumpedHabits": 1,
    "windowDays": 30
  },
  "schedulableItems": {
    "activeHabits": 7,
    "autoScheduleTasks": 4
  }
}

Example

curl "https://tuturuuu.com/api/v1/workspaces/{wsId}/calendar/schedule" \
  -H "Cookie: your-session-cookie"

Authentication

User Authentication

Standard user authentication via session cookie. The user must be a member of the workspace.

Cron Authentication

For background jobs, the API accepts a Bearer token with the cron secret:
Authorization: Bearer {CRON_SECRET}
This is used by the Vercel cron job that runs scheduling every 6 hours. The cron secret is read from process.env.CRON_SECRET ?? process.env.VERCEL_CRON_SECRET.

Error Responses

StatusDescription
400Invalid workspace ID
401Not authenticated
403Not a workspace member
409Safe apply blocked because the schedule still has unresolved warnings
422Workspace timezone is not set, or is set to auto
500Internal server error

Rate Limiting

The scheduling endpoint is rate-limited to prevent abuse:
  • Manual triggers: Limited by standard API rate limits
  • Cron triggers: A single global cron runs every 6 hours and fans out to eligible workspaces (not per-workspace at the cron level)

Cron Job

Smart Scheduling runs automatically every 6 hours via Vercel Cron:
{
  "path": "/api/cron/calendar/smart-schedule",
  "schedule": "0 */6 * * *"
}
The cron job:
  1. Finds all workspaces with auto-schedule enabled habits or tasks
  2. Calls the scheduling API for each workspace
  3. Logs results and any errors
The cron job uses forceReschedule: false to avoid disrupting existing schedules. Only new items are scheduled.