Skip to main content

SystemEvent

A SystemEvent is an immutable record of a domain event. The system writes one whenever a tracked state change occurs; webhooks are dispatched off this table.

Purpose​

  • Provide an append-only audit log of everything the platform does.
  • Drive webhook delivery (the dispatcher polls/listens on this table).
  • Enable backfill: clients can list events since a timestamp instead of relying only on push.

Schema​

FieldTypeDescription
idUUIDInternal id.
workspace_idUUIDOwning workspace.
inbox_idUUID | nullAssociated inbox, if any.
email_idUUID | nullAssociated email, if any.
slugstringEvent identifier (email.db.created, etc.).
payloadobjectEvent-specific data.
created_at / updated_at / deleted_atdatetime

Current slugs​

Row-level slugs (workspace, inbox, agent, agent_run, webhook, email) are emitted automatically on every create/update of the row; the payload stored here keeps the internal camelCase keys, while webhook deliveries expose them in snake_case inside data (see Webhook).

SlugEmitted whenStored payload
<resource>.db.createdRow inserted{} (+ agentId / runId / webhookId for those resources)
<resource>.db.updatedRow updated (soft delete included){ changedFields: [...] }
email.status_changed / agent_run.status_changedstatus column changed{ status: { from, to } }
agent.version_updatedPrompt version bumped{ agentId, version: { from, to } }
email.rejectedEmail rejected by policy{ reason } — one of recipient_unknown, encoding, spam, virus, recipients, filters, attachments
email.agent.processedAgent run finished{ runId, totalCost, costLimitBreached, workflowRunId }
workflow.run.succeededEvery step of an agent workflow completed{ workflowRunId, runId, stepsTotal, stepsSucceeded, durationMs }
workflow.run.failedAn agent workflow finished with at least one failed step{ workflowRunId, runId, stepsTotal, stepsSucceeded, durationMs, failedStep, failedSteps, error }
workspace.cost_limit_breachedWorkspace went past its monthly cost limit{ runId, emailId, totalCost }
webhook.delivery.failedA delivery exhausted its retries{ webhookId, originalEventId }
webhook.ping/webhooks/{id}/test invoked{ webhookId, ts }

New slugs may be added without notice. Consumers should ignore unknown slugs gracefully.

Example​

{
"id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"workspace_id": "a8b2c1d4-9e7f-4a3b-8c5d-1f2e3a4b5c6d",
"inbox_id": "b3c4d5e6-7a89-4b0c-9d1e-2f3a4b5c6d7e",
"email_id": "e5f6a7b8-9c0d-4e1f-2a3b-4c5d6e7f8a9b",
"slug": "email.db.created",
"payload": {
"email_id": "e5f6a7b8-9c0d-4e1f-2a3b-4c5d6e7f8a9b",
"message_id": "01HZ9X8K4N0P2Q5R7S9T1V3W5X",
"inbox_id": "b3c4d5e6-7a89-4b0c-9d1e-2f3a4b5c6d7e"
},
"created_at": "2026-05-17T10:00:14.130Z",
"updated_at": "2026-05-17T10:00:14.130Z",
"deleted_at": null
}

Reading​

MethodPath
GET/system-events?slug=email.agent.processed&created_at[gte]=…
GET/system-events/{id}

Filters: slug, inbox_id, email_id, created_at[gte|lt]. Default sort -created_at.

Retention​

SystemEvent rows are retained for 365 days. Older rows are archived to S3 (Glacier) by a daily cron. Archived events are not exposed through the API.