"Audit log"
Tether records who changed what in each organisation and project. Admins and owners can read it from **Organisation settings → Audit log** (every project) or a project's **Settings → Audit log** (that project only).
What's recorded
| Area | Actions |
|---|---|
| Deploys | deploy.functions, deploy.schema |
| Environments | environment.create, environment.delete, environment.update, environment.default.update, environment.export, environment.domains.update, environment.auth_provider.update |
| Keys | environment.key.regenerate, environment.publishable_key.create, environment.publishable_key.revoke, api_key.create, api_key.rotate, api_key.revoke, db_token.create, db_token.revoke |
| Projects | project.create, project.rename, project.settings.update, project.transfer, project.delete |
| Members | member.join, member.leave, member.remove, member.role.update |
| Invites | invite.create, invite.resend, invite.revoke |
| Organisation | organisation.create, organisation.rename, organisation.delete |
| Account | oauth_app.create, oauth_app.update, oauth_app.delete, oauth_app.secret_rotate, oauth.consent, oauth.access_revoke, device.approve, device.deny, session.revoke (in your personal organisation's log) |
| Access | access.denied: a request from a signed-in person or key that its role or scopes didn't allow |
| Configuration | env_var.set, env_var.delete, cron.create, cron.update, cron.delete, cron.trigger, backup.create, backup.delete, backup.restore, backup.download, backup.config.update, bridge.*, rls.*, logs.clear |
| Data | data.table.delete, data.sql (SQL console), data.exec; and data.row.insert, data.row.update, data.row.delete, asset.delete when a person makes the change |
Successful changes are recorded, and so are denied attempts. Ordinary reads, function calls and data written by API keys aren't, so the log stays readable.
Entries are kept for 400 days.
Tamper evidence
Each entry stores a hash that covers the entry and the one before it in the same organisation. Changing or deleting an entry breaks the chain from that point on. Check it with:
GET /api/v1/organisations/{id}/audit/verify
It returns { "intact": true }, or { "intact": false, "firstAlteredEntry": "<id>" }.
Each entry has:
- actor: the person (
user), API key (api_key), OAuth app (oauth_app) or publishable key that made the change - action and target (for example the cron id, table name or invited email address)
- project and environment, where relevant
- details such as the old and new role
- the caller's IP address and the time
Variable values, keys and other secrets are never written to the log.
Filtering
Filter by activity type, who made the change (people, API keys or OAuth apps), project, environment and date range. Entries are newest first; Load older entries pages back through history.
API reference
GET /api/v1/organisations/{id}/audit
GET /api/v1/projects/{id}/audit
Both need the admin or owner role and accept these query parameters:
| Parameter | Meaning |
|---|---|
action |
An exact action, or a prefix ending in . such as environment. |
actorType |
user, api_key, oauth_app or publishable_key |
actorId |
A user id or scoped key id |
projectId |
Organisation log only |
environment |
Environment name |
from, to |
Dates (2026-10-01) or RFC 3339 times; to is exclusive |
before |
Return entries older than this time (use nextBefore from the previous page) |
limit |
1 to 500, default 100 |
{
"entries": [
{
"id": "...",
"projectId": "...",
"environment": "production",
"actor": { "type": "user", "id": "...", "name": "Sam Taylor" },
"action": "deploy.functions",
"target": null,
"createdAt": "2026-10-18T09:12:44.381Z"
}
],
"nextBefore": null
}