ai
Covers 11 API operations in the ai category.
| Method | Path | Description |
|---|---|---|
| GET | /v1/ai/models | AI model catalog (runlot ai models) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/ai | AI status (runlot ai usage) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/ai | Turns AI back on after it was turned off |
| PATCH | /v1/orgs/{orgSlug}/projects/{projectName}/ai | Lend your team's own subscriptions to this app (runlot ai --byos) |
| DELETE | /v1/orgs/{orgSlug}/projects/{projectName}/ai | Turns off AI (runlot ai delete) |
| GET | /v1/orgs/{orgSlug}/ai/credit | AI credit balance and auto top-up settings (runlot ai credit) |
| GET | /v1/orgs/{orgSlug}/ai/ledger | AI ledger |
| POST | /v1/orgs/{orgSlug}/ai/credit/checkout | Credit top-up checkout |
| PUT | /v1/orgs/{orgSlug}/ai/autotopup | Turns auto top-up on or off |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/ai/dev/run | One env.ai.run from runlot dev (the development lane) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/ai/dev/embed | One env.ai.embed from runlot dev (the development lane) |
GET /v1/ai/models
Every model env.ai can call. Any signed-in user can read it — this is the price list.
There are two tiers. frontier passes the provider's list price straight through
(listPrice: true, zero margin), which is why the provider's name stays in the model id and
provider is included. value models are sold at Runlot's own price, and provider is
not included for them.
Prices are integer microcents per million tokens (1 µ¢ = 1e-8 USD), so that the cost of a small call does not round away to zero.
A model id that is not on this list returns 400 at call time. There is no arbitrary model passthrough.
operationId listAIModels
| Status code | Description | Response body |
|---|---|---|
| 200 | Catalog | object |
| 401 | — | — |
GET /v1/orgs/{orgSlug}/projects/{projectName}/ai
Whether AI is turned on, the four limits, the organization's credit balance, and the last 24
hours of usage. The limits come populated even when AI is off, so you can see what they would
be if you turned it on; granted is the real state.
0 in maxOutputTokens and maxInputTokens means the model decides.
spentMicroCents24h is read from the AI ledger, which is the source of truth for amounts.
Requires viewer or higher.
operationId getAI
| Status code | Description | Response body |
|---|---|---|
| 200 | AI status | AIStatus |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — the service is temporarily unavailable | Error |
POST /v1/orgs/{orgSlug}/projects/{projectName}/ai
This is idempotent. There is no request body — neither the limits nor the model list is a value you set.
Every project has AI from the start; this is the way back after DELETE, and it clears the
turn-off so later deploys keep it. env.ai is attached from the next deployment.
Requires member or higher. Audited as ai.grant.
operationId grantAI
| Status code | Description | Response body |
|---|---|---|
| 200 | Status after turning it on (the existing value if it was already on) | AIStatus |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — the service is temporarily unavailable | Error |
PATCH /v1/orgs/{orgSlug}/projects/{projectName}/ai
Turns on serving this project's anthropic/* and openai/* calls from a Claude or Codex
subscription signed in on a Studio desktop of one of your organization's members. Those
calls cost no credit.
byosCreditFallback decides what happens when no desktop can take the call: on, the
ordinary credit path runs and you are billed as usual; off, the call is a 503
byos_unavailable.
Omitting a field leaves it as it was, so turning lending on does not clear a fallback you had set.
Nothing is lent by default and this setting cannot lend on anybody's behalf: a desktop serves apps only when its own user turned "앱에 모델 빌려주기" on and enabled that model. Running a personal subscription behind an app's end-user traffic may be outside the vendor's consumer terms, and the account at risk is the lender's.
Requires admin — the account that carries that risk belongs to a person, not to the
organization. Audited as ai.byos.
operationId patchAI
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 200 | AI status after the change | AIStatus |
| 400 | Neither field was given | Error |
| 403 | — | — |
| 404 | — | — |
| 409 | ai_not_granted — AI is off for this project, so there is nothing to lend to | Error |
| 503 | no_core — the service is temporarily unavailable | Error |
DELETE /v1/orgs/{orgSlug}/projects/{projectName}/ai
From the next deployment on, there is no env.ai. This is idempotent.
The ledger is not deleted — it is the record of money already spent. The credit balance stays as well: the balance belongs to the organization, and what you are turning off belongs to the project.
Requires admin. Audited as ai.revoke.
operationId revokeAI
| Status code | Description | Response body |
|---|---|---|
| 204 | turned off | — |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — the service is temporarily unavailable | Error |
GET /v1/orgs/{orgSlug}/ai/credit
The balance is in microcents and can go negative: the balance is checked before a call and deducted after it, so a call that has already started can take the balance past zero.
If hasPaymentMethod is false, auto top-up cannot be turned on — there is no saved card, and
the first top-up is always manual, which is what saves the card.
autoTopupsToday and autoTopupPerDay together are the ceiling on a day's automatic spend,
and explain why a top-up did not happen.
Requires member or higher.
operationId getAICredit
| Status code | Description | Response body |
|---|---|---|
| 200 | Credit status | AICredit |
| 403 | — | — |
GET /v1/orgs/{orgSlug}/ai/ledger
The source of truth for AI amounts. kind is call (negative), topup (positive), or
adjust. Pages are cut by ledger_id rather than by time, so two rows written in the same
millisecond are never split across a page boundary.
Requires member or higher.
operationId listAILedger
| Parameter | Location | Required | Type | Description |
|---|---|---|---|---|
limit | query | No | integer | — |
before | query | No | integer | rows before this ledger_id |
lane | query | No | string | Only rows spent by this lane. app is the deployed worker's env.ai, dev is the same app running on a developer's machine or tab, and studio is Studio's own agent turns. Absent means every lane; an unknown value is a 400 rather than an empty page. |
kind | query | No | string | Only rows of this kind. kind=topup&limit=1 is the last top-up, which is otherwise an unbounded walk backwards through a busy day's calls. An unknown value is a 400. |
since | query | No | string | Only rows at or after this instant (RFC 3339). It is an instant and not a date on purpose: the day boundary belongs to the caller, whose midnight is their own zone's. A value that is not RFC 3339 is a 400. |
| Status code | Description | Response body |
|---|---|---|
| 200 | Ledger | object |
| 403 | — | — |
POST /v1/orgs/{orgSlug}/ai/credit/checkout
Returns an embedded checkout URL; the dashboard opens it in an iframe.
A browser returning to returnTo is not proof of payment. The balance rises only once the
payment is confirmed, so poll the balance after the success event.
microCents must be one of the offered top-up amounts — the same list auto top-up uses.
operationId createAICreditCheckout
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 200 | Checkout | object |
| 400 | The top-up amount is not one of the offered amounts, or returnTo is not an allowed address | Error |
| 403 | — | — |
| 501 | billing_off — this installation has no credit product configured | Error |
PUT /v1/orgs/{orgSlug}/ai/autotopup
Turning it on is explicit consent. The screen states "when the balance falls below X, we charge Y to the saved card, at most N times a day" and takes a checkbox, because card network rules require prior consent for off-session charges.
The server checks three things: whether a payment method is saved (409 if not), whether the amount is one of the offered top-up amounts, and whether the threshold is greater than 0 and smaller than the top-up amount. A threshold of 0 makes every automatic charge fail with 402, and a threshold at or above the top-up amount leaves the balance still below the threshold after a top-up, so it would keep topping up until it hit the daily cap.
Requires admin. Audited as ai.autotopup.on / ai.autotopup.off.
operationId setAIAutoTopup
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 200 | Turned on | object |
| 204 | turned off | — |
| 400 | The amount is not an offered top-up amount, or the threshold is 0 or less, or at or above it | Error |
| 403 | — | — |
| 409 | no_payment_method — there is no saved card. Top up manually once first | Error |
POST /v1/orgs/{orgSlug}/projects/{projectName}/ai/dev/run
The call a local runlot dev makes when your worker calls env.ai.run. It is forwarded to the
same lane Studio's local runtime uses: catalog models only, the free plan's caps on every plan
(4,096 output tokens, 30 calls a minute, two at a time), the org's balance checked before and
debited after, recorded in the ledger as lane = dev. No streaming — one JSON answer.
This is not an API for calling models from outside a worker: it needs a member's login and a
project with AI turned on, and it answers env.ai.run's own shape. Requires member or higher.
operationId devAIRun
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 200 | env.ai.run's answer | object |
| 400 | — | — |
| 402 | no_credit — the organization has no AI credit | Error |
| 403 | ai_not_granted — AI is turned off for this project; or not a member | Error |
| 404 | — | — |
| 429 | rate_limited — over the development lane's caps; details.retryAfterSeconds | Error |
POST /v1/orgs/{orgSlug}/projects/{projectName}/ai/dev/embed
The embedding half of the development lane above — the same gate, caps and ledger row. Requires member or higher.
operationId devAIEmbed
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 200 | env.ai.embed's answer | object |
| 400 | — | — |
| 402 | no_credit | Error |
| 403 | ai_not_granted, or not a member | Error |
| 404 | — | — |
| 429 | rate_limited | Error |