Quick Start: Pull (Worker)
Your worker long-polls Chronos for jobs, runs your handler, and reports the result. You control the compute.
Prerequisites
Section titled “Prerequisites”- Node.js 20 or later
@chronos.sh/sdk0.2.0 or later for the Node.js tabs (installed in step 1)- Go 1.26 or later for the Go tabs
- A Chronos account (sign up free)
- An API key (create one in the dashboard under Settings → API Keys)
-
Install the SDK
Terminal window pnpm add @chronos.sh/sdkTerminal window npm install @chronos.sh/sdkTerminal window yarn add @chronos.sh/sdk -
Write your handler
worker.mts import { Chronos } from '@chronos.sh/sdk';const chronos = new Chronos({apiKey: process.env.CHRONOS_API_KEY!,});chronos.worker.handle('hello', async (ctx) => {console.log(`Job ${ctx.jobId} running (attempt ${ctx.attempt})`);return { ok: true };});await chronos.worker.start();The handler name
"hello"is the routing key. Chronos uses it to match jobs to the right function. The.mtsextension makes tsx run the file as an ES module, which top-levelawaitneeds. -
Start the worker
Terminal window CHRONOS_API_KEY=chrns_your_api_key pnpm dlx tsx worker.mtsTerminal window CHRONOS_API_KEY=chrns_your_api_key npx tsx worker.mtsTerminal window CHRONOS_API_KEY=chrns_your_api_key yarn dlx tsx worker.mtsThe worker connects to Chronos and waits for jobs.
-
Create a job
In a second terminal, create a one-off job:
Terminal window curl -X POST https://api.chronos.sh/v1/jobs \-H "Authorization: Bearer chrns_your_api_key" \-H "Content-Type: application/json" \-d '{"name": "My first job","handler": "hello"}'create-job.mts import { Chronos } from '@chronos.sh/sdk';const chronos = new Chronos({ apiKey: process.env.CHRONOS_API_KEY! });await chronos.jobs.create({ name: 'My first job', handler: 'hello' });Run it with the command from step 3, replacing
worker.mtswithcreate-job.mts.create-job.go package mainimport ("context""log""os"chronos "chronos.sh/go")func main() {client, err := chronos.NewClient(os.Getenv("CHRONOS_API_KEY"))if err != nil {log.Fatal(err)}_, err = client.Jobs.Create(context.Background(), chronos.JobCreateParams{Name: "My first job",Handler: new("hello"),})if err != nil {log.Fatal(err)}}Terminal window go mod init hello && go get chronos.sh/goCHRONOS_API_KEY=chrns_your_api_key go run create-job.goYour running worker claims the job and runs the handler. You should see:
Job a8f3e2b1-... running (attempt 1)
What just happened
Section titled “What just happened”- You created a one-off job via the API
- Your worker long-polled Chronos and claimed it
- The handler ran and returned a result
- Chronos recorded the execution as
completed
If the handler had thrown an error, Chronos would have retried up to 3 times with exponential backoff.
Make it recurring
Section titled “Make it recurring”Create a schedule and your worker picks up jobs automatically:
curl -X POST https://api.chronos.sh/v1/schedules \ -H "Authorization: Bearer chrns_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Hello every 10 minutes", "handler": "hello", "interval": { "value": 10, "unit": "minute" } }'import { Chronos } from '@chronos.sh/sdk';
const chronos = new Chronos({ apiKey: process.env.CHRONOS_API_KEY! });
const schedule = await chronos.schedules.create({ name: 'Hello every 10 minutes', handler: 'hello', interval: { value: 10, unit: 'minute' },});console.log(schedule.id);Run it with the command from step 3, replacing worker.mts with create-schedule.mts. It prints the schedule id.
package main
import ( "context" "fmt" "log" "os"
chronos "chronos.sh/go")
func main() { client, err := chronos.NewClient(os.Getenv("CHRONOS_API_KEY")) if err != nil { log.Fatal(err) } schedule, err := client.Schedules.Create(context.Background(), chronos.ScheduleCreateParams{ Name: "Hello every 10 minutes", Handler: new("hello"), Interval: &chronos.Interval{Value: 10, Unit: chronos.IntervalUnitMinute}, }) if err != nil { log.Fatal(err) } fmt.Println(schedule.ID)}CHRONOS_API_KEY=chrns_your_api_key go run create-schedule.goYour running worker now receives a new job every 10 minutes. To stop it, archive the schedule:
curl -X POST https://api.chronos.sh/v1/schedules/SCHEDULE_ID/archive \ -H "Authorization: Bearer chrns_your_api_key"import { Chronos } from '@chronos.sh/sdk';
const chronos = new Chronos({ apiKey: process.env.CHRONOS_API_KEY! });
await chronos.schedules.archive(process.argv[2]);Run it like create-schedule.mts, with the schedule id as the last argument.
package main
import ( "context" "log" "os"
chronos "chronos.sh/go")
func main() { client, err := chronos.NewClient(os.Getenv("CHRONOS_API_KEY")) if err != nil { log.Fatal(err) } if _, err := client.Schedules.Archive(context.Background(), os.Args[1]); err != nil { log.Fatal(err) }}CHRONOS_API_KEY=chrns_your_api_key go run archive-schedule.go SCHEDULE_ID