Docs
BlogHomeStart building

Projects

Manage the lifecycle of your vibe coding projects.


Projects are the top-level unit of the VCaaS API. Each project has its own database, source code, dev server, and (optionally) a deployment and custom domain. All endpoints require the api-key header and return the standard { "errors": ..., "data": ... } envelope.

#Create Project

POST/api/v1/vcaas/projectsUses credits

Create a new vibe coding project.

Body parameters

FieldTypeRequiredDescription
projectIdstringYes4-35 chars, lowercase letters + numbers + hyphens, must start with letter
descriptionstringNoProject description, max 500 characters

Response fields

FieldTypeDescription
data.projectIdstringThe project ID
data.descriptionstringProject description
data.planstringAlways "api" for VCaaS projects
data.createdAtstringISO 8601 creation date

Example request

bash
curl -X POST \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"my-app","description":"A SaaS landing page"}' \
  https://api-accounts.totalum.app/api/v1/vcaas/projects
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "projectId": "my-app",
    "description": "A SaaS landing page",
    "plan": "api",
    "createdAt": "2026-03-11T10:30:00.000Z"
  }
}
Error · 409
json
{
  "errors": {
    "errorCode": "PROJECT_ALREADY_EXISTS",
    "errorMessage": "A project with this name already exists"
  },
  "data": null
}

Error codes

CodeHTTPMeaning
MISSING_PROJECT_ID400projectId is required
INVALID_PROJECT_NAME400Invalid format. Use lowercase letters, numbers, and hyphens. Must start with a letter
INVALID_PROJECT_NAME_LENGTH400Project name must be between 4 and 35 characters
PROJECT_ALREADY_EXISTS409A project with this name already exists
INSUFFICIENT_CREDITS402Not enough credits for this operation
RATE_LIMIT_EXCEEDED429Maximum 10 project creations per 60 seconds

#List Projects

GET/api/v1/vcaas/projectsFree

Get all your projects.

Response fields

FieldTypeDescription
dataarrayArray of project objects
data[].projectIdstringThe project ID
data[].descriptionstringProject description
data[].planstringAlways "api" for VCaaS projects
data[].createdAtstringISO 8601 creation date

Example request

bash
curl -H "api-key: tlm_sk_your_key" \
  https://api-accounts.totalum.app/api/v1/vcaas/projects
Success · 200 OK
json
{
  "errors": null,
  "data": [
    {
      "projectId": "my-app",
      "description": "A SaaS landing page",
      "plan": "api",
      "createdAt": "2026-03-11T10:30:00.000Z"
    }
  ]
}
Error · 400
json
{
  "errors": {
    "errorCode": "LIST_PROJECTS_ERROR",
    "errorMessage": "Internal error listing projects"
  },
  "data": null
}

Error codes

CodeHTTPMeaning
LIST_PROJECTS_ERROR400Internal error listing projects

#Get Project Details

GET/api/v1/vcaas/projects/:projectIdFree

Retrieve full project info including status, deployment, secrets, and URLs. This is the main polling endpoint for project state.

Path parameters

ParameterTypeDescription
:projectIdstringThe project ID

Response fields

FieldTypeDescription
data.projectIdstringThe project ID
data.descriptionstringProject description
data.planstringAlways "api" for VCaaS projects
data.agentProcessStatusstring | undefined"init" (running) | "done" (finished) | "idle" (not started)
data.agentServerStatusstring | undefined"Active" | "Creating" | "Starting" | "Archived" | "Unarchiving" | "Archiving"
data.createdAtstringISO 8601 creation date
data.deploymentobject | nullLatest deployment info, null if never deployed
data.deployment.statusstring"deploying" | "success" | "error"
data.deployment.createdAtstringISO 8601 deployment date
data.deployment.versionIdstring | undefinedVersion ID that was deployed
data.versionRecoveryobject | nullSet while a recoverVersion call is running, otherwise null. This is the canonical signal for "is a version recovery in progress" — do NOT poll agentProcessStatus for recovery (the agent is not involved).
data.versionRecovery.statusstring"recovering" (in progress) | "error" (last recovery failed)
data.versionRecovery.versionIdstringThe version ID currently being / last attempted being recovered
data.versionRecovery.startedAtstringISO 8601 start time
data.versionRecovery.errorMessagestring | undefinedPresent when status="error" — surface this text to the user
data.secretsarrayList of secret names (values never returned)
data.secrets[]._idstringSecret ID (use for deletion)
data.secrets[].secretNamestringEnvironment variable name
data.secrets[].environmentstring"development" | "production" | "both"
data.customDomainobject | nullCustom domain info, null if none configured
data.customDomain.hostnamestringThe custom domain hostname
data.customDomain.statusstring"pending_validation" | "pending_deployment" | "active" | "blocked"
data.customDomain.sslStatusstringSSL certificate status
data.customDomain.dnsRecordsToAddarray | undefinedDNS records to configure: [{ type: "CNAME"|"TXT", name, value }]
data.temporalDevelopmentProjectUrlstring | null | undefinedLive development preview URL (from the running dev server). May be null/undefined if no server has started yet.
data.cachedDevelopmentUrlstring | null | undefinedCached development preview URL (static snapshot, available when server is not active). May be null/undefined if the project has never been archived.
data.developmentUrlFieldToUsestring | null | undefinedWhich field to use for the development preview right now: "temporalDevelopmentProjectUrl" or "cachedDevelopmentUrl". If this field is null or undefined, default to temporalDevelopmentProjectUrl.
data.productionProjectUrlstring | undefinedProduction URL — custom domain if connected, otherwise {projectId}.totalum-project.com
data.totalCreditsSpentnumberTotal credits spent on this project
data.creditLimitsobjectCurrently configured monthly credit limits for this project
data.creditLimits.maxDevelopmentCreditsPerMonthnumber | nullMax development credits/month (null = no limit)
data.creditLimits.maxInfrastructureCreditsPerMonthnumber | nullMax infrastructure credits/month (null = no limit)
data.multiPromptobject | nullPresent only when a multi-prompt batch was started via POST /agent/start with multiPrompt. Same shape as on GET /agent/status.
Preview URL logic

Use data.developmentUrlFieldToUse to decide which development URL to display. It returns the name of the response field containing the best URL for the current state. If it returns "cachedDevelopmentUrl", use data.cachedDevelopmentUrl; if it returns "temporalDevelopmentProjectUrl", use data.temporalDevelopmentProjectUrl. If developmentUrlFieldToUse is null or undefined, always fall back to data.temporalDevelopmentProjectUrl. The cached URL is a static snapshot available when the dev server is down (e.g. archived). Once the server is active and a prompt completes, it switches back to the live URL.

When to refresh the preview

You MUST call GET /projects/:projectId and re-read the preview URL fields on these events: (1) when the user navigates to the project page, (2) when the user manually refreshes the page, and (3) every time a prompt finishes (agent status becomes "done"). The preview URL can change between these events. Always re-read developmentUrlFieldToUse after fetching and use it to pick the correct URL. Never cache the preview URL permanently. If you embed a dev preview URL or the production URL in an iframe, always provide an "Open in new tab" button next to it.

Example request

bash
curl -H "api-key: tlm_sk_your_key" \
  https://api-accounts.totalum.app/api/v1/vcaas/projects/my-app
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "projectId": "my-app",
    "description": "A SaaS landing page",
    "plan": "api",
    "agentProcessStatus": "done",
    "agentServerStatus": "Active",
    "createdAt": "2026-03-11T10:30:00.000Z",
    "deployment": {
      "status": "success",
      "createdAt": "2026-03-11T11:00:00.000Z",
      "versionId": "v_abc123"
    },
    "versionRecovery": null,
    "secrets": [
      {
        "_id": "s1",
        "secretName": "STRIPE_KEY",
        "environment": "both"
      }
    ],
    "customDomain": {
      "hostname": "app.mysite.com",
      "status": "active",
      "sslStatus": "active",
      "dnsRecordsToAdd": [
        { "type": "CNAME", "name": "app", "value": "my-app.totalum-project.com" },
        { "type": "TXT", "name": "_cf-custom-hostname.app", "value": "verification-token" }
      ]
    },
    "temporalDevelopmentProjectUrl": "https://dev-my-app.totalum.app",
    "cachedDevelopmentUrl": "https://my-app-dev-a1b2c3d4.totalum-project.com",
    "developmentUrlFieldToUse": "temporalDevelopmentProjectUrl",
    "productionProjectUrl": "app.mysite.com",
    "totalCreditsSpent": 12.4,
    "creditLimits": {
      "maxDevelopmentCreditsPerMonth": 100,
      "maxInfrastructureCreditsPerMonth": null
    },
    "multiPrompt": null
  }
}
Error · 404
json
{
  "errors": {
    "errorCode": "PROJECT_NOT_FOUND",
    "errorMessage": "Project does not exist or you don't own it"
  },
  "data": null
}

Error codes

CodeHTTPMeaning
MISSING_PROJECT_ID400projectId is required
PROJECT_NOT_FOUND404Project does not exist or you don't own it

#Delete Project

DELETE/api/v1/vcaas/projects/:projectIdFree

Permanently delete a project and all its data.

Path parameters

ParameterTypeDescription
:projectIdstringThe project ID to delete

Response fields

FieldTypeDescription
data.successbooleantrue on successful deletion

Example request

bash
curl -X DELETE -H "api-key: tlm_sk_your_key" \
  https://api-accounts.totalum.app/api/v1/vcaas/projects/my-app
Success · 200 OK
json
{ "errors": null, "data": { "success": true } }
Error · 404
json
{
  "errors": {
    "errorCode": "PROJECT_NOT_FOUND",
    "errorMessage": "Project does not exist or you don't own it"
  },
  "data": null
}

Error codes

CodeHTTPMeaning
MISSING_PROJECT_ID400projectId is required
PROJECT_NOT_FOUND404Project does not exist or you don't own it
PLAN_NOT_API400Only API plan projects can be deleted from this API

#Update Credit Limits

PATCH/api/v1/vcaas/projects/:projectId/credit-limitsFree

Set monthly spending caps per project for development and/or infrastructure credits. By default, projects have no credit limits. Set a field to null to remove that limit.

Path parameters

ParameterTypeDescription
:projectIdstringThe project ID

Body parameters

FieldTypeRequiredDescription
maxDevelopmentCreditsPerMonthnumber or nullNoMax development credits per month (null to remove)
maxInfrastructureCreditsPerMonthnumber or nullNoMax infrastructure credits per month (null to remove)

Response fields

FieldTypeDescription
data.creditLimits.maxDevelopmentCreditsPerMonthnumber or nullCurrent development limit
data.creditLimits.maxInfrastructureCreditsPerMonthnumber or nullCurrent infrastructure limit

Example request

bash
curl -X PATCH \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"maxDevelopmentCreditsPerMonth":500,"maxInfrastructureCreditsPerMonth":100}' \
  https://api-accounts.totalum.app/api/v1/vcaas/projects/my-app/credit-limits

To remove a limit, set it to null:

bash
curl -X PATCH \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"maxDevelopmentCreditsPerMonth":null}' \
  https://api-accounts.totalum.app/api/v1/vcaas/projects/my-app/credit-limits
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "creditLimits": {
      "maxDevelopmentCreditsPerMonth": 500,
      "maxInfrastructureCreditsPerMonth": 100
    }
  }
}
Error · 404
json
{
  "errors": {
    "errorCode": "PROJECT_NOT_FOUND",
    "errorMessage": "Project doesn't exist or you don't own it"
  },
  "data": null
}
Note

By default, projects have no credit limits — all operations are allowed as long as you have credits in your account. When a project reaches its monthly limit, operations in that category return a 403 PROJECT_CREDIT_LIMIT_REACHED error. Limits reset automatically on the 1st of each month.

Error codes

CodeHTTPMeaning
MISSING_LIMIT_FIELDS400At least one of the two limit fields is required
INVALID_LIMIT400Amount must be a positive number
PROJECT_NOT_FOUND404Project doesn't exist or you don't own it