# Totalum App Builder API — Versions

This file is the complete reference for this area. The short guide for agents is https://www.totalum.app/totalum-api.md.

- Base URL: `https://builder-api.totalum.app/api/v1/vcaas`
- Authentication: header `api-key: tlm_sk_…` on every request, from a server only.
- Response envelope: `{ "errors": null | { "errorCode", "errorMessage", "errorDetails?" }, "data": … }`.


---

# Versions

> Every change is a version. Browse them, compare them, roll back.

Every change to a project's code is saved as a **version**: each prompt that changed files, each file write through the API, each visual edit, GitHub pull, import and restore. Restoring a version changes the **development preview**; [publish](https://www.totalum.app/docs/api/deployments) to put it live.

## List Versions

```endpoint
method: GET
path: /api/v1/vcaas/projects/:projectId/versions
cost: Free
```

The project's versions, newest first.

**Path parameters**

| Parameter | Type | Description |
|---|---|---|
| `projectId` | string | The project id |

**Query parameters**

| Field | Type | Required | Description |
|---|---|---|---|
| `limit` | number | No | 1–100 (default 20) |
| `skip` | number | No | Versions to skip (default 0) |

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.versions` | object[] | The versions |
| `data.versions[]._id` | string | Version id — for [Recover Version](#recover-version) |
| `data.versions[].name` | string | Display name |
| `data.versions[].commitSha` | string | Commit of the version — for [Get Version Diff](#get-version-diff) |
| `data.versions[].commitMessage` | string \| undefined | Commit message |
| `data.versions[].prompt` | string \| undefined | The prompt that produced it (first 300 characters) |
| `data.versions[].gcsUploaded` | boolean | `true` once the version's archive is stored |
| `data.versions[].recoveredVersionId` | string \| undefined | When this version is a restore: the version it restored |
| `data.versions[].createdAt` | string | ISO 8601 |
| `data.versions[].updatedAt` | string | ISO 8601 (same as `createdAt`) |
| `data.totalCount` | number | Total versions |

**Example request**

```bash
curl -H "api-key: tlm_sk_your_key" \
  "https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/versions?limit=20"
```

:::success Success · 200 OK
```json
{
  "errors": null,
  "data": {
    "versions": [
      {
        "_id": "ver_01k6xd2m8q",
        "commitSha": "9f2c1ab4d3e5f60718293a4b5c6d7e8f90a1b2c3",
        "commitMessage": "Add a contact form",
        "prompt": "Add a contact form that emails me every message",
        "gcsUploaded": true,
        "createdAt": "2026-10-08T11:15:40.000Z",
        "updatedAt": "2026-10-08T11:15:40.000Z",
        "name": "Version 4"
      }
    ],
    "totalCount": 4
  }
}
```
:::

## Get Version Diff

```endpoint
method: GET
path: /api/v1/vcaas/projects/:projectId/version-diff
cost: Free
```

The unified diff (`git diff` format) a version introduced.

**Path parameters**

| Parameter | Type | Description |
|---|---|---|
| `projectId` | string | The project id |

**Query parameters**

| Field | Type | Required | Description |
|---|---|---|---|
| `commitSha` | string | Yes | The version's `commitSha`, 7–40 hexadecimal characters |

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.commitSha` | string | The commit |
| `data.diff` | string | The diff; `""` when nothing tracked changed |

**Example request**

```bash
curl -H "api-key: tlm_sk_your_key" \
  "https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/version-diff?commitSha=9f2c1ab"
```

:::success Success · 200 OK
```json
{ "errors": null, "data": { "commitSha": "9f2c1ab", "diff": "diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx\nnew file mode 100644\n+export default function Contact() {\n" } }
```
:::

**Error codes**

| Code | HTTP | Meaning |
|---|---|---|
| `MISSING_COMMIT_SHA` | 400 | `commitSha` is missing |
| `INVALID_COMMIT_SHA` | 400 | Not 7–40 hexadecimal characters |
| `VERSION_NOT_FOUND` | 404 | No version with this commit |

## Recover Version

```endpoint
method: POST
path: /api/v1/vcaas/projects/:projectId/versions/:id/recover
cost: 2 credits
```

Restore an earlier version's code as a new version, deployed to the preview. It runs in the background (1–4 minutes): poll [Get Project](https://www.totalum.app/docs/api/projects#get-project) until `versionRecovery` is `null` (on failure it shows `status: "error"` with `errorMessage`).

The database is never rolled back by a code restore: the restored code keeps working on the current schema (a column it needs that a later change dropped is added back, empty). Send `restoreDevDatabase: true` to also put the **development** database back to that version's time.

**Path parameters**

| Parameter | Type | Description |
|---|---|---|
| `projectId` | string | The project id |
| `id` | string | The version's `_id` |

**Body parameters**

| Field | Type | Required | Description |
|---|---|---|---|
| `restoreDevDatabase` | boolean | No | Also restore the development database to the version's time (a restore point is taken first) |

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.message` | string | `"Version recovered successfully"` — the restore has started |

**Example request**

```bash
curl -X POST -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/versions/ver_01k6xd2m8q/recover
```

:::success Success · 200 OK
```json
{ "errors": null, "data": { "message": "Version recovered successfully" } }
```
:::

**Error codes**

| Code | HTTP | Meaning |
|---|---|---|
| `VERSION_NOT_FOUND` | 404 | No such version |
| `AGENT_RUNNING` | 409 | A prompt is running |
| `DEPLOYMENT_RUNNING` | 409 | A publish is running |
| `OPERATION_IN_PROGRESS` | 409 | Another restore or long operation is running |
| `INSUFFICIENT_CREDITS` | 402 | Not enough credits |

## Clear Recovery Marker

```endpoint
method: DELETE
path: /api/v1/vcaas/projects/:projectId/versions/recovery
cost: Free
```

Clear `versionRecovery` on the project after a failed restore, so it no longer shows. A restore that is really running ends by itself; never more than 25 minutes.

**Path parameters**

| Parameter | Type | Description |
|---|---|---|
| `projectId` | string | The project id |

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.cleared` | boolean | `false` when there was nothing to clear |
| `data.wasRunning` | boolean | The cleared restore had started less than 10 minutes ago |
| `data.previousStatus` | string \| undefined | Its status before clearing |
| `data.message` | string | What to do next |

**Example request**

```bash
curl -X DELETE -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/versions/recovery
```

:::success Success · 200 OK
```json
{ "errors": null, "data": { "cleared": true, "wasRunning": false, "previousStatus": "error", "message": "Cleared. Restart, deploy, prompts and a new recovery are allowed again." } }
```
:::
