# Totalum App Builder API — Errors & Limits

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


---

# Errors & Limits

> What can go wrong, and the numbers to design for.

## The envelope

Every response is JSON in the same envelope. On success `errors` is `null`; on failure `data` is `null` and `errors` has a stable `errorCode` (branch on it), a human `errorMessage` (show it, never parse it) and sometimes `errorDetails`.

```json
{ "errors": { "errorCode": "AGENT_RUNNING", "errorMessage": "An agent run is already in progress", "errorDetails": { "runId": "run_01k6xc4n7d" } }, "data": null }
```

Legacy projects and the older host `api-accounts.totalum.app` keep two older shapes: `403 VCAAS_INSUFFICIENT_CREDITS` answers `{ "error", "code" }` and a secret that fails validation `{ "success": false, "message", "errors": [...] }` ([Legacy projects](https://www.totalum.app/docs/api/migration-v2#what-behaves-differently)).

## Errors any endpoint can answer

| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| `invalid token` / `Unauthorized api key` | 401 | Missing or unknown `api-key` header | Send a valid `tlm_sk_` key |
| `VCAAS_INSUFFICIENT_CREDITS` | 403 | Your balance is below 1 credit (reads and deleting a project still work) | Add credits |
| `PROJECT_NOT_FOUND` | 404 | No project with this id in your account | Check the id ([List Projects](https://www.totalum.app/docs/api/projects#list-projects)) |
| `PROJECT_NOT_ALLOWED` | 403 | Your key is restricted to other projects | Use a key with access |
| `API_ACCESS_DISABLED` | 403 | API access is switched off for this project in your account settings | Switch it on |
| `PROJECT_NOT_READY` | 409 | The project is still being set up (its first seconds) | Retry after `Retry-After` seconds |
| `INSUFFICIENT_CREDITS` | 402 | The action costs more than your balance | Add credits |
| `PROJECT_CREDIT_LIMIT_REACHED` | 403 | The project's monthly cap for that category is reached | [Raise the cap](https://www.totalum.app/docs/api/limits#update-credit-limits) |
| `AGENT_RUNNING` | 409 | A prompt is running | Wait for `agent/status` to be `"done"` |
| `DEPLOYMENT_RUNNING` | 409 | A publish is running | Wait for `deployments/status` to leave `"deploying"` |
| `OPERATION_IN_PROGRESS` | 409 | Another long operation (restore, import, pause, database move…) holds the project | Retry when it ends ([Get Project State](https://www.totalum.app/docs/api/projects#get-project-state)) |
| `PROJECT_PAUSED_BY_USER` | 409 | The project is paused | [Resume](https://www.totalum.app/docs/api/projects#resume-project) it |
| `PROJECT_PAUSED_RUNAWAY` | 429 | The emergency stop paused the project after unusual usage (it lifts by itself after 24 hours) | Fix the cause, then [release it](https://www.totalum.app/docs/api/projects#release-runaway-pause) |
| `AI_MEDIA_PAUSED_THIS_HOUR` | 429 | The app used a lot of credits this hour, so its image, video and speech AI calls are paused until the hour ends (UTC); text AI and everything else keep working | Wait for `Retry-After` (the start of the next hour) |
| `RATE_LIMIT_EXCEEDED` / `RATE_LIMITED` | 429 | Too many requests | Back off; honour `Retry-After` |
| `VALIDATION_ERROR` | 400 | A field is missing or has the wrong type | Fix the request |
| `INVALID_JSON` | 400 | The body is not valid JSON | Fix the body |
| `PAYLOAD_TOO_LARGE` | 413 | The JSON body is over 1 MB | Upload files with [Upload File](https://www.totalum.app/docs/api/source-files#upload-file) |
| `ROUTE_NOT_FOUND` | 404 | No endpoint at this path | Check the path |
| `METHOD_NOT_ALLOWED` | 405 | The path exists for other methods (listed in the `Allow` header) | Use one of them |
| `ENGINE_UNAVAILABLE` | 503 | A temporary failure | Retry in a few seconds |
| `INTERNAL_ERROR` | 500 | An unexpected error | Retry; contact support if it persists |

**Retrying.** `4xx` means the request must change (except `409` and `429`, which clear by themselves). `503` and the `PROJECT_NOT_READY` `409` are temporary: retry after `Retry-After`. Every long operation (prompt, publish, restore, import) answers at once and is followed by polling; never retry the start call while the first one is still running.

## Limits

The API's own limits. Plan, project, database and built-in feature limits are all on [Limits](https://www.totalum.app/docs/limits).

| What | Limit |
|---|---|
| Authentication | One `api-key` header per request, kept on your server |
| JSON request body | 1 MB |
| File upload | 20 MB per file ([Upload File](https://www.totalum.app/docs/api/source-files#upload-file)); 300 uploads a minute |
| Prompt | 40,000 characters, up to 10 attachments |
| Multi-prompt batch | 50 prompts |
| One prompt's run | The agent works up to about 40 minutes, then wraps up and saves its work |
| Concurrency per project | One prompt, one publish, one restore or import at a time |
| Requests per API key | Free 10 a second, paid plans 100, Enterprise 1,000 (counted each second, Enterprise over 10 s); over it `429 RATE_LIMITED` with `Retry-After` |
| Prompts per account | All projects together: as many a minute as the plan's new projects a minute (a create counts as one), and twice that many running at once — see [Limits](https://www.totalum.app/docs/limits); over it `429 RATE_LIMITED` with `Retry-After` |
| Project creation | Per plan: Free 2 projects (1 a minute), Starter 10, Builder 50, Professional 300, Enterprise unlimited — see [Create Project](https://www.totalum.app/docs/api/projects#create-project) |
| Project id | 4–35 characters: lowercase letters, digits and single hyphens, starting with a letter |
| File read / write through the API | 1 MB read, 512 KB write; 300 writes a minute |
| Secrets | 500 per project, values up to 10,000 characters |
| Scheduled jobs | 2 (Free), 10 (Starter) or 20 per environment; every hour (Free) or every minute (paid) at most |
| Export | 5 an hour per project |
| Webhooks | One unfiltered subscription per event; deliveries time out after 10 s |
| The app's built-in features | 100 calls a second per project; 20 paid calls a minute per visitor (AI, web, browser) |
| Database (per environment) | 10 GB on the default database (move to Turso for more); a query runs up to 30 s; 100 bound parameters per query |
| Published site | 5,000 requests a minute per visitor by default ([rate limit](https://www.totalum.app/docs/api/limits#get-rate-limit)) |

## Plans and credits

Every plan can use the API, including the free one. Everything is paid in **credits**: plan credits renew each billing period and are spent first; purchased credits never expire.

- **Prompts** are metered by the work done: at least 3 credits, usually 3 to 50. A failed run that built nothing is refunded.
- **Fixed-price actions** (create, publish, restore, export…) are listed by [Get Credit Costs](https://www.totalum.app/docs/api/account#get-credit-costs).
- **The running app** (hosting, database, files, AI, e-mail, scraping…) is metered per use; a published project on a paid plan also pays a small monthly fee, and an active custom domain another.
- Cap each project with [credit limits](https://www.totalum.app/docs/api/limits) and follow spending with [Usage & Analytics](https://www.totalum.app/docs/api/analytics).
