Logs & Preview Server
See what your app prints, in development and in production.
A project writes logs in two places: the development preview (dev) and the published site (live). Each log line belongs to one request, so you can follow a failing request from its status to the error it threw. Get Project Logs reads both with filters; the other two endpoints keep simpler shapes.
#Get Project Logs
/api/v1/vcaas/projects/:projectId/logsapi-keyFreeLog lines of the preview or the published site, newest first, with filters.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project id |
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
env | string | No | "dev" (preview) or "live" (published site) |
from | string | No | Start, ISO 8601 |
to | string | No | End, ISO 8601 |
level | string | No | "error", "warn", "info", "log" or "debug" |
q | string | No | Text to find in the message (up to 200 characters) |
status | string | No | HTTP status of the request: 500, or a class like 5xx |
path | string | No | Request path |
requestId | string | No | One request's lines |
limit | number | No | 1–500 |
Response fields
| Field | Type | Description |
|---|---|---|
data.items | object[] | Log lines |
data.items[].ts | string | ISO 8601 time |
data.items[].level | string | error, warn, info, log or debug |
data.items[].message | string | The text (secrets redacted) |
data.items[].requestId | string | null | The request it belongs to |
data.items[].method | string | null | HTTP method |
data.items[].path | string | null | Request path |
data.items[].status | number | null | Response status |
data.items[].cpuMs | number | null | CPU time of the request |
data.items[].wallMs | number | null | Duration of the request |
data.items[].outcome | string | How the request ended (ok, exception, canceled, …) |
data.items[].exception | object | undefined | { name, message, stack? } of an uncaught error |
data.window | object | { from, to, source }: the range searched |
data.nextCursor | string | null | Cursor for older lines |
data.sampled | boolean | true when a very busy window was sampled |
data.hint | string | undefined | A suggestion when nothing matched |
Example request
curl -H "api-key: tlm_sk_your_key" \
"https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/logs?env=live&level=error&limit=50"const res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/logs?env=live&level=error&limit=50", {
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{
"errors": null,
"data": {
"items": [
{
"ts": "2026-10-08T12:03:11.000Z",
"level": "error",
"message": "TotalumError [INSUFFICIENT_CREDITS]: The account has no credits",
"requestId": "9a1f2c",
"method": "POST",
"path": "/api/summary",
"status": 502,
"cpuMs": 4,
"wallMs": 210,
"outcome": "ok"
}
],
"window": { "from": "2026-10-08T06:03:00.000Z", "to": "2026-10-08T12:03:30.000Z", "source": "buffer" },
"nextCursor": null,
"sampled": false
}
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
VALIDATION_ERROR | 400 | A filter has an invalid value |
#Get Production Logs
/api/v1/vcaas/projects/:projectId/backend/prod/logsapi-keyFreeThe published site's requests, one record per request with the console output and exceptions of that request nested in it. Without from/to it covers the last 6 hours (the last 3 days when to or regexSearch is given). At most 500 log lines are read.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project id |
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
from | string | No | Start, ISO 8601 |
to | string | No | End, ISO 8601 |
regexSearch | string | No | Text to find — the fastest way to a specific request |
Response fields
| Field | Type | Description |
|---|---|---|
data.ok | boolean | true |
data.organizationId | string | The project id |
data.fromMs | number | Start of the range (epoch ms) |
data.toMs | number | End of the range (epoch ms) |
data.regexSearch | string | null | The search |
data.count | number | Records returned |
data.records | object[] | One per request |
data.records[].EventTimestampMs | number | When it was served |
data.records[].Outcome | string | How it ended |
data.records[].WallTimeMs | number | undefined | Duration |
data.records[].CPUTimeMs | number | undefined | CPU time |
data.records[].Event.Request | object | { URL, Method } |
data.records[].Event.Response | object | undefined | { Status } |
data.records[].Logs | object[] | { Level, Message: [text], TimestampMs } |
data.records[].Exceptions | object[] | { Name, Message, TimestampMs } |
data.totalChars | number | Size of the records |
data.truncated | boolean | true when the 500-line read limit was hit — narrow the range |
data.window | object | { from, to, source } actually searched |
Example request
curl -H "api-key: tlm_sk_your_key" \
"https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/backend/prod/logs?regexSearch=checkout"const res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/backend/prod/logs?regexSearch=checkout", {
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{
"errors": null,
"data": {
"ok": true,
"organizationId": "barber-bookings",
"fromMs": 1791547200000,
"toMs": 1791806400000,
"regexSearch": "checkout",
"count": 1,
"records": [
{
"EventTimestampMs": 1791806380000,
"Outcome": "ok",
"WallTimeMs": 128,
"CPUTimeMs": 14,
"Event": { "Request": { "URL": "/api/checkout", "Method": "POST" }, "Response": { "Status": 500 } },
"Logs": [{ "Level": "error", "Message": ["checkout failed: missing price"], "TimestampMs": 1791806380000 }],
"Exceptions": []
}
],
"totalChars": 312,
"truncated": false
}
}#Get Dev Server Logs
/api/v1/vcaas/projects/:projectId/backend/dev/logsapi-keyFreeThe development preview's log of the last hour, as plain text ([time] message per line, oldest first).
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project id |
Response fields
| Field | Type | Description |
|---|---|---|
data.logs | string | The lines, or a note when there are none yet |
Example request
curl -H "api-key: tlm_sk_your_key" \
https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/backend/dev/logsconst res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/backend/dev/logs", {
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{ "errors": null, "data": { "logs": "[2026-10-08T11:58:02.000Z] booking saved bk_1001\n[2026-10-08T11:58:03.000Z] e-mail sent to owner" } }#Start or Restart Server
/api/v1/vcaas/projects/:projectId/agent/server/start-or-restartapi-key2 credits (free to wake a sleeping project)Restart the project's development environment from its saved code, for example when the preview is stuck. On a project asleep after a long inactivity it wakes it instead (free): the preview answers again within seconds. You rarely need this — a prompt wakes a project by itself.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project id |
Response fields
| Field | Type | Description |
|---|---|---|
data.message | string | "Server is restarting" or "Project is reactivating" |
data.status | string | "restarting" or "reactivating" |
data.operationId | string | The operation, visible in Get Project State |
data.creditsCharged | number | 2 for a restart, 0 to wake |
Example request
curl -X POST -H "api-key: tlm_sk_your_key" \
https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/server/start-or-restartconst res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/agent/server/start-or-restart", {
method: "POST",
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{ "errors": null, "data": { "message": "Server is restarting", "status": "restarting", "operationId": "op_01k6xt", "creditsCharged": 2 } }Error codes
| Code | HTTP | Meaning |
|---|---|---|
AGENT_RUNNING | 409 | A prompt is running |
OPERATION_IN_PROGRESS | 409 | Another operation (publish, restore…) is running |
