> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.recursiv.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.recursiv.io/_mcp/server.

# Scheduled Jobs

## Overview

Create scheduled jobs that run on a cron schedule in your project's sandbox. No need to manage your own server — define the handler code and schedule, and Recursiv executes it automatically.

All job methods are available on `r.jobs`.

## Methods

| Method              | Description                               |
| ------------------- | ----------------------------------------- |
| `create(input)`     | Create a scheduled job.                   |
| `list()`            | List all scheduled jobs.                  |
| `update(id, input)` | Update a job (schedule, handler, status). |
| `delete(id)`        | Delete a scheduled job.                   |

## Create a job

```typescript
const { data: job } = await r.jobs.create({
  name: 'daily-digest',
  cron: '0 8 * * *', // Every day at 8am
  project_id: 'proj_123',
  handler_code: `async () => {
    // This runs in your project sandbox on schedule
    const db = require('pg');
    const client = new db.Client({ connectionString: process.env.DATABASE_URL });
    await client.connect();
    const { rows } = await client.query('SELECT COUNT(*) FROM orders WHERE created_at > NOW() - INTERVAL \\'1 day\\'');
    console.log('Orders today:', rows[0].count);
    await client.end();
  }`,
  timezone: 'America/New_York',
});

console.log(job.id);          // Job ID
console.log(job.next_run_at); // Next scheduled execution
```

## List jobs

```typescript
const { data: jobs } = await r.jobs.list();

for (const job of jobs) {
  console.log(`${job.name} — ${job.cron} — ${job.status} — last run: ${job.last_run_at}`);
  if (job.last_error) console.log(`  Error: ${job.last_error}`);
}
```

## Pause / resume a job

```typescript
// Pause
await r.jobs.update('job_id', { status: 'paused' });

// Resume
await r.jobs.update('job_id', { status: 'active' });
```

## Update schedule or handler

```typescript
await r.jobs.update('job_id', {
  cron: '0 */6 * * *', // Every 6 hours
  handler_code: `async () => { /* updated logic */ }`,
});
```

## Delete a job

```typescript
await r.jobs.delete('job_id');
```

## Cron expression reference

| Expression  | Schedule                 |
| ----------- | ------------------------ |
| `* * * * *` | Every minute             |
| `0 * * * *` | Every hour               |
| `0 8 * * *` | Every day at 8am         |
| `0 0 * * 1` | Every Monday at midnight |
| `0 0 1 * *` | First day of every month |

> **Note**
>
> Job handlers run in your project's E2B sandbox with a 60-second timeout. They have access to your project's environment variables and database.