Skip to main content
Every change to a record is a revision. Revisions are numbered per record from 1, numbers are never reused, and the current one is the record’s revision (and its ETag). Changes add revisions and never edit old ones: only redaction, the plan’s retention and purges of deleted data remove anything from history. In the web app, open a record’s History tab. Through the API, reading history needs records:read, and reverting records:write (and records:read to preview a revert).

What a revision records

Each revision has:
  • operation: create, update, publish, unpublish, delete, restore, revert, migrate or merge
  • actor: the person or API key that made the change (type is user, api_key or system), with its name
  • via: the client it came through: ui, api, cli, sdk, mcp, system or scheduler
  • note: the change note, if one was sent
  • changed_fields: the keys of the fields (and published_at or deleted_at) it changed
  • draft: for a merge, the draft it merged, with who started it and who edited it
  • reverted_to_revision: for a revert, the revision it went back to
A single revision also has data, the record’s values as of that revision, and changes, each with before and after. Changes name a field by its current key and its stable field_id, so history stays readable after a field is renamed.

List and read revisions

Lists are newest first. Filter by operation, by actor_id (a usr_ or key_ ID) or by a created_at range:
Webhooks and the activity log name a revision by its rev_ ID (revision_id); GET /v1/revisions/{revision_id} reads it. History stays readable while a record is deleted.

Compare two revisions

GET /v1/records/{record_id}/diff?from=3&to=7 returns the changes between any two revisions, field values and published_at alike. In the web app, open a revision and pick Compare with #7.

Revert

Reverting writes a new revert revision with an earlier revision’s values; nothing in between is lost. In the web app, open a revision, choose Revert to this revision, check the changes and choose Revert record. Through the API, preview first with dry_run, which writes nothing:
The old values are mapped onto the current schema:
  • A field whose type changed since gets its old value converted, as a field migration would. A value that can’t be converted fails the revert (422), and a field whose old and new types have no conversion keeps its current value.
  • Fields added since, and fields whose old value was redacted, keep their current values. Deleted fields don’t come back.
  • The result is validated like any update, and whether the record is published doesn’t change. Reverting a live record changes what is live.
A deleted record must be restored before it can be reverted (409). Send If-Match to revert only if nobody changed the record since you looked. To review an old version before it goes live, start a draft from it with from_revision instead.

Change notes and attribution

Every change is attributed to the person or API key that made it. Give each tool, agent and CI job a key of its own, so history tells them apart. To say why, send Nohead-Change-Note when you create, update, publish, unpublish, delete, restore or revert a record, change records in a batch, merge a draft, or change a schema (fields, collections, field migrations). The note is percent-encoded UTF-8, as encodeURIComponent encodes it, at most 500 characters once decoded; plain ASCII can be sent as it is.
The SDKs encode it for you:
The SDKs also name themselves in Nohead-Client, so their changes show via: sdk. Changes made by a schedule show actor.type: system and via: scheduler. The MCP server requires a note on every revision it makes.

Redact a field’s past values

When a value should never have been stored, such as personal data or a secret, owners and admins can remove it from history in the web app. On the record’s History tab, choose Redact…, pick the Field and the Values to remove (every past value, or the value set in one revision), check the preview, type the field’s key and choose Redact permanently.
Redaction can’t be undone.
  • Each removed value reads {"$redacted": true} wherever it appears in revision snapshots and changes, and those revisions list the field in redacted_fields.
  • Copies in stored webhook payloads are removed too.
  • The current value is never touched. If it is the problem, change the record first, then redact.
  • Reverting to a redacted revision keeps the field’s current value.
  • Redactions are recorded in the activity log, and sent to webhooks, as record.redacted.
Redaction is not part of the API: API keys can’t redact.

How long history is kept

How long revisions are kept depends on the organization’s plan. Once a day, older revisions are removed, but every record keeps its first revision and its last 10. A record’s history_pruned_through is the highest revision number removed (null while nothing was), and the History tab says which revisions were removed. For 30 days after a move to a plan that keeps less, nothing is removed.
History doesn’t outlive deletion: when a deleted record is purged, its revisions go with it, and when a deleted field is purged, its values are removed from every revision.
Published-only API keys can’t read history (403), since it holds unpublished content.

Activity log

Revisions hold what a record’s content was. The activity log holds everything else that changed in the organization, and who changed it, through what: every record, draft, schema, asset, webhook, API key and search token change in its projects, and changes to the projects, the organization, its members, invitations and plan. Each event names its type (such as record.published or member.role_changed), its actor and its via, with small references such as a revision_id, but never content. Reads aren’t recorded. Admins and owners read it on the organization’s Activity page. Filter it by project, by what changed (Show: Records, Drafts, Schema, Members and so on) and by Who: a member, All API keys or System; choosing a name in the list shows only their activity. Client shows what each change came through: Web app, API, CLI, SDK, MCP, System or Scheduler. A record’s or collection’s event links to it. An API key with Read the activity log (audit:read) reads its own project’s events with GET /v1/projects/{project_id}/audit-events, newest first. Filter by type, exactly or by prefix (filter[type]=record.*), by resource_type and resource_id, by actor_type and actor_id, and by a created_at range. $PROJECT_ID is your key’s project: GET /v1/me returns it as api_key.project_id.
Only admins and owners can create a key with this scope, and published-only keys can’t have it. Events about the organization itself, such as members and billing, are on the Activity page only. Webhooks get many of the same events, with the same types, as they happen. How long the activity log is kept depends on the organization’s plan; older events are removed once a day. As with history, nothing is removed for 30 days after a move to a plan that keeps less. Every endpoint is in the API reference.