> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensorlake.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Cron Scheduler

> Schedule recurring invocations of your Orchestration endpoints.

Cron schedules trigger your deployed orchestration endpoints on a recurring basis. You can manage schedules programmatically via the API or through the Applications UI.

## Creating a Schedule

Send a `POST` request to create a cron schedule for a deployed application. The schedule starts immediately after creation.

```
POST /applications/{application}/cron-schedules
```

<CodeGroup>
  ```python Python theme={null}
  import requests, base64, json

  application = "my-app"

  payload = {"cron_expression": "0 * * * *"}  # Every hour

  # Optional: pass input data to each invocation
  input_data = json.dumps({"report_type": "daily"}).encode()
  payload["input_base64"] = base64.b64encode(input_data).decode()

  response = requests.post(
      f"https://api.tensorlake.ai/applications/{application}/cron-schedules",
      json=payload,
      headers={"Authorization": "Bearer TENSORLAKE_API_KEY"},
  )
  response.raise_for_status()

  schedule_id = response.json()["schedule_id"]
  print(f"Created schedule: {schedule_id}")
  ```

  ```typescript TypeScript theme={null}
  async function createCronSchedule(
    application: string,
    cronExpression: string,
    inputBytes?: Uint8Array,
  ) {
    const body: Record<string, string> = { cron_expression: cronExpression };
    if (inputBytes) {
      body.input_base64 = btoa(String.fromCharCode(...inputBytes));
    }

    const res = await fetch(
      `/applications/${application}/cron-schedules`,
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      },
    );

    if (!res.ok) {
      const err = await res.json();
      throw new Error(err.error ?? `HTTP ${res.status}`);
    }

    const { schedule_id } = await res.json();
    return schedule_id as string;
  }
  ```
</CodeGroup>

### Request fields

| Field             | Type   | Required | Description                                                                      |
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------- |
| `cron_expression` | string | Yes      | A valid 5-field cron expression                                                  |
| `input_base64`    | string | No       | Base64-encoded bytes passed as input on every invocation. Maximum 1 MiB decoded. |

The response returns a `schedule_id`. Save this — it is required to delete the schedule later.

<Note>
  The minimum allowed interval is 60 seconds. `* * * * *` (every minute) is the fastest supported expression. Sub-minute expressions are rejected with a `400` error.
</Note>

## Listing Schedules

Retrieve all cron schedules for an application:

```
GET /v1/namespaces/{namespace}/applications/{application}/cron-schedules
```

<CodeGroup>
  ```python Python theme={null}
  response = requests.get(
      f"https://api.tensorlake.ai/applications/{application}/cron-schedules",
      headers={"Authorization": "Bearer TENSORLAKE_API_KEY"},
  )
  response.raise_for_status()

  for schedule in response.json()["schedules"]:
      print(schedule["id"], schedule["cron_expression"], schedule["next_fire_time_ms"])
  ```

  ```typescript TypeScript theme={null}
  interface CronSchedule {
    id: string;
    application_name: string;
    cron_expression: string;
    next_fire_time_ms: number;
    last_fired_at_ms: number | null;
    created_at: number;
    enabled: boolean;
  }

  async function listCronSchedules(application: string) {
    const res = await fetch(
      `/applications/${application}/cron-schedules`,
    );
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const { schedules } = await res.json();
    return schedules as CronSchedule[];
  }
  ```
</CodeGroup>

### Response fields

| Field               | Type           | Description                                                                           |
| ------------------- | -------------- | ------------------------------------------------------------------------------------- |
| `id`                | string         | Unique ID for this schedule                                                           |
| `application_name`  | string         | The application this schedule belongs to                                              |
| `cron_expression`   | string         | The schedule expression as stored                                                     |
| `next_fire_time_ms` | number         | Unix timestamp (ms) of the next scheduled invocation                                  |
| `last_fired_at_ms`  | number \| null | Unix timestamp (ms) of the last invocation. `null` if the schedule has never fired.   |
| `created_at`        | number         | Monotonic counter for ordering — not a wall-clock timestamp, do not display as a date |
| `enabled`           | boolean        | Always `true` — reserved for future use                                               |

`next_fire_time_ms` and `last_fired_at_ms` are standard Unix millisecond timestamps. In JavaScript: `new Date(next_fire_time_ms)`.

## Deleting a Schedule

```
DELETE /applications/{application}/cron-schedules/{schedule_id}
```

<CodeGroup>
  ```python Python theme={null}
  response = requests.delete(
      f"https://api.tensorlake.ai/applications/{application}/cron-schedules/{schedule_id}",
      headers={"Authorization": "Bearer TENSORLAKE_API_KEY"},
  )
  response.raise_for_status()
  ```

  ```typescript TypeScript theme={null}
  async function deleteCronSchedule(
    application: string,
    scheduleId: string,
  ) {
    const res = await fetch(
      `/applications/${application}/cron-schedules/${scheduleId}`,
      { method: "DELETE" },
    );
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
  }
  ```
</CodeGroup>

Deletion is permanent. To modify a schedule, delete it and recreate it — you can reuse the `cron_expression` from the list response to pre-populate the new request.

## Limits

| Limit                             | Value           |
| --------------------------------- | --------------- |
| Minimum interval                  | 60 seconds      |
| Maximum schedules per application | 100             |
| Maximum input payload             | 1 MiB (decoded) |

## Related

<CardGroup cols={2}>
  <Card title="Observability" icon="chart-line" href="/applications/observability">
    Monitor scheduled invocations alongside the rest of your application activity.
  </Card>

  <Card title="Retries" icon="rotate" href="/applications/retries">
    Configure automatic retries for functions triggered by the scheduler.
  </Card>

  <Card title="Secrets" icon="user-secret" href="/applications/secrets">
    Pass secrets securely to functions that run on a schedule.
  </Card>
</CardGroup>
