---
title: "Rocket Chat Scheduler API Guide"
slug: "scheduler-api"
description: "Use the Scheduler API in Rocket Chat Apps-Engine. Automate secure tasks and enhance collaboration workflows."
updated: 2026-02-27T05:34:33Z
published: 2026-02-27T05:34:33Z
---

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

# Scheduler API

The Scheduler API allows apps to create tasks that run in a defined schedule. These tasks can be one-time events or recurring tasks. It uses [agenda.js](https://github.com/agenda/agenda) as the backend, so the [schedule syntax](https://github.com/agenda/human-interval) and internal processes are all according to its documentation.

The API details are in the [Module scheduler](https://rocketchat.github.io/Rocket.Chat.Apps-engine/modules/scheduler.html) definition and this [example app](https://github.com/RocketChat/Apps.RocketChat.Tester/tree/scheduler) can also be used as a guide. Check your app logs to see the example in action.

## Add permissions

As per the [permission system](/v1/docs/app-permission-system), the scheduler API needs the following permission in your app's manifest (`app.json` file):

```json
{
  "permissions": [
    { "name": "scheduler" }
  ]
}
```

## Register jobs (processors)

To use the scheduler API, you'll need two things:

- The functions to be run as jobs (we call them `processors`).
- The schedule in which they run.

This is configured using the app's `extendConfiguration` method. The processors are registered during the app's startup to make them available for scheduling. Refer to the following code snippet:

```typescript
import { IConfigurationExtend } from '@rocket.chat/apps-engine/definition/accessors';
import { IJobContext } from '@rocket.chat/apps-engine/definition/scheduler';
import { App } from '@rocket.chat/apps-engine/definition/App';

export class MyApp extends App {
    public async extendConfiguration(configuration: IConfigurationExtend): Promise<void> {
        configuration.scheduler.registerProcessors([
            {
                id: 'first',
                // NOTE: Use a method reference — do NOT use an arrow function or .bind(this)
                processor: this.myProcessor,
            },
        ]);
    }

    private async myProcessor(jobData: IJobContext): Promise<void> {
        this.getLogger().info(`[${ new Date() }] this is a task`, jobData);
    }
}
```

The `processor` is an `async` function and can receive arguments (`jobData`). The arguments are passed during scheduling.

> [!WARNING]
> Processor functions are commonly registered as arrow functions. For example,
> 
> ```typescript
> processor: async (jobData) => this.getLogger().info(`[${ Date() }] this is a task`, jobData)
> ```
> 
> But this poses a challenge for us to inject the correct app reference to its execution. Arrow functions lexically bind `this` at definition time, which prevents the runtime from injecting the correct request-scoped app proxy during execution. It is recommended that you follow the code examples used in this document. For further details on logging, refer to the [**App Logs**](/v1/docs/app-logs) document.

## Start a job

To trigger the registered processor as a job, you must provide:

- The `id` of the processor.
- The type of job it will be. The available types are `scheduleRecurring` (the job runs in an `interval`) and `scheduleOnce` (the job runs once using the `when` keyword).

Starting a job can be done when running a slash command, for example:

```typescript
// slashcommand class
public async executor(context: SlashCommandContext, read: IRead, modify: IModify): Promise<void> {
    // SCHEDULING A RECURRING TASK
    const task = {
        id: 'first',
        interval: '10 seconds',
        data: { test: true },
    };
    await modify.getScheduler().scheduleRecurring(task);

    // SCHEDULING ONETIME TASK
    const task = {
        id: 'first',
        when: '8 seconds',
    };
    await modify.getScheduler().scheduleOnce(task);
}
```

You can also trigger a job as soon as it gets registered without manual or automated triggering. When you register your processor in the `extendConfiguration` method, you can pass a prop called `startupSetting` in the processor's object, as follows:

```typescript
import { IConfigurationExtend } from '@rocket.chat/apps-engine/definition/accessors';
import { IJobContext, StartupType } from '@rocket.chat/apps-engine/definition/scheduler';
import { App } from '@rocket.chat/apps-engine/definition/App';

export class MyApp extends App {
    public async extendConfiguration(configuration: IConfigurationExtend): Promise<void> {
        configuration.scheduler.registerProcessors([
            {
                id: 'first',
                // Using a method reference
                processor: this.firstProcessor,
                startupSetting: {
                    type: StartupType.ONETIME,
                    when: '20 seconds',
                    data: { test: true },
                },
            },
            {
                id: 'second',
                // Using a method reference
                processor: this.secondProcessor,
                startupSetting: {
                    type: StartupType.RECURRING,
                    interval: '20 seconds',
                },
            },
        ]);
    }

    private async firstProcessor(jobData: IJobContext): Promise<void> {
        this.getLogger().info(`[${ new Date() }] first processor ran`, jobData);
    }

    private async secondProcessor(jobData: IJobContext): Promise<void> {
        this.getLogger().info(`[${ new Date() }] second processor ran`, jobData);
    }
}
```

This indicates that you want that particular processor to be scheduled as soon as it is registered. You can define the "immediate scheduling" as a recurring job ( `StartupType.RECURRING`) or a one-time job ( `StartupType.ONETIME`). You can also pass data using the `data` object. It will work just like when you schedule a task using the `modify` accessor.

Here, `data` is not something that's passed to the processor or a function as a living object or executable code. This `data` is a static piece of data that is passed to the processor's first argument.

The signature of the processor function is as follows:

```typescript
(jobContext: IJobContext, read: IRead, modify: IModify, http: IHttp, persis: IPersistence) => Promise<void>
```

The first argument is the data object you're passing when actually scheduling the job; ( `[k: string]:any`). The rest of the arguments are passed when the function is run.

## Cancel a job

To stop a job, all you have to do is pass the ID of the job you want to stop:

```typescript
const jobId = 'first';
await modify.getScheduler().cancelJob(jobId);
```

It will stop the running job (if any).

## Cancel all jobs from the app

To stop all the current running jobs from the app:

```typescript
await modify.getScheduler().cancelAllJobs();
```
