Coordinator
@scrape-admin/coordinator is a lightweight, multi-tenant service for scheduling webhook callbacks on a cron
expression and retrying them reliably, rather than relying on each client (such as Web) to
implement its own scheduling and retry logic.
It integrates with Scrape Admin's web app: a collection entry's destinations can be scheduled with the coordinator so
the entry is refreshed on its cronExpression, with the coordinator calling back into the web app (or any other
client) to run the actual work.
Authentication
Every request must send an x-tenant-id header identifying the caller. All scheduled webhooks and runs are scoped to
that tenant — a tenant can only read or modify its own data.
API
All endpoints are under /api/v1/webhooks/scheduled:
| Method | Path | Description |
|---|---|---|
GET | / | List scheduled webhooks for the tenant. |
POST | / | Create a scheduled webhook. |
GET | /:id | Get a scheduled webhook. |
PATCH | /:id | Update a scheduled webhook (reschedules it). |
DELETE | /:id | Mark a scheduled webhook for deletion. |
GET | /:id/runs | List runs for a scheduled webhook. |
POST | /:id/runs | Manually trigger a run, outside its cron schedule. |
GET | /:id/runs/:runId | Get a single run. |
POST | /rebuild | Rebuild all of the tenant's schedules (for example, after a deploy). |
A scheduled webhook has one or more destinations (see Schema's zWebhookDestination), an
optional payload, and a cronExpression. Each run creates one attempt per destination and retries failed attempts
up to maxAttempts times with the statuses pending, running, retrying, completed, and failed.
Typed client
@scrape-admin/coordinator-sdk wraps the API in a typed client for use from other apps — see
Coordinator SDK for the full usage guide:
import { createCoordinatorClient } from '@scrape-admin/coordinator-sdk'
const coordinator = createCoordinatorClient({
baseUrl: 'http://localhost:3001',
tenantId: 'my-tenant',
})
const webhook = await coordinator.scheduledWebhooks.create({
destinations: [{ url: 'https://example.com/hooks/scrape-complete' }],
cronExpression: '*/5 * * * *',
})
await coordinator.scheduledWebhooks.runs(webhook.id).trigger()
For running the app locally or with Docker, see the coordinator README.