Versioning
Nothing is ever overwritten.
Every refresh creates a new version. Every version is permanent. You can roll back to any prior state, diff any two versions, and publish a cleaned alt alongside the original — all without touching the source data.
How versions are created
A new version is created every time a refresh completes successfully — whether triggered by the nightly scheduler, a ping URL hit, or a manual refresh from the dashboard. Version numbers are monotonically incrementing integers starting at 1. They are never reused or deleted.
When a new version is created, it automatically becomes the active version unless you have manually rolled back to a specific version, in which case active stays pinned where you left it.
Version fields
Each version record exposed by /dataset/view contains these fields.
Monotonically incrementing integer. Starts at 1 and increases by 1 on every successful refresh. Never reused.
Internal storage path of the version file. Not exposed via the public API.
Internal storage path of the alt version file, if one exists. Null otherwise.
Number of entities in this version.
Size of the version file in bytes.
Whether this version is the current active version. Only one version can be active at a time.
ISO 8601 timestamp of when this version was created.
Accessing versions via the API
The third segment of every API URL is the version reference. Three forms are accepted.
active
The pinned active version. Controlled by rollback. This is what consumers should use by default — it only changes when you explicitly pin a new version or a refresh completes.
latest
The highest version number in the dataset. After a nightly refresh, latest is the new version. active only moves to match if no rollback is in effect.
v1, v2, v3…
A specific version by number. Immutable. The data at v3 will always be exactly what was captured at that refresh.
GET https://quorel.vercel.app/api/42/my-dataset/active/ # pinned version GET https://quorel.vercel.app/api/42/my-dataset/latest/ # most recent version GET https://quorel.vercel.app/api/42/my-dataset/v3/ # exactly version 3
The resolved version number is always returned in the X-Dataset-Version response header, so you always know exactly which version you received even when requesting active or latest.
Rollback
Rolling back pins active to any prior version. The dataset continues to refresh nightly and newer versions keep accumulating — they just aren't served at active until you update the pin.
Request
POST /dataset/rollback
Authorization: <session>
{
"dataset_id": 42,
"version_number": 3,
"freeze": false
}What rollback does
Sets active_version to the specified version_number. The API immediately starts serving that version at ?version=active. No data is deleted or modified.
What rollback does not do
Rollback does not delete newer versions. v5, v6, v7 are all still accessible by number after rolling back to v3. Nothing is ever destroyed.
Freeze on rollback
You can optionally freeze the dataset at rollback time by passing freeze: true. This locks the dataset at that version permanently and prevents future refreshes.
Unfreezing
Unfreezing re-activates the dataset for nightly refreshes. It counts against your plan's active dataset limit. A frozen dataset does not count toward the limit.
Alt versions
Every version can have an alt — a separate copy of the entities for that version that lives alongside the original without replacing it. Alts are useful for cleaned, enriched, or deduplicated versions of the same data. The original is never modified.
Accessing an alt
# Via query param GET https://quorel.vercel.app/api/42/my-dataset/active/?alt=true # Via URL path suffix GET https://quorel.vercel.app/api/42/my-dataset/v3/alt/
alt=true
Query parameter. Returns the alt version of the requested version. Equivalent to appending /alt/ to the path.
/alt/
URL path suffix. GET /api/42/my-dataset/v3/alt/ returns the alt for v3.
How alt versions are created
Dashboard
Open any version in the dashboard, switch to the Alt tab, edit or replace the entity list manually, and save. The alt is written immediately.
MCP agent (push_alt_version)
Call pull_for_edit to get the raw entities, process them with Claude, then push_alt_version to write the result back as the alt. The original is never touched.
API (web alternate save)
POST to /dataset/alternate/save with dataset_id, version, and a JSON array of entities. The alt is written to storage and the alt_file_path is recorded against the version.
Requesting an alt that doesn't exist returns 404. Check X-Dataset-Alt in the response headers to confirm whether an alt was served.
Deleting an alt
Alts can be deleted independently of the original version. The original is unaffected.
DELETE /dataset/alternate/delete
Authorization: <session>
{
"dataset_id": 42,
"version": 3
}The alt file is removed from storage and alt_file_path is set to null on the version record. The version itself is untouched.
Diffing two versions
Any two versions of the same dataset can be diffed. Quorel matches entities across versions using their source URL and a weighted field-similarity score, then classifies each change as added, subtracted, or modified.
Request
GET /dataset/diff?dataset_id=42&v1=3&v2=5
Response shape
{
"added": 12,
"subtracted": 3,
"modified": 27,
"total_v1": 801,
"total_v2": 847,
"records": [
{
"id": "rec_0001",
"change_type": "modified",
"source": "https://example.com/job/123",
"v1": { "title": "Senior Engineer", "salary": 120000 },
"v2": { "title": "Senior Engineer", "salary": 135000 },
"field_diffs": [
{ "field": "salary", "v1": 120000, "v2": 135000 }
]
}
]
}Number of entities present in v2 but not in v1.
Number of entities present in v1 but not in v2.
Number of entities matched across versions where at least one field value changed.
Total entity count in v1.
Total entity count in v2.
Array of diff records. Each has id, change_type (added / subtracted / modified), source, v1, v2, and field_diffs for modified records.
Change types
added
Entity exists in v2 but not v1. v1 is null.
subtracted
Entity exists in v1 but not v2. v2 is null.
modified
Entity matched across versions (same source URL, similar field values). field_diffs lists exactly which fields changed and shows v1 and v2 values side by side.
Entity matching is weighted by field cardinality — fields with more unique values across the dataset carry more weight in the similarity score. A minimum similarity threshold of 0.3 is required for two entities to be considered a match. Below that threshold, both are treated as independent additions and subtractions.
Clones and versions
When you clone a public dataset, the clone receives v1 containing a copy of the source dataset's latest version at the time of cloning. If the source dataset had an alt on that version, the alt is also copied into the clone's v1.
From that point on, the clone's version history is entirely independent. Future refreshes of the source dataset do not affect the clone. The clone's v2, v3, and beyond come from its own nightly refreshes against its own source URLs.