Docs
BlogHomeStart building

Spending & Rate Limits

Keep every project's spending and traffic under control.


Three independent controls, all per project. Every limit of an account and a project, and which ones Totalum can raise, is on Limits.

  • Credit limits — a monthly cap on development credits (prompts, publishes, builder actions) and on infrastructure credits (what the running app uses).
  • Feature limits — switch each built-in feature of the app (AI, e-mail, web scraping…) on or off and give it its own monthly budget.
  • Rate limit — requests per minute each visitor (IP) may send to the published site.

A refused call never reaches a provider and costs nothing. Budgets reset on the 1st of each month (UTC).

#Get Credit Limits

GET/api/v1/vcaas/projects/:projectId/credit-limitsapi-keyFree

The project's monthly caps and what it spent this month (UTC), per category.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.creditLimits.maxDevelopmentCreditsPerMonthnumber | nullThe development cap; null = no cap
data.creditLimits.maxInfrastructureCreditsPerMonthnumber | nullThe infrastructure cap; null = no cap
data.usedThisMonthobject | null{ development, infrastructure } credits spent this month; null when it cannot be read right now

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/credit-limits
Success · 200 OK
json
{ "errors": null, "data": { "creditLimits": { "maxDevelopmentCreditsPerMonth": 5000, "maxInfrastructureCreditsPerMonth": 300 }, "usedThisMonth": { "development": 42.5, "infrastructure": 3.1 } } }

#Update Credit Limits

PATCH/api/v1/vcaas/projects/:projectId/credit-limitsapi-keyFree

Set the project's monthly caps. null removes a cap. Defaults for a project created through the API: a development cap of 5,000 credits a month and an infrastructure cap of 300 credits a month. Both can also be set when the project is created (Launch Project, Create Project).

At the development cap a prompt is refused with 403 PROJECT_CREDIT_LIMIT_REACHED, and a running prompt that crosses it stops (keeping what it built). At the infrastructure cap the app's paid built-in calls are refused until the next month or until you raise it. You get the project.credit_limit.reached webhook and an e-mail.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Body parameters

FieldTypeRequiredDescription
maxDevelopmentCreditsPerMonthnumber | nullNo¹Positive number, or null for no cap
maxInfrastructureCreditsPerMonthnumber | nullNo¹Positive number, or null for no cap

¹ At least one of the two.

Response fields

FieldTypeDescription
data.creditLimits.maxDevelopmentCreditsPerMonthnumber | nullWhen sent: the new development cap
data.creditLimits.maxInfrastructureCreditsPerMonthnumber | nullWhen sent: the new infrastructure cap

Example request

curl -X PATCH \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"maxDevelopmentCreditsPerMonth":500,"maxInfrastructureCreditsPerMonth":null}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/credit-limits
Success · 200 OK
json
{ "errors": null, "data": { "creditLimits": { "maxDevelopmentCreditsPerMonth": 500, "maxInfrastructureCreditsPerMonth": null } } }

Error codes

CodeHTTPMeaning
MISSING_LIMIT_FIELDS400Neither cap was sent
INVALID_CREDIT_LIMITS400The body is not an object
INVALID_LIMIT400A cap is not a positive number or null
OWNER_ONLY403Only the account owner can change the caps

#List Projects at Their Limit

GET/api/v1/vcaas/projects/credit-limits/at-limitapi-keyFree

The account's projects that reached a monthly credit limit this month (UTC), with their caps and spend — the list behind the platform's "projects at their monthly limit" notice. Raise one with Update Credit Limits.

Response fields

FieldTypeDescription
data.projectsobject[]The projects at a limit (empty when none)
data.projects[].projectIdstringThe project id
data.projects[].labelstring | nullIts display name
data.projects[].createdViastring | null"ui" (the platform) or "api"
data.projects[].creditLimitsobject{ maxDevelopmentCreditsPerMonth, maxInfrastructureCreditsPerMonth }
data.projects[].usedThisMonthobject{ development, infrastructure } credits spent this month
data.projects[].atLimitobject{ development, infrastructure }: true for each limit reached
data.resetsAtstringWhen the limits reset (the start of next month, UTC)
data.canEditbooleanWhether this caller may raise them (the account owner)

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/credit-limits/at-limit
Success · 200 OK
json
{ "errors": null, "data": { "projects": [{ "projectId": "barber-bookings", "label": "Barber bookings", "createdVia": "api", "creditLimits": { "maxDevelopmentCreditsPerMonth": 5000, "maxInfrastructureCreditsPerMonth": 300 }, "usedThisMonth": { "development": 812.4, "infrastructure": 300.2 }, "atLimit": { "development": false, "infrastructure": true } }], "resetsAt": "2026-11-01T00:00:00.000Z", "canEdit": true } }
End of List Projects at Their LimitNext endpointGETGet Feature Limits

#Get Feature Limits

GET/api/v1/vcaas/projects/:projectId/limitsapi-keyFree

Every built-in feature of the app: whether it is on, its monthly budgets and what it used this month. Every feature is on by default, with no budget of its own.

FeatureCovers
aiEvery AI call below
ai_textChat, structured output, vision, embeddings, reranking
ai_imageImage generation and editing
ai_videoVideo generation
speechSpeech-to-text and text-to-speech
webWeb scraping, crawling, search, extraction
browserCloud browser sessions
scanDocument scanning (OCR)
storageFile uploads and stored files
emailSending e-mail
pdfPDFs, screenshots, SEO pings
vectorsVector search
realtimeReal-time rooms
cronScheduled job runs
mobileMobile app builds
databaseThe database (cannot be switched off)
workerThe site itself (cannot be switched off)
allEverything: one switch and one total monthly budget, in credits

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.planstringThe account's plan
data.featuresobjectFeature → its entry
data.features.<feature>.enabledbooleanfalse = switched off
data.features.<feature>.parentstring | undefined"ai" for ai_text, ai_image, ai_video (the parent's switch and budget also apply)
data.features.<feature>.monthlyCreditCapnumber | undefinedBudget in credits, when set
data.features.<feature>.monthlyUnitCapnumber | undefinedBudget in the feature's unit, when set
data.features.<feature>.unitstringcalls, recipients, pages, bytes, session_minutes, room_minutes, executions, builds, rows, requests or credits
data.features.<feature>.consumedobject{ credits, units } this month
data.features.<feature>.periodobject{ from, to }: the month
data.features.<feature>.planCeilingobjectHighest budget your plan allows: { monthlyCreditCap, monthlyUnitCap } (null = none)
data.features.<feature>.sourcestringplan (default), user (you set it) or ceo (set by Totalum support)

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/limits
Success · 200 OK
json
{
  "errors": null,
  "data": {
    "plan": "starter",
    "features": {
      "ai_video": { "enabled": false, "parent": "ai", "unit": "calls", "consumed": { "credits": 0, "units": 0 }, "period": { "from": "2026-10-01T00:00:00.000Z", "to": "2026-11-01T00:00:00.000Z" }, "planCeiling": { "monthlyCreditCap": null, "monthlyUnitCap": 20 }, "source": "user" },
      "all": { "enabled": true, "monthlyCreditCap": 300, "unit": "credits", "consumed": { "credits": 12.4, "units": 0 }, "period": { "from": "2026-10-01T00:00:00.000Z", "to": "2026-11-01T00:00:00.000Z" }, "planCeiling": { "monthlyCreditCap": null, "monthlyUnitCap": null }, "source": "user" }
    }
  }
}

The answer lists every feature; the example shows two.

Concurrency. Besides budgets, two features have per-project concurrency limits: browser (3 open sessions, 1 on the free plan; a call up to 60 s) and web (1 call at a time, up to 10 s). A call over the limit waits in a fair queue, then answers 429 CONCURRENCY_QUEUE_TIMEOUT (or CONCURRENCY_QUEUE_FULL) with errorDetails.retryAfter. A project makes at most 100 built-in calls per second in total; above it a call answers 429 RATE_LIMITED with Retry-After.

Busy hours. When an app spends half of what would trigger the emergency stop within one hour, its image, video and speech AI calls answer 429 AI_MEDIA_PAUSED_THIS_HOUR until that hour ends (UTC), with Retry-After; text AI and everything else keep working. They come back by themselves at the next hour; releasing an emergency-stop pause also brings them back.

End of Get Feature LimitsNext endpointPUTSet Feature Limits

#Set Feature Limits

PUT/api/v1/vcaas/projects/:projectId/limitsapi-keyFree

Switch features on or off and set monthly budgets. Send only the features you change; null removes a budget. Account owner only. Setting the budget of all also sets the project's infrastructure credit limit.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Body parameters

FieldTypeRequiredDescription
featuresobjectYesFeature → { enabled?, monthlyCreditCap?, monthlyUnitCap? }

Response fields

FieldTypeDescription
data.planstringThe account's plan
data.featuresobjectEvery feature after the change, as in Get Feature Limits

Example request

curl -X PUT \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"features":{"ai_video":{"enabled":false},"ai":{"monthlyCreditCap":200},"all":{"monthlyCreditCap":500}}}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/limits
Success · 200 OK
json
{ "errors": null, "data": { "plan": "starter", "features": { "ai_video": { "enabled": false, "parent": "ai", "unit": "calls", "consumed": { "credits": 0, "units": 0 }, "period": { "from": "2026-10-01T00:00:00.000Z", "to": "2026-11-01T00:00:00.000Z" }, "planCeiling": { "monthlyCreditCap": null, "monthlyUnitCap": 20 }, "source": "user" } } } }

What the app's code gets when a feature is refused (show a message, do not retry):

App errorHTTPMeaning
FEATURE_DISABLED403The feature (or ai, or all) is switched off; errorDetails.feature names it
FEATURE_LIMIT_REACHED429Its budget is spent; errorDetails: feature, limit, used, unit, resetsAt
AI_MEDIA_PAUSED_THIS_HOUR429The app used a lot of credits this hour, so image, video and speech AI wait until the hour ends (UTC); Retry-After and errorDetails.resetsAt say when. Text AI and everything else keep working

Error codes

CodeHTTPMeaning
UNKNOWN_FEATURE400Not a feature of the table above
INVALID_LIMIT400A negative or non-integer budget, or a monthlyUnitCap on all
FEATURE_NOT_DISABLABLE400database and worker cannot be switched off
LIMIT_ABOVE_PLAN_CEILING400A budget above your plan's ceiling
OWNER_ONLY403Only the account owner can change budgets
End of Set Feature LimitsNext endpointGETGet Rate Limit

#Get Rate Limit

GET/api/v1/vcaas/projects/:projectId/rate-limitapi-keyFree

How many requests per minute each visitor (IP) may send to the published site.

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Response fields

FieldTypeDescription
data.perIpPerMinutenumber | nullRequests per minute per IP; null = off
data.allowlistCidrsstring[]IP ranges that are never limited (up to 50)
data.verifiedBotsExemptbooleanSearch engines and other verified bots are not limited
data.planDefaultnumberYour plan's default
data.planMaxnumber | nullThe highest value your plan allows
data.canDisablebooleanWhether your plan may switch it off
data.sourcestring"plan" or "user"

Example request

curl -H "api-key: tlm_sk_your_key" \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/rate-limit
Success · 200 OK
json
{ "errors": null, "data": { "perIpPerMinute": 5000, "allowlistCidrs": [], "verifiedBotsExempt": true, "planDefault": 5000, "planMax": 60000, "canDisable": true, "source": "plan" } }

#Update Rate Limit

PATCH/api/v1/vcaas/projects/:projectId/rate-limitapi-keyFree

Change the per-visitor limit, the allowlist or the bot exemption. Send only what changes.

Separately, each visitor may cause at most 20 paid built-in calls a minute (AI, web, browser, screenshots), so nobody can spend the project's credits by calling a public AI page in a loop; over it the app's call answers 429 RATE_LIMIT_EXCEEDED with Retry-After. Ask the agent to change it ("let each visitor send 60 AI messages a minute").

Path parameters

ParameterTypeDescription
projectIdstringThe project id

Body parameters

FieldTypeRequiredDescription
perIpPerMinutenumber | nullNoFrom 10 to 60,000 on paid plans (5,000 on the free plan, the default everywhere); null = off (paid plans only)
allowlistCidrsstring[]NoUp to 50 IP ranges (203.0.113.0/24)
verifiedBotsExemptbooleanNoExempt verified bots

Response fields

FieldTypeDescription
dataobjectThe setting after the change, as in Get Rate Limit

Example request

curl -X PATCH \
  -H "api-key: tlm_sk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"perIpPerMinute":300}' \
  https://builder-api.totalum.app/api/v1/vcaas/projects/barber-bookings/rate-limit
Success · 200 OK
json
{ "errors": null, "data": { "perIpPerMinute": 300, "allowlistCidrs": [], "verifiedBotsExempt": true, "planDefault": 5000, "planMax": 60000, "canDisable": true, "source": "user" } }

Error codes

CodeHTTPMeaning
VALIDATION_ERROR400A value is out of range
RATE_LIMIT_ABOVE_PLAN400Above your plan's maximum (errorDetails.planMax)
INVALID_CIDR400An allowlist entry is not an IPv4 or IPv6 range
RATE_LIMIT_DISABLE_NOT_ALLOWED403The free plan cannot switch the limit off
End of Update Rate Limit Back to top