> ## Documentation Index
> Fetch the complete documentation index at: https://developers.fibery.com/llms.txt
> Use this file to discover all available pages before exploring further.

# History

> Learn how to read Entity change history using the Fibery API.

Use the History API to access a full, paginated log of every change made in your Fibery workspace. Common use cases include:

* Building custom audit trails and compliance reports
* Generating activity digests or changelogs ("what changed this week?")
* Debugging automation behavior by inspecting what triggered a change
* Powering external change-notification workflows

<Callout icon="circle-exclamation" color="#fba32f">
  This API does **not** include changes to Documents content (rich text fields).
</Callout>

## POST `/api/history/v2/search`

Returns a paginated list of workspace history entries matching the given filters.

### Request body

#### **Parameters**

| Parameter                 | Required | Description                                                                                                                           |
| ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `where`                   | No       | Array of filter objects. All filters are combined with logical `AND`. Pass `[]` for no filters.                                       |
| `timeframe`               | No       | Date range to search. Maximum span is **1 year**. If omitted, defaults to last 30 days. Values are ISO 8601 datetime strings in UTC.  |
| `limit`                   | Yes      | Number of items per page. The API may return fewer items than requested even when more pages exist — always check `nextPage.hasNext`. |
| `excludeAutomaticChanges` | No       | Specifies which types of automatic changes to exclude from processing.                                                                |
| `sinceItem`               | No       | ID of the last item from the previous page. Pass this to retrieve the next page.                                                      |

#### **Sample request**

```json theme={null}
{
  "where": [
    {
      "field": "typeId",
      "operator": "=",
      "value": "{database-uuid}"
    },
    {
      "field": "action",
      "operator": "in",
      "value": [
        "fibery.entity/create",
        "fibery.entity/delete"
      ]
    }
  ],
  "timeframe": {
    "start": "{start-datetime}",
    "end": "{end-datetime}"
  },
  "excludeAutomaticChanges": [
    "automations",
    "integrations",
    "formulas",
    "auto-linking"
  ],
  "limit": 50,
  "sinceItem": "{since-item-id}"
}
```

### Filters (`where`)

| Field            | Description                                                             | Operators                    | Value                                                              |
| ---------------- | ----------------------------------------------------------------------- | ---------------------------- | ------------------------------------------------------------------ |
| `id`             | History entry ID                                                        | `=` `in`                     | Number                                                             |
| `action`         | Kind of change performed                                                | `=` `in`                     | See action values below                                            |
| `entityPublicId` | Entity short public ID                                                  | `=` `in`                     | String                                                             |
| `entityState`    | Current state of the entity                                             | `=` `in`                     | `EXIST` `DELETED` `ARCHIVED`                                       |
| `author`         | User who made the change                                                | `=` `in` `empty` `not-empty` | User UUID. For `empty`/`not-empty`, omit the `value` key entirely. |
| `typeId`         | Database ID — returns entity changes only, no schema changes            | `=` `in`                     | Database UUID                                                      |
| `entityTypeId`   | Database ID — returns entity changes **and** all related schema changes | `=` `in`                     | Database UUID                                                      |
| `entityName`     | Entity name (partial match)                                             | `contains`                   | Text (minimum 3 characters)                                        |
| `entityId`       | Entity UUID                                                             | `=` `in`                     | UUID                                                               |
| `field`          | Exclude specific field types from results                               | `not-in`                     | See field filter section below                                     |

#### **Available `action` values:**

* `fibery.entity/create`
* `fibery.entity/delete`
* `fibery.entity/update`
* `fibery.entity/add-collection-items`
* `fibery.entity/remove-collection-items`
* `history/fibery.entity/archived`
* `history/fibery.entity/restored`
* `history/permissions-changed`

#### **The `field` filter (`not-in`):**

Use this filter to exclude noisy system-generated changes and get a clean log of meaningful, human-made edits. It supports specific field names and wildcard aliases:

| Alias        | What it excludes   |
| ------------ | ------------------ |
| `:hidden`    | All hidden fields  |
| `:private`   | All private fields |
| `:deleted`   | All deleted fields |
| `:createdBy` | Created-by fields  |
| `:system`    | All system fields  |
| `:name`      | All title fields   |

Example — exclude hidden fields and rank fields:

```json theme={null}
{
  "field": "field",
  "operator": "not-in",
  "value": [
    {
      "field": ":hidden",
      "options": {
        "includeSoftDeleted": true
      }
    },
    {
      "field": "fibery/rank"
    },
    {
      "field": "fibery/menu-rank"
    },
    {
      "type": "Collaboration~Documents/Document"
    },
    {
      "type": "fibery/rich-text"
    },
    {
      "field": "fibery/public-id"
    },
    {
      "field": ":createdBy"
    }
  ]
}
```

### Exclude automatic changes (`excludeAutomaticChanges`)

Use this option to exclude noisy changes made by system automatically

| Alias          | What it excludes                 |
| -------------- | -------------------------------- |
| `integrations` | All integration changes          |
| `automations`  | Changes made by automation rules |
| `auto-linking` | Automatically linked relations   |
| `formulas`     | All formula fields               |

***

### Response body

#### **Example response**

```json theme={null}
{
  "items": [
    {
      "id": "120659039",
      "action": "fibery.entity/update",
      "date": "{ISO 8601 datetime}",
      "schemaVersion": 22782,
      "sequenceId": "18740668",
      "type": {
        "id": "1e1d96c0-5dcb-11e8-90b6-c6e140253257",
        "name": "Product Management/feature",
        "title": "Feature",
        "exist": true,
        "softDeleted": false
      },
      "entity": {
        "id": "d7cea490-354d-11eb-9bfa-a53706ca0a40",
        "name": "History API",
        "exist": true,
        "softDeleted": false,
        "publicId": "2797",
        "capabilities": {
          "restore": false
        }
      },
      "author": {
        "id": "79f2f29b-9a45-4e30-9ba6-b785f10c78ec",
        "name": "Eugene Kisel",
        "exist": true,
        "softDeleted": false,
        "publicId": "1210"
      },
      "order": "120659039",
      "fromService": null,
      "caller": null,
      "changedValues": [
        {
          "field": {
            "id": "56cba110-5dcb-11e8-90b6-c6e140253257",
            "name": "workflow/state",
            "title": "State"
          },
          "currentValue": {
            "id": "5715c970-5dcb-11e8-90b6-c6e140253257",
            "name": "In Progress"
          },
          "previousValue": {
            "id": "c9cfb7f0-a45d-11ec-b0b9-197891c72881",
            "name": "Next"
          }
        }
      ]
    }
  ],
  "nextPage": {
    "hasNext": true,
    "sinceItem": "120550073"
  }
}
```

#### **`items` — array of history entries:**

| Field           | Description                                                                                                                                |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`            | Unique ID of this history entry                                                                                                            |
| `action`        | The type of change that was made                                                                                                           |
| `date`          | ISO 8601 datetime of when the change occurred                                                                                              |
| `schemaVersion` | Workspace schema version at the time of the change — useful for correlating changes with schema migrations                                 |
| `sequenceId`    | Monotonically increasing event sequence ID — use this to establish ordering when processing events across pages                            |
| `type`          | The Database the changed entity belongs to (`id`, `name`, `title`)                                                                         |
| `entity`        | The entity that was changed (`id`, `name`, `publicId`, `exist`, `softDeleted`)                                                             |
| `author`        | The user who made the change. If `null`, the change was made by the system or an automation — see `fromService`.                           |
| `fromService`   | Internal Fibery service that triggered the change (set when `author` is `null`)                                                            |
| `caller`        | Additional source information related to `fromService`                                                                                     |
| `changedValues` | List of field changes. Each item contains `field` (which field changed), `currentValue` (value after), and `previousValue` (value before). |

#### **`nextPage` — pagination metadata:**

| Field            | Description                                                                                                   |
| ---------------- | ------------------------------------------------------------------------------------------------------------- |
| `hasNext`        | `true` if more results exist on the next page                                                                 |
| `sinceItem`      | Pass this as `sinceItem` in the next request to retrieve the following page                                   |
| `hasNextLimited` | `true` when a workspace plan limit has been reached. Upgrade the workspace to access further history entries. |

***

## Datetime format

All `timeframe` values must be ISO 8601 datetime strings in UTC.

| Boundary                        | Example value              |
| ------------------------------- | -------------------------- |
| Start of a day (midnight)       | `2026-03-01T00:00:00.000Z` |
| End of a day (last millisecond) | `2026-03-01T23:59:59.999Z` |
| Start of an hour                | `2026-03-01T14:00:00.000Z` |
| Start of a minute               | `2026-03-01T14:30:00.000Z` |

The maximum allowed span between `start` and `end` is **1 year**.

For the "Get all changes from a specific day" sample below:

* Replace `{start-of-day}` with midnight on your chosen date — e.g. `2026-03-01T00:00:00.000Z`
* Replace `{end-of-day}` with the last millisecond of that day — e.g. `2026-03-01T23:59:59.999Z`

For all other samples, replace `{start-datetime}` and `{end-datetime}` with ISO 8601 values matching your desired range.

## Query samples

### Get all changes from a specific day

```json theme={null}
{
  "where": [],
  "timeframe": {
    "start": "{start-of-day}",
    "end": "{end-of-day}"
  },
  "limit": 50
}
```

### Get changes to a specific Database

Replace `{feature-type-uuid}` with the Database UUID (find it in Database settings).

```json theme={null}
{
  "where": [
    {
      "field": "typeId",
      "operator": "=",
      "value": "{feature-type-uuid}"
    }
  ],
  "timeframe": {
    "start": "{start-datetime}",
    "end": "{end-datetime}"
  },
  "limit": 50,
  "sinceItem": "{next-page-since-item}"
}
```

To include schema changes (field additions, renames, deletions) alongside entity changes, replace `typeId` with `entityTypeId`.

### Get all changes by a specific user

```json theme={null}
{
  "where": [
    {
      "field": "author",
      "operator": "=",
      "value": "{user-uuid}"
    }
  ],
  "timeframe": {
    "start": "{start-datetime}",
    "end": "{end-datetime}"
  },
  "limit": 50,
  "sinceItem": "{next-page-since-item}"
}
```

### Get all changes to a specific entity

By entity UUID:

```json theme={null}
{
  "where": [
    {
      "field": "typeId",
      "operator": "=",
      "value": "{type-uuid}"
    },
    {
      "field": "entityId",
      "operator": "=",
      "value": "{entity-uuid}"
    }
  ],
  "timeframe": {
    "start": "{start-datetime}",
    "end": "{end-datetime}"
  },
  "limit": 50
}
```

By public ID (the short numeric ID shown in the Fibery UI):

```json theme={null}
{
  "where": [
    {
      "field": "typeId",
      "operator": "=",
      "value": "{type-uuid}"
    },
    {
      "field": "entityPublicId",
      "operator": "=",
      "value": "{entity-public-id}"
    }
  ],
  "timeframe": {
    "start": "{start-datetime}",
    "end": "{end-datetime}"
  },
  "limit": 50
}
```

### Exclude automatic and system-generated changes

The log includes many system-generated changes by default (rank updates, formula recalculations, automation triggers). Use `field not-in` to filter them out:

```json theme={null}
{
  "where": [
    {
      "field": "field",
      "operator": "not-in",
      "value": [
        {
          "field": ":hidden",
          "options": { "includeSoftDeleted": true }
        },
        { "field": "fibery/rank" },
        { "field": "fibery/menu-rank" },
        { "type": "Collaboration~Documents/Document" },
        { "type": "fibery/rich-text" },
        { "field": "fibery/public-id" },
        { "field": ":createdBy" },
      ]
    }
  ],
  "excludeAutomaticChanges": ["integrations", "automations", "auto-linking", "formulas"],
  "timeframe": {
    "start": "{start-datetime}",
    "end": "{end-datetime}"
  },
  "limit": 50
}
```

### Paginating through results

The API uses cursor-based pagination via `sinceItem`. To retrieve all pages:

1. Make an initial request without `sinceItem`.
2. If `nextPage.hasNext` is `true`, copy the value of `nextPage.sinceItem`.
3. Pass it as `sinceItem` in the next request.
4. Repeat until `hasNext` is `false`.

<Callout icon="circle-info" color="#199EE3">
  The API may return fewer items per page than your `limit` value, even when `hasNext` is `true`. This can happen when long-running internal tasks are interrupted mid-page. Always use `hasNext` to determine whether more results exist — do not assume the last page has been reached just because a partial result was returned.
</Callout>

## Use cases

<Callout icon="https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg/2728.svg" color="#1fbed3">
  Feel free to use the scripts below as is, fork them, or simply feed them to your coding agent as an example when working with History API.
</Callout>

### Find maximum historical value of a Number Field

For each entity in a Database, get the maximum historical value of a certain Number Field. For example, understand what was the peak revenue for each customer.

Here's the solution overview (typed by a human):

1. Filter entities to avoid querying everything in a Database (History API is quite slow by design).
2. For each entity, find the Field’s maximum historical value.
3. Write the results into a CSV file for manual inspection.
4. Take the CSV file and update another Field with the maximum historical value for each entity.

And here's the source code (co-created with AI):

[https://gitlab.com/fibery-community/api-examples/-/tree/master/extract-historical-max-value](https://gitlab.com/fibery-community/api-examples/-/tree/master/extract-historical-max-value)

### Find when a Number Field value crossed a threshold

For each entity in a Database, understand when the value of a certain Number Field crossed a threshold.

For example, for each Event, understand when the number of registrations crossed the 100 people mark — the point when an Event typically breaks even and is worth organizing.

Here's the solution:

1. Find threshold crossings (e.g., when Subscription.Users became ≥ 2).
2. Enrich them (if the Number Field is on Subscriptions DB but the Date Field should be on Workspaces DB, we have to to map IDs).
3. Set the dates (→ Workspace.\[Second Purchase Date]).

Source code in our community repo:

[https://gitlab.com/fibery-community/api-examples/-/tree/master/find-threshold-crossings-via-history](https://gitlab.com/fibery-community/api-examples/-/tree/master/find-threshold-crossings-via-history)

## Related guides

* [Activity Log](https://the.fibery.io/@public/User_Guide/Guide/Activity-Log-276)
* [API overview](/guides/http-api/overview)
