MonkeyTasks

A durable task scheduler with recurring schedules, webhook authentication, and instant status tracking. Define tasks with execution config and cron schedules, fire them on-demand or let the scheduler handle it, and track every run.

Concepts

ConceptDescription
TaskA named definition that owns its webhook config, schedules, and execution settings. Create once, run many times.
TaskRunA single execution of a task. Created by a schedule firing, an on-demand run, or a retry.
ScheduleA cron expression on a task. When it fires, MonkeyTasks automatically creates a new run.

Quick Start

typescript
// Create a task
const task = await monkey.tasks.create({
  name: 'weekly-report',
  execution: {
    url: 'https://api.myapp.com/hooks/report',
    auth: { type: 'hmac', secret: 'whsec_abc123...' },
    payload: { reportType: 'weekly' },
    timeout: 60,
    maxRetries: 3,
  },
  schedules: [
    { title: 'Every Monday at 9am', cron: '0 9 * * MON', timezone: 'America/New_York' },
  ],
})

// Fire immediately
const run = await task.runNow()

console.log(run.id)     // "run_01JDXYZ..."
console.log(run.status) // "queued"

Task Management

typescript
// List all tasks
const tasks = await monkey.tasks.list()

// Filter by group, status, or tag
const reporting = await monkey.tasks.list({ group: 'reporting' })
const paused = await monkey.tasks.list({ status: 'paused' })

// Look up by ID or name
const task = await monkey.tasks.lookup('weekly-report')

// Update
await monkey.tasks.update('weekly-report', {
  description: 'Updated description',
  execution: { timeout: 120 },
})

// Pause / resume all schedules
await task.pause()
await task.resume()

// Remove (cancels pending runs)
await monkey.tasks.remove('weekly-report')

Run Tasks

With delay

Delays accept seconds, duration strings, or absolute timestamps.

typescript
// Seconds
await task.runNow({ delay: 300 })

// Duration string — supports 's', 'm', 'h', 'd'
await task.runNow({ delay: '30m' })

// Absolute timestamp (prefix with @)
await task.runNow({ delay: '@2026-03-20T09:00:00Z' })
Note: Delays under 15 minutes use SQS native delay. Longer delays are persisted and enqueued when the time arrives.

With custom payload

typescript
// Override the default payload for this run
await task.runNow({ payload: { userId: '123', format: 'csv' } })

Batch run

Run up to 10 tasks in a single call.

typescript
const runs = await task.runBatch([
  { payload: { userId: '1' } },
  { payload: { userId: '2' } },
  { payload: { userId: '3' } },
])

Schedules (Cron)

Schedules are defined directly on the task. When a schedule fires, MonkeyTasks creates a run using the task's execution config.

typescript
// Create a task with schedules
const task = await monkey.tasks.create({
  name: 'daily-report',
  schedules: [
    { title: 'Every weekday at 9am', cron: '0 9 * * MON-FRI', timezone: 'America/New_York' },
    { title: 'Sunday recap', cron: '0 18 * * SUN' },
  ],
  execution: {
    url: 'https://api.myapp.com/hooks/report',
    allowOverlap: false,
  },
})

// Update schedules via task update
await monkey.tasks.update('daily-report', {
  schedules: [
    { title: 'Every weekday at 10am', cron: '0 10 * * MON-FRI', timezone: 'America/New_York' },
  ],
})

// Pause all schedules
await task.pause()

// Resume
await task.resume()

Cron format

Standard 5-field cron with optional timezone (defaults to UTC). Minimum interval is 1 minute.

ExpressionMeaning
0 9 * * MONEvery Monday at 9am
*/15 * * * *Every 15 minutes
0 0 1 * *First day of every month at midnight

Run Lifecycle

scheduledqueuedprocessingcompleted
failed(retry up to maxRetries)dead_letter
any statecancelled

Run History

typescript
// List recent runs
const history = await task.listHistory(25)

// Filter by status
const failures = await task.listHistory(50, { status: 'failed' })

// Get a specific run
const run = await task.getRun('run_01JDXYZ...')
// {
//   id: 'run_01JDXYZ...',
//   taskId: 'task_abc...',
//   taskName: 'weekly-report',
//   trigger: 'schedule',
//   scheduleTitle: 'Every Monday at 9am',
//   status: 'completed',
//   result: { statusCode: 200 },
//   startedAt: 1710345601000,
//   completedAt: 1710345603000,
// }

// Cancel a pending run
await task.cancel('run_01JDXYZ...')

// Retry a dead-lettered run
await task.retry('run_01JDXYZ...')

Webhook Authentication

Three auth modes, configured in the task's execution block.

ModeHeader sent
HMAC (recommended)X-MonkeyHub-Signature: sha256=<HMAC-SHA256(timestamp.body, secret)>
Bearer tokenAuthorization: Bearer <token>
Custom header<name>: <value>

Verifying webhooks

typescript
import { verifyWebhook } from '@monkeyhub/sdk'

const isValid = verifyWebhook({
  signature: req.headers['x-monkeyhub-signature'],
  timestamp: req.headers['x-monkeyhub-timestamp'],
  body: req.body,
  secret: process.env.MONKEYHUB_WEBHOOK_SECRET,
})

API Routes

MethodRouteDescription
POST/api/tasksCreate a task
GET/api/tasksList tasks
GET/api/tasks/:idOrNameGet a task by ID or name
PUT/api/tasks/:idOrNameUpdate a task
DELETE/api/tasks/:idOrNameRemove a task
POST/api/tasks/:idOrName/pausePause task
POST/api/tasks/:idOrName/resumeResume task
POST/api/tasks/:idOrName/runFire a run
POST/api/tasks/:idOrName/run/batchFire a batch (max 10)
GET/api/tasks/:idOrName/runsList runs
GET/api/tasks/:idOrName/runs/:runIdGet a specific run
POST/api/tasks/:idOrName/runs/:runId/cancelCancel a run
POST/api/tasks/:idOrName/runs/:runId/retryRetry a dead-letter run
POST/api/tasks/:idOrName/auth/rotateRotate webhook auth

Limits

Baby MonkeyChimpMandrillSilverback
Tasks/sec51050500
Max batch run10101010
Max retries10101010
Webhook timeout300s300s300s300s
Run retention (terminal)30 days30 days30 days30 days
Min cron interval1 min1 min1 min1 min