> For the complete documentation index, see [llms.txt](https://docs.umbraco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.umbraco.com/ai-in-umbraco/19.latest/reference/services/ai-entity-version-service.md).

# IAIEntityVersionService

Service for managing entity version history.

Service for accessing version history, comparing versions, and creating snapshots of AI entities.

## Namespace

```csharp
using Umbraco.AI.Core.Versioning;
```

## Interface

{% code title="IAIEntityVersionService" %}

```csharp
public interface IAIEntityVersionService
{
    Task<(IEnumerable<AIEntityVersion> Items, int Total)> GetVersionHistoryAsync(
        Guid entityId,
        string entityType,
        int skip,
        int take,
        CancellationToken cancellationToken = default);

    Task<AIEntityVersion?> GetVersionAsync(
        Guid entityId,
        string entityType,
        int version,
        CancellationToken cancellationToken = default);

    Task<TEntity?> GetVersionSnapshotAsync<TEntity>(
        Guid entityId,
        int version,
        CancellationToken cancellationToken = default)
        where TEntity : class, IAIVersionableEntity;

    Task SaveVersionAsync<TEntity>(
        TEntity entity,
        Guid? userId,
        string? changeDescription = null,
        CancellationToken cancellationToken = default)
        where TEntity : class, IAIVersionableEntity;

    Task SaveVersionAsync(
        Guid entityId,
        string entityType,
        int version,
        string snapshot,
        Guid? userId,
        string? changeDescription = null,
        CancellationToken cancellationToken = default);

    Task DeleteVersionsAsync(
        Guid entityId,
        string entityType,
        CancellationToken cancellationToken = default);

    Task<AIVersionComparison?> CompareVersionsAsync(
        Guid entityId,
        string entityType,
        int fromVersion,
        int toVersion,
        CancellationToken cancellationToken = default);

    string CreateSnapshot<TEntity>(TEntity entity)
        where TEntity : class, IAIVersionableEntity;

    TEntity? RestoreFromSnapshot<TEntity>(string snapshot)
        where TEntity : class, IAIVersionableEntity;

    Task<AIVersionCleanupResult> CleanupVersionsAsync(
        CancellationToken cancellationToken = default);
}
```

{% endcode %}

## Methods

### GetVersionHistoryAsync

Gets the version history for an entity.

| Parameter           | Type                | Description                                  |
| ------------------- | ------------------- | -------------------------------------------- |
| `entityId`          | `Guid`              | The entity ID                                |
| `entityType`        | `string`            | The entity type (e.g., "profile", "context") |
| `skip`              | `int`               | Records to skip                              |
| `take`              | `int`               | Records to take                              |
| `cancellationToken` | `CancellationToken` | Cancellation token                           |

**Returns**: Tuple of (versions, total count).

{% code title="Example" %}

```csharp
var (versions, total) = await _versionService.GetVersionHistoryAsync(
    profileId,
    "profile",
    skip: 0,
    take: 10);

foreach (var v in versions)
{
    Console.WriteLine($"Version {v.Version}: {v.DateCreated}");
}
```

{% endcode %}

### GetVersionAsync

Gets a specific version record.

| Parameter           | Type                | Description        |
| ------------------- | ------------------- | ------------------ |
| `entityId`          | `Guid`              | The entity ID      |
| `entityType`        | `string`            | The entity type    |
| `version`           | `int`               | The version number |
| `cancellationToken` | `CancellationToken` | Cancellation token |

**Returns**: The version record if found, otherwise `null`.

### GetVersionSnapshotAsync

Gets the entity state at a specific version.

| Parameter           | Type                | Description        |
| ------------------- | ------------------- | ------------------ |
| `entityId`          | `Guid`              | The entity ID      |
| `version`           | `int`               | The version number |
| `cancellationToken` | `CancellationToken` | Cancellation token |

**Returns**: The deserialized entity at that version, or `null`.

{% code title="Example" %}

```csharp
var previousProfile = await _versionService.GetVersionSnapshotAsync<AIProfile>(
    profileId,
    version: 3);

if (previousProfile != null)
{
    Console.WriteLine($"Profile name at v3: {previousProfile.Name}");
    Console.WriteLine($"Temperature at v3: {previousProfile.Settings?.Temperature}");
}
```

{% endcode %}

### SaveVersionAsync

Saves a version snapshot for an entity. This is typically called automatically by entity services. Two overloads are available: a generic one that snapshots a typed entity, and a non-generic one that accepts raw snapshot data.

{% code title="Generic overload" %}

```csharp
Task SaveVersionAsync<TEntity>(
    TEntity entity,
    Guid? userId,
    string? changeDescription = null,
    CancellationToken cancellationToken = default)
    where TEntity : class, IAIVersionableEntity;
```

{% endcode %}

| Parameter           | Type                | Description              |
| ------------------- | ------------------- | ------------------------ |
| `entity`            | `TEntity`           | The entity to snapshot   |
| `userId`            | `Guid?`             | User who made the change |
| `changeDescription` | `string?`           | Description of changes   |
| `cancellationToken` | `CancellationToken` | Cancellation token       |

{% code title="Raw-snapshot overload" %}

```csharp
Task SaveVersionAsync(
    Guid entityId,
    string entityType,
    int version,
    string snapshot,
    Guid? userId,
    string? changeDescription = null,
    CancellationToken cancellationToken = default);
```

{% endcode %}

| Parameter           | Type                | Description                            |
| ------------------- | ------------------- | -------------------------------------- |
| `entityId`          | `Guid`              | The entity ID                          |
| `entityType`        | `string`            | The entity type name (e.g., "Profile") |
| `version`           | `int`               | The version number                     |
| `snapshot`          | `string`            | The raw JSON snapshot                  |
| `userId`            | `Guid?`             | User who made the change               |
| `changeDescription` | `string?`           | Description of changes                 |
| `cancellationToken` | `CancellationToken` | Cancellation token                     |

### DeleteVersionsAsync

Deletes all version history for an entity.

| Parameter           | Type                | Description        |
| ------------------- | ------------------- | ------------------ |
| `entityId`          | `Guid`              | The entity ID      |
| `entityType`        | `string`            | The entity type    |
| `cancellationToken` | `CancellationToken` | Cancellation token |

### CompareVersionsAsync

Compares two versions and returns the differences.

| Parameter           | Type                | Description        |
| ------------------- | ------------------- | ------------------ |
| `entityId`          | `Guid`              | The entity ID      |
| `entityType`        | `string`            | The entity type    |
| `fromVersion`       | `int`               | Source version     |
| `toVersion`         | `int`               | Target version     |
| `cancellationToken` | `CancellationToken` | Cancellation token |

**Returns**: Comparison result with changes.

{% code title="Example" %}

```csharp
var comparison = await _versionService.CompareVersionsAsync(
    profileId,
    "profile",
    fromVersion: 2,
    toVersion: 5);

if (comparison != null)
{
    foreach (var change in comparison.Changes)
    {
        Console.WriteLine($"{change.Path}: {change.ChangeType}");
        Console.WriteLine($"  From: {change.FromValue}");
        Console.WriteLine($"  To: {change.ToValue}");
    }
}
```

{% endcode %}

### CreateSnapshot / RestoreFromSnapshot

Creates and restores JSON snapshots of entities.

{% code title="Example" %}

```csharp
// Create a snapshot
var snapshot = _versionService.CreateSnapshot(profile);

// Later, restore from snapshot
var restored = _versionService.RestoreFromSnapshot<AIProfile>(snapshot);
```

{% endcode %}

### CleanupVersionsAsync

Removes old versions based on retention settings.

**Returns**: Cleanup result with count of removed versions.

{% code title="Example" %}

```csharp
var result = await _versionService.CleanupVersionsAsync();
Console.WriteLine($"Cleaned up {result.DeletedCount} old versions");
```

{% endcode %}

## Entity Types

| Type String    | Entity Class                            |
| -------------- | --------------------------------------- |
| `"connection"` | `AIConnection`                          |
| `"profile"`    | `AIProfile`                             |
| `"context"`    | `AIContext`                             |
| `"prompt"`     | `AIPrompt` (requires Umbraco.AI.Prompt) |
| `"agent"`      | `AIAgent` (requires Umbraco.AI.Agent)   |

## Related

* [AIEntityVersion](/ai-in-umbraco/19.latest/reference/models/ai-entity-version.md) - The version model
* [Version History Concept](/ai-in-umbraco/19.latest/concepts/versioning.md) - Versioning concepts


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.umbraco.com/ai-in-umbraco/19.latest/reference/services/ai-entity-version-service.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
