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

# Scheduler and webhooks: cron, timers, and event ingestion

> How Vendo drives UTC cron schedules and duration timers, ingests host events, and verifies external webhook triggers for the automations block.

## Schedules

Long-lived hosts can call `automations.start()`. Serverless hosts schedule:

```http theme={null}
POST /api/vendo/tick
Authorization: Bearer <secret>
```

Schedules support exactly one of a five-field `cron`, a duration such as
`15m`, or a one-shot UTC timestamp. Cron evaluates in UTC. If the host misses a
window, the next tick fires once and never back-fills.

## Host events

Emit from the host code path that owns the event:

```ts theme={null}
await vendo.emit("invoice.paid", invoice, principal);
```

This runs enabled automations for that principal whose host-event name matches.

## External deliveries

Mount `POST /webhooks/:source`. Connector sources use their own signature
scheme. Self-minted sources sign HMAC-SHA256 over
`id.timestamp.rawBody`, place signature, timestamp, and delivery id in headers,
and accept only a five-minute clock window.

Vendo rejects unverified deliveries before principal resolution or dispatch.
Delivery ids are deduplicated, so at-least-once retries do not double-run an
automation. Secrets never travel in the URL.

## Stopping a run

Cancel an in-flight automation run when a schedule fires against stale state,
an agent is looping on a bad plan, or a user asks to abort. Post to the run
under its owning principal:

```http theme={null}
POST /api/vendo/runs/:id/stop
Content-Type: application/json
```

The engine signals cancellation cooperatively: the current step finishes,
outstanding tool calls are drained, and the run transitions to a cancelled
terminal state. Parked approvals attached to the run are dropped rather than
resumed. Stopping a run that has already reached a terminal state is a no-op
and returns 200.

Cancellation is idempotent and audit-logged. The engine uses the store's
atomic compare-and-set primitive on the run record, so concurrent stop
requests and scheduler ticks cannot race a run into a resurrected state.
