Workspace Events
A unified, cross-project activity feed for your workspace — builds, changes, tasks, approvals, and deployments across every project in your account, in one newest-first stream.
Table of contents
Plan requirement
Multi-project observability is available on the Team plan and up (Team, Studio, Enterprise). Requests from accounts on other plans receive 403 Forbidden:
{
"error": "Multi-project observability requires a Team plan or higher. If you belong to a Team workspace, pass ?account_id=<account id> — this endpoint defaults to your personal account.",
"upgrade_url": "https://butterstack.com/pricing"
}
Note the account_id hint: API tokens belong to your user, and without account_id the endpoint resolves to your default (usually personal) account. If your Team-plan workspace is a separate account, pass its id explicitly.
Endpoint
GET /api/v1/workspace/events
Authenticate with an API token via the Authorization header — see Authentication.
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
"https://butterstack.com/api/v1/workspace/events?limit=20"
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 20 | Events per page. Clamped to 1–50. |
days_back | integer | 7 | How far back to look. Clamped to 1–90. |
cursor | string | — | Opaque pagination cursor. Pass back pagination.next_cursor verbatim; malformed cursors return 400. |
account_id | string | your default account | Which of your accounts to read (acct_… prefix id or numeric id). Must be an account you belong to — anything else returns 404. |
Response
{
"events": [
{
"event_type": "build_run.failed",
"project_id": 42,
"project_name": "Thrive",
"actor": "Ada Lovelace",
"timestamp": "2026-07-01T14:03:22.000Z",
"target_ref": "812",
"status": "err",
"message": "Build #812 failed",
"url": "/projects/42/build_runs/…",
"cursor_key": "2026-07-01T14:03:22.000000Z|build|9137"
}
],
"rollup": {
"changes_24h": 12,
"builds_passed_24h": 8,
"builds_failed_24h": 1,
"open_tasks": 23,
"total_projects": 3,
"active_projects": 2
},
"pagination": {
"limit": 20,
"has_more": true,
"next_cursor": "2026-07-01T09:41:07.512340Z|task|58821"
}
}
status is a pill kind for rendering: ok, err, info, warn, or neutral.
Event types
event_type | Source | Notes |
|---|---|---|
build_run.completed | Build runs | Includes builds that passed pending approval. |
build_run.failed | Build runs | |
change.submitted | Asset events | Asset created/updated by a connected tool (Perforce, Jira, …). |
task.state_changed | Tasks | Approximation: emitted from the task’s last update time, so any edit to a task (title, assignee) within the window re-surfaces it stamped with the edit time — not only genuine state transitions. |
approval.requested | Asset approvals | Pending approvals. |
approval.granted | Asset approvals | |
approval.denied | Asset approvals | |
approval.ignored | Asset approvals | Approval dismissed without a decision. |
deployment.created | Deployments | Steam, Epic Games Store, app stores, custom. |
Pagination
Cursor-based and stable under continuous insertion:
- Request page 1 (no
cursor). The response includesrollupand, when more events exist,pagination.next_cursor. - Request the next page with
?cursor=<next_cursor>. Cursor pages return"rollup": null— the rollup is page-independent, so it is only computed on the first page. - Stop when
has_moreisfalse(next_cursorwill benull).
Treat cursors as opaque strings; their format may change.
Errors
| Status | Meaning |
|---|---|
400 Bad Request | Malformed cursor. |
401 Unauthorized | Missing or invalid API token. |
403 Forbidden | The account’s plan does not include multi-project observability (see Plan requirement). |
404 Not Found | account_id is not an account you belong to. |