Events
The Events resource gives you access to everything that happens in Clockwork as an ordered, immutable log. You can stream events in real time, replay past events for recovery, or subscribe a webhook endpoint to receive push notifications.
When to use client.events
- Building a real-time dashboard that reacts to task completions and delays
- Triggering downstream systems when a workflow reaches a milestone
- Replaying events to rebuild state after an outage
- Auditing workflow history for compliance
Methods
| Method | Description |
|---|---|
list(opts?) | Fetch recent events, optionally filtered |
stream() | Open a real-time SSE stream |
replay(input?) | Replay events from a sequence cursor |
subscribe(input) | Register a webhook endpoint |
listSubscriptions() | List active subscriptions |
unsubscribe(id) | Deactivate a subscription |
events.stream()
Returns an async generator that yields events as they occur. The connection is a Server-Sent Events (SSE) stream.
typescript
for await (const event of client.events.stream()) {
console.log(event.type, event.data, event.ts)
if (event.type === 'task.completed') {
await triggerDownstreamSystem(event.data.taskId)
}
if (event.type === 'workflow.completed') {
await sendCompletionEmail(event.data.instanceId)
}
}Stream event types
| Type | Fired when |
|---|---|
task.created | A task is created |
task.updated | A task is updated |
task.completed | A task is marked complete |
workflow.started | A workflow instance starts |
workflow.completed | All tasks in an instance complete |
workflow.failed | An instance fails |
artifact.created | An artifact is attached |
constraint.violated | A constraint is breached (conflict detected) |
events.subscribe(input)
Registers a webhook endpoint to receive signed POST requests when events occur.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | yes | HTTPS endpoint that will receive events |
events | WebhookEvent[] | yes | List of event types to subscribe to |
typescript
const { data: sub } = await client.events.subscribe({
url: 'https://yourapp.com/webhooks/clockwork',
events: ['task_completed', 'task_delayed', 'conflict_detected', 'workflow_completed'],
})
// Store the secret — it's only shown once
console.log('Webhook secret:', sub.secret)Available webhook events
| Event | Description |
|---|---|
task_ready | A task became ready (all predecessors completed) |
task_completed | A task was marked complete |
task_delayed | A task was delayed |
conflict_detected | A scheduling conflict was detected |
workflow_completed | A workflow instance completed |
* | All events |
Verifying webhook signatures
Every webhook request includes X-Clockwork-Signature: sha256=<hex>. Always verify this before processing:
typescript
import { createHmac, timingSafeEqual } from 'crypto'
function verifyWebhook(signature: string, secret: string, rawBody: string): boolean {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex')
return timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
}
// Express example
app.post('/webhooks/clockwork', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-clockwork-signature'] as string
if (!verifyWebhook(sig, process.env.WEBHOOK_SECRET!, req.body.toString())) {
return res.status(401).send('Invalid signature')
}
const payload = JSON.parse(req.body.toString())
console.log(payload.event, payload.task_id, payload.timestamp)
res.status(200).send('OK')
})events.list(opts?)
Fetches recent events. Newest first.
typescript
const { data: events } = await client.events.list({
workflowInstanceId: 'wi_abc123',
type: 'task.completed',
limit: 50,
})events.replay(input?)
Replays the full event log from a sequence cursor. Useful for rebuilding state after an outage.
typescript
const { data: events } = await client.events.replay({
fromSequence: 0,
limit: 500,
})Type reference
typescript
interface Event {
id: string
sequence: number
projectId: string | null
type: string
subjectType: string | null
subjectId: string | null
payload: Record<string, unknown> | null
correlationId: string | null
createdAt: string
}
interface EventSubscription {
id: string
url: string
events: WebhookEvent[]
isActive: boolean
createdAt: string
secret?: string // Only on creation
}Related
- Guides: Webhooks — complete webhook guide including retries and idempotency
- Guides: Event-Driven Patterns
- Conflicts — conflicts also surface as
conflict_detectedevents