# Totalum App Builder API — Visual Edits

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": … }`.


---

# Visual Edits

> Edit the preview directly, no prompt needed.

The preview marks every element with its source location (`data-tlm-loc="src/app/page.tsx:12:5"`). A visual editor sends a **batch** of changes to those elements; Totalum patches the code, checks that it still builds, and saves the batch as **one version** deployed to the preview. All or nothing: a change that cannot be applied leaves the code untouched. Visual edits need a paid plan.

## Apply Visual Edit

```endpoint
method: POST
path: /api/v1/vcaas/projects/:projectId/visual-edit/apply
cost: 0.6 credits
```

Apply a batch. Answers `202`; follow it with [Get Visual Edit](#get-visual-edit). Sending the same `batchId` again returns the same result without a second charge.

**Path parameters**

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

**Body parameters**

| Field | Type | Required | Description |
|---|---|---|---|
| `batchId` | string | Yes | A UUID you generate (the idempotency key) |
| `baseVersionId` | string | Yes | The version the preview showed |
| `changes` | object[] | Yes | 1–200 changes |
| `changes[].loc` | string | Yes | The element's `data-tlm-loc` (`path:line:column`) |
| `changes[].kind` | string | Yes | `"text"`, `"style"`, `"image"`, `"link"`, `"visibility"` or `"delete"` |
| `changes[].before` | string \| object | No | The current value (text, classes, src or href) |
| `changes[].after` | string \| object \| null | Yes | `text`: the new text · `style`: `{ add?, remove?, replace? }` of Tailwind classes · `image`: `{ src, alt? }` · `link`: `{ href, target? }` · `visibility`: `{ hidden }` · `delete`: `null` |
| `changes[].id` | string | No | Your id for the change |

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.batchId` | string | The batch |
| `data.versionId` | string | The version being saved |
| `data.operation` | object | `{ kind: "visualEdit", id, status: "building" }` |
| `data.creditsCharged` | number | 0.6 the first time, 0 on a repeat |

**Example request**

```bash
curl -X POST \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"batchId":"5f0c2e1a-8d3b-4c6e-9a7f-1b2c3d4e5f60","baseVersionId":"ver_01k6xd2m8q","changes":[{"loc":"src/app/page.tsx:14:7","kind":"text","before":"Book now","after":"Book your cut"}]}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/visual-edit/apply
```

:::success Success · 202 Accepted
```json
{ "errors": null, "data": { "batchId": "5f0c2e1a-8d3b-4c6e-9a7f-1b2c3d4e5f60", "versionId": "ver_01k6y6", "operation": { "kind": "visualEdit", "id": "op_01k6y7", "status": "building" }, "creditsCharged": 0.6 } }
```
:::

**Error codes**

| Code | HTTP | Meaning |
|---|---|---|
| `VALIDATION_ERROR` | 400 | `batchId` is not a UUID, or a change is invalid |
| `FREE_PLAN_NO_SOURCE_EDITING` | 403 | Editing code needs a paid plan |
| `BATCH_ID_IN_USE` | 409 | The `batchId` belongs to another project |
| `AGENT_RUNNING` | 409 | A prompt is running |
| `INSUFFICIENT_CREDITS` | 402 | Not enough credits |

## Get Visual Edit

```endpoint
method: GET
path: /api/v1/vcaas/projects/:projectId/visual-edit/:batchId
cost: Free
```

Whether a batch was saved. A batch that failed before it was saved is refunded.

**Path parameters**

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

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.batchId` | string | The batch |
| `data.versionId` | string \| null | Its version |
| `data.state` | string | `"saving"`, `"saved"` or `"failed"` |
| `data.errorCode` | string \| undefined | On failure, e.g. `VISUAL_EDIT_NOT_PATCHABLE`, `VISUAL_EDIT_TYPECHECK_FAILED`, `VISUAL_EDIT_BASE_MISMATCH` (the file changed since `baseVersionId`) |
| `data.errorMessage` | string \| undefined | On failure |
| `data.refunded` | boolean | The credits were given back |

**Example request**

```bash
curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/visual-edit/5f0c2e1a-8d3b-4c6e-9a7f-1b2c3d4e5f60
```

:::success Success · 200 OK
```json
{ "errors": null, "data": { "batchId": "5f0c2e1a-8d3b-4c6e-9a7f-1b2c3d4e5f60", "versionId": "ver_01k6y6", "state": "saved", "refunded": false } }
```
:::

**Error codes**

| Code | HTTP | Meaning |
|---|---|---|
| `VISUAL_EDIT_NOT_FOUND` | 404 | No such batch on this project |
