Account/Activity

Account activity

Every mutating action on an account is recorded with the person who did it, what it touched, and when. The dashboard shows the feed under Account → Activity; the same data is available at GET /v1/account/events.

This is the record for questions like who deleted that Cell and when did that vault key change — and, on a shared account, which of us did it.


What is recorded

Action Written when
member.invited Someone is invited to the account
member.invite_revoked An open invite is withdrawn
member.joined An invite is accepted and the person joins
member.role_changed A member moves between admin and member
member.removed A member is removed, or leaves
cell.deploy.create A Cell is deployed for the first time
cell.deploy.update An existing Cell is redeployed
cell.delete A Cell is deleted
vault.set A vault secret is set or replaced
vault.delete A vault secret is deleted
gate.link.created A gate capability link is minted
gate.link.revoked A capability link is revoked
gate.session.revoked A gate viewer session is revoked
vesicle.capture.reveal A vesicle capture body is read in full
billing.entitlements The account's entitlements change
account.closed A closure is scheduled
account.close_cancelled A scheduled closure is cancelled
account.purged A closure completes and the account is destroyed

Gate sign-ins are not in the feed: one row per visitor sign-in on a gated Cell would drown everything else. Per-request traffic is a different thing entirely and lives in analytics and the access log.


Retention

The feed holds 30 days. Records older than that are deleted by a background prune, from the feed and from the store behind it. There is no longer-lived copy to ask for, so export anything you need to keep — see exporting your data, whose events block carries up to 1000 rows from the same 30-day window.


Reading it over the API

curl -H "Authorization: Bearer $TISSUE_TOKEN" \
  "https://api.tissue.systems/v1/account/events?limit=50"
{
  "events": [
    {
      "action": "cell.deploy.update",
      "actor_email": "ada@example.com",
      "target": "my-api",
      "detail": "{\"kind\":\"js\"}",
      "created_at": 1754870400
    }
  ],
  "next_before": 1754870399
}
Parameter Meaning
limit Rows per page, 1–500. Default 50
before Keyset cursor in unix seconds, exclusive. Pass the previous response's next_before
action Exact action string from the table above

Paging walks backwards in time: request a page, then pass its next_before as before for the next one. next_before is null when the window is exhausted. The cursor is a timestamp rather than a row id because row ids are platform-wide — an id cursor would tell one account how much every other account writes.

Five fields come back per row and no more: action, actor_email, target, detail, created_at. target is the name of the thing acted on, which for deploys, gate changes and vault changes is the Cell name and for member.* rows is the other person's email address; detail is a small JSON document carried as a string, or null. A member.removed row carries {"role":…,"self":…}, where self is true when someone left on their own rather than being removed by an administrator. A vault event names the Cell, never the key's value. Source IP, server, and internal row ids stay inside the platform. An action taken by the platform itself reports actor_email as system.

An action value that is not in the table returns an empty page, not an error. The list of visible actions is fixed, and answering differently for an unlisted one would make the endpoint a way to discover the operator-only actions that exist.

The endpoint needs the events:read scope. A session holds it at every role; an API token needs it granted explicitly.


See also