# Totalum App Builder API — Figma

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


---

# Figma

> Build from your designs.

Connect Figma with a token, then paste a Figma link in a prompt ("build the pricing section from this design: https://www.figma.com/design/…?node-id=42-1337"); the agent reads that frame. In Figma, right-click a frame → **Copy link to selection** for a link to exactly that frame. Tokens are stored encrypted and never returned.

**Create a token:** Figma → **Settings** → **Security** → **Personal access tokens** → *Generate new token*, with the scopes `current_user:read` and `file_content:read` (it starts with `figd_`). An Organization or Enterprise **plan access token** works the same way and survives people leaving the team.

## Connect Figma

```endpoint
method: POST
path: /api/v1/vcaas/projects/:projectId/figma/connect
cost: Free
```

Link a Figma account to the project. The token is checked with Figma before anything is stored. [Launch Project](https://www.totalum.app/docs/api/projects#launch-project) also takes `figma.token`.

**Path parameters**

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

**Body parameters**

| Field | Type | Required | Description |
|---|---|---|---|
| `token` | string | Yes | Figma personal or plan access token |

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.connected` | boolean | `true` |
| `data.account` | object | `{ id, handle, email?, imgUrl? }` of the Figma account |

**Example request**

```bash
curl -X POST \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"token":"figd_xxx"}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/figma/connect
```

:::success Success · 200 OK
```json
{ "errors": null, "data": { "connected": true, "account": { "id": "123456", "handle": "Ada Lovelace", "email": "ada@example.com", "imgUrl": "https://s3-alpha.figma.com/profile/…" } } }
```
:::

**Error codes**

| Code | HTTP | Meaning |
|---|---|---|
| `MISSING_FIGMA_TOKEN` | 400 | `token` is missing |
| `FIGMA_TOKEN_MALFORMED` | 400 | Not a Figma token (whitespace, a URL, too short) |
| `FIGMA_TOKEN_INVALID` | 400 | Figma rejected it: wrong, expired or revoked |
| `FIGMA_TOKEN_FORBIDDEN` | 400 | Missing the `current_user:read` / `file_content:read` scopes |
| `FIGMA_RATE_LIMITED` | 400 | Figma is rate-limiting; retry shortly |
| `FIGMA_UNREACHABLE` | 400 | Figma could not be reached |
| `AGENT_RUNNING` | 409 | A prompt is running |

## Check a Figma Token

```endpoint
method: POST
path: /api/v1/vcaas/figma/validate
cost: Free
```

Check a token without connecting it — for a connect form. 10 checks a minute per account.

**Body parameters**

| Field | Type | Required | Description |
|---|---|---|---|
| `token` | string | Yes | The token |

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.valid` | boolean | `true` |
| `data.account` | object | `{ id, handle, email?, imgUrl? }` |

**Example request**

```bash
curl -X POST \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"token":"figd_xxx"}' \
  https://builder-api.totalum.app/api/v1/vcaas/figma/validate
```

:::success Success · 200 OK
```json
{ "errors": null, "data": { "valid": true, "account": { "id": "123456", "handle": "Ada Lovelace", "email": "ada@example.com" } } }
```
:::

**Error codes**

| Code | HTTP | Meaning |
|---|---|---|
| `FIGMA_TOKEN_MISSING` | 400 | No token |
| `FIGMA_TOKEN_MALFORMED` / `FIGMA_TOKEN_INVALID` / `FIGMA_TOKEN_FORBIDDEN` / `FIGMA_RATE_LIMITED` / `FIGMA_UNREACHABLE` | 400 | As in [Connect Figma](#connect-figma) |
| `RATE_LIMITED` | 429 | More than 10 checks a minute |

## Get Figma Status

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

Whether Figma is connected, and to which account. A failed re-check never disconnects it.

**Path parameters**

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

**Query parameters**

| Field | Type | Required | Description |
|---|---|---|---|
| `verify` | boolean | No | `true` re-checks the token with Figma (a live call: on screen open, not in a poll) |

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.connected` | boolean | Connected |
| `data.account` | object \| undefined | `{ id, handle, email?, imgUrl? }` |
| `data.connectedAt` | string \| undefined | When it was connected |
| `data.tokenValid` | boolean \| undefined | With `verify=true`: Figma still accepts the token |
| `data.tokenError` | string \| undefined | With `verify=true`: why it failed |
| `data.expiresAt` | string \| undefined | Token expiry, when known |

**Example request**

```bash
curl -H "api-key: tlm_sk_your_key" \
  "https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/figma/status?verify=true"
```

:::success Success · 200 OK
```json
{ "errors": null, "data": { "connected": true, "account": { "id": "123456", "handle": "Ada Lovelace" }, "connectedAt": "2026-10-08T10:24:00.000Z", "tokenValid": true } }
```
:::

## Disconnect Figma

```endpoint
method: DELETE
path: /api/v1/vcaas/projects/:projectId/figma/connect
cost: Free
```

Remove the Figma connection (nothing changes in your Figma account). Calling it on a project that is not connected also answers `200`.

**Path parameters**

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

**Response fields**

| Field | Type | Description |
|---|---|---|
| `data.disconnected` | boolean | `true` |
| `data.message` | string | Confirmation |

**Example request**

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

:::success Success · 200 OK
```json
{ "errors": null, "data": { "disconnected": true, "message": "Figma disconnected successfully" } }
```
:::
