Your handler receives one Event per delivery. Branch on event.type and
use the typed accessor — only the accessor matching the event’s type is
non-null.
client.on(async (event) => {
switch (event.type) {
case "webhook.received":
handleWebhook(event.webhook!);
break;
case "email.received":
handleEmail(event.email!);
break;
case "slack.event":
handleSlack(event.slack!);
break;
case "cron.fired":
handleCron(event.cron!);
break;
}
});
Fields
| Attribute | Type | Notes |
|---|---|---|
id | string | ULID. Stable across live + replay. |
type | string | webhook.received, email.received, slack.event, or cron.fired. |
origin | "live" | "replay" | Use for idempotency. |
createdAt | Date | UTC. |
channel | { id, label, type } | Which channel received the event. |
data | Record<string, unknown> | Raw source payload — always populated. |
promptReady | string | LLM-ready text rendering. |
promptReadyVersion | number | Renderer version stamp. |
webhook | WebhookData | null | Populated when type === "webhook.received". |
email | EmailData | null | Populated when type === "email.received". |
slack | SlackData | null | Populated when type === "slack.event". |
cron | CronData | null | Populated when type === "cron.fired". |
WebhookData
event.webhook.method // "POST"
event.webhook.path // "/v1/webhook/…"
event.webhook.headers // Record<string, string>
event.webhook.bodyEncoding // "json" | "text" | "base64"
event.webhook.body // unknown — JSON-decoded when encoding is "json"
event.webhook.bodyRawB64 // string — raw bytes base64-encoded, when "base64"
event.webhook.bodySizeBytes // number
EmailData
event.email.from // string
event.email.to // string[]
event.email.cc // string[]
event.email.bcc // string[]
event.email.subject // string
event.email.text // string
event.email.html // string
event.email.messageId // string — RFC 5322 Message-ID; used for threading
event.email.attachments // Attachment[]
event.email.receivedAt // Date | null
SlackData
event.slack.teamId // string — workspace id
event.slack.teamName // string
event.slack.eventType // "app_mention" | "message" | …
event.slack.eventTs // string — Slack timestamp, also used for threading
event.slack.channelId // string
event.slack.userId // string
event.slack.text // string
event.slack.threadTs // string — set when the message is already in a thread
event.slack.raw // object — full outer Slack event preserved verbatim
CronData
event.cron.scheduleId // string
event.cron.cronExpr // string — e.g. "0 14 * * THU"
event.cron.timezone // string — IANA name
event.cron.scheduledAt // Date — what the schedule asked for
event.cron.firedAt // Date — when the scheduler actually ran
event.cron.payload // Record<string, unknown> — the static JSON
See cron template tokens if your
payload uses {{…}} markers.
Immutability
Event objects are deeply frozen. Safe to share across tasks, safe to cache.
Prompt-ready
event.promptReady is a pre-rendered text string useful when a model is the next hop. Ignore it if you don’t need it. See Prompt-ready.