Describes the structure of API request and response bodies. Each schema is referenced by the API operations that use it.
| Field | Type | Required | Description |
|---|
store | boolean | Yes | — |
features | string[] | Yes | — |
| Field | Type | Required | Description |
|---|
key | string | Yes | A built-in $ key or a bare user key (dot-separated for nesting) |
op | string | Yes | — |
value | object | No | String, number or boolean; omitted for exists/not_exists |
| Field | Type | Required | Description |
|---|
op | string | Yes | count, count_distinct, min, max, sum, avg, stddev, variance, or p001–p999 (two digits are percent, three per mille) |
key | string | No | — |
| Field | Type | Required | Description |
|---|
timeframe | object | No | — |
view | string | No | — |
dataset | string | No | What a calculations view aggregates; inferred from the keys when omitted |
filters | ObsFilter[] | No | — |
search | string | No | — |
calculations | ObsCalc[] | No | — |
groupBy | string[] | No | — |
orderBy | object | No | — |
limit | integer | No | — |
granularity | integer | No | Seconds per time bucket (calculations view) |
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
kind | string | Yes | — |
key | string | No | — |
op | string | No | — |
| Field | Type | Required | Description |
|---|
available | boolean | Yes | — |
view | string | No | — |
dataset | string | No | — |
from | string | No | — |
to | string | No | — |
clamped | boolean | No | The timeframe began before the plan's retention and was shortened |
columns | ObsColumn[] | No | — |
rows | object[] | No | Calculations rows are keyed by column name (t, g0…, c0…); invocations rows are ObsInvocation, events rows ObsEvent, traces rows trace summaries |
| Field | Type | Required | Description |
|---|
key | string | Yes | — |
type | string | Yes | — |
builtin | boolean | Yes | — |
count | integer | No | — |
| Field | Type | Required | Description |
|---|
available | boolean | Yes | — |
view | string | No | — |
since | string | No | — |
until | string | No | — |
keys | ObsKey[] | No | — |
| Field | Type | Required | Description |
|---|
available | boolean | Yes | — |
key | string | No | — |
values | object[] | No | — |
| Field | Type | Required | Description |
|---|
pattern | string | Yes | — |
events | integer | Yes | — |
sample | string | Yes | — |
level | string | Yes | — |
firstSeen | string | Yes | — |
new | boolean | Yes | — |
trend | number | Yes | Events in the window's second half over its first half |
| Field | Type | Required | Description |
|---|
available | boolean | Yes | — |
since | string | No | — |
until | string | No | — |
patterns | ObsPattern[] | No | — |
| Field | Type | Required | Description |
|---|
ts | string | Yes | — |
epoch | integer | Yes | — |
generation | integer | Yes | — |
pid | integer | Yes | — |
role | string | No | — |
exitCode | integer | Yes | — |
signal | string | No | — |
oomKill | integer | Yes | — |
oomLevel | string | No | — |
peakBytes | integer | No | — |
limitBytes | integer | No | — |
cause | string | Yes | — |
| Field | Type | Required | Description |
|---|
requestId | string | Yes | — |
ts | string | Yes | — |
eventType | string | Yes | — |
deploymentId | string | No | — |
deploymentVersion | integer | No | — |
method | string | No | — |
host | string | No | — |
path | string | No | — |
route | string | No | — |
status | integer | No | — |
wallMs | number | Yes | — |
reqBytes | integer | No | Request body bytes, when known. |
respBytes | integer | No | Response body bytes, when known. |
outcome | string | Yes | Resolved: a workerExited record takes its process exit's cause |
recordedOutcome | string | Yes | — |
outcomeSignal | string | No | — |
upstream | string | No | — |
woke | boolean | No | — |
wakeMs | number | No | — |
country | string | No | — |
region | string | No | — |
sampled | boolean | Yes | — |
synthetic | boolean | No | — |
userHash | string | No | — |
userAgent | string | No | — |
attrs | object | No | — |
exit | ObsExit | No | — |
cpuMs | number | No | JavaScript CPU the invocation spent, in milliseconds (thread CPU while its JavaScript ran, including its waitUntil work; database statements and runtime work between turns are not in it). Null when it was not measured: a runtime without per-request CPU, an answer front gave in the app's place, or a queue batch, whose reading cannot carry the batch's request ID. |
| Field | Type | Required | Description |
|---|
ts | string | Yes | — |
requestId | string | No | — |
level | string | Yes | — |
source | string | Yes | — |
message | string | Yes | — |
fields | object | No | — |
exceptionName | string | No | — |
exceptionStack | string | No | — |
truncated | boolean | No | — |
redacted | boolean | No | — |
weight | integer | Yes | How many offered events this stored one stands for (past the daily cap) |
deploymentVersion | integer | No | — |
eventType | string | No | — |
| Field | Type | Required | Description |
|---|
spanId | string | Yes | — |
parentSpanId | string | No | — |
name | string | Yes | — |
kind | string | Yes | — |
start | string | Yes | — |
startOffsetMs | number | Yes | — |
durationMs | number | Yes | — |
status | string | Yes | — |
peer | string | No | — |
attrs | object | No | — |
| Field | Type | Required | Description |
|---|
available | boolean | Yes | — |
requestId | string | No | — |
invocation | ObsInvocation | No | — |
events | ObsEvent[] | No | — |
spans | ObsSpan[] | No | — |
errors | object[] | No | — |
histories | object[] | No | — |
links | object | No | — |
| Field | Type | Required | Description |
|---|
scope | string | No | Fixed at creation |
name | string | Yes | — |
description | string | No | — |
tags | string[] | No | — |
body | ObsQuery | Yes | — |
| Field | Type | Required | Description |
|---|
queryId | string | Yes | — |
projectId | string | No | — |
scope | string | Yes | — |
name | string | Yes | — |
description | string | Yes | — |
tags | string[] | Yes | — |
body | ObsQuery | Yes | — |
createdBy | string | No | — |
createdAt | string | Yes | — |
updatedAt | string | Yes | — |
stars | integer | Yes | — |
starred | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
queries | SavedQuery[] | Yes | — |
limit | integer | Yes | -1 is no limit |
| Field | Type | Required | Description |
|---|
type | string | Yes | — |
enabled | boolean | No | — |
source | string | No | — |
target | string | No | — |
pattern | string | No | — |
delimiter | string | No | — |
from | string | No | — |
to | string | No | — |
keepOriginal | boolean | No | — |
field | string | No | — |
mapping | object | No | — |
filter | ObsFilter[] | No | — |
rate | number | No | — |
| Field | Type | Required | Description |
|---|
processors | ObsProcessor[] | Yes | — |
version | integer | Yes | — |
source | string | Yes | — |
updatedAt | string | No | — |
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
pattern | string | Yes | — |
action | string | Yes | — |
enabled | boolean | No | — |
| Field | Type | Required | Description |
|---|
builtins | object | No | Per built-in rule (jwt, bearer, api_key, email, card, kr_rrn): off, redact, hash or drop. Absent redacts. |
rules | ObsScanRule[] | No | — |
| Field | Type | Required | Description |
|---|
builtins | object | Yes | — |
rules | ObsScanRule[] | Yes | — |
available | string[] | Yes | — |
source | string | Yes | — |
| Field | Type | Required | Description |
|---|
result | string | Yes | — |
dropped | boolean | Yes | — |
hits | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
name | string | No | — |
kind | string | No | — |
dataset | string | No | — |
filter | ObsFilter[] | No | — |
valueKey | string | No | The numeric field a distribution records |
groupBy | string[] | No | — |
enabled | boolean | No | — |
source | string | No | — |
updatedAt | string | No | — |
A live-tail line under format=json: the stored log event's shape
| Field | Type | Required | Description |
|---|
type | string | Yes | — |
ts | string | Yes | — |
level | string | Yes | — |
source | string | Yes | — |
message | string | Yes | — |
fields | object | No | — |
requestId | string | No | — |
epoch | integer | No | — |
generation | integer | No | — |
truncated | boolean | No | — |
| Field | Type | Required | Description |
|---|
pipeline | ObsProcessor[] | No | — |
scanner | ObsScannerConfig | No | — |
logMetrics | ObsLogMetric[] | No | — |
| Field | Type | Required | Description |
|---|
issueId | string | Yes | — |
eventId | string | Yes | — |
at | string | Yes | — |
issueAvailable | boolean | Yes | — |
eventAvailable | boolean | Yes | — |
shortId | string | No | — |
title | string | No | — |
status | string | No | Current surviving issue status |
| Field | Type | Required | Description |
|---|
version | integer | Yes | — |
deploymentId | string | Yes | — |
kind | string | Yes | — |
windowStart | string | Yes | — |
windowEnd | string | Yes | — |
issues | ReleaseIssueTransition[] | Yes | — |
cursor | string | No | — |
| Field | Type | Required | Description |
|---|
unjoinedErrorRequests | integer | Yes | — |
version | integer | Yes | — |
deploymentId | string | Yes | — |
commit | string | No | — |
live | boolean | Yes | — |
requests | integer | Yes | — |
httpFailures | integer | Yes | — |
recordedErrorRequests | integer | Yes | — |
failedRequests | integer | Yes | — |
unknownStatuses | integer | Yes | — |
dropped | integer | Yes | — |
observedErrorFreePercent | number | Yes | — |
adoptionPercent | number | Yes | — |
knownUsers | integer | Yes | — |
knownFailedUsers | integer | Yes | — |
knownUserRequests | integer | Yes | — |
knownUsersErrorFreePercent | number | Yes | — |
sessions | integer | No | Browser-agent tab sessions with an attributed page view of this release in the window |
erroredSessions | integer | No | — |
crashFreeSessionsPercent | number | No | Sessions with no reported browser error; untrusted browser claims |
newIssues | integer | Yes | — |
regressions | integer | Yes | — |
insight | string | Yes | — |
insightReason | string | Yes | — |
| Field | Type | Required | Description |
|---|
available | boolean | Yes | — |
source | string | Yes | — |
points | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
note | string | Yes | — |
events | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
releases | ReleaseHealthRelease[] | Yes | — |
windowStart | string | Yes | — |
windowEnd | string | Yes | — |
population | string | Yes | — |
coverage | string | Yes | — |
errorDefinition | string | Yes | — |
userDefinition | string | Yes | — |
sessionDefinition | string | No | — |
crashFreeRequestsPercent | number | Yes | — |
crashFreeUsersPercent | number | Yes | — |
unknownLoss | boolean | Yes | — |
receiptRetentionHours | integer | Yes | — |
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
deploymentId | string | Yes | — |
requestId | string | Yes | — |
epoch | integer | Yes | — |
at | string | Yes | — |
status | integer | Yes | — |
userHash | string | No | — |
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
deploymentId | string | Yes | — |
count | integer | Yes | — |
| Field | Type | Required | Description |
|---|
nodeId | string | Yes | — |
batchId | string | Yes | — |
at | string | Yes | — |
receipts | ReleaseHealthReceipt[] | Yes | — |
losses | ReleaseHealthLoss[] | Yes | — |
unknownLoss | integer | Yes | — |
| Field | Type | Required | Description |
|---|
accepted | integer | Yes | — |
duplicate | integer | Yes | — |
rejected | integer | Yes | — |
dropped | integer | Yes | — |
| Field | Type | Required | Description |
|---|
proposalSha | string | Yes | — |
appliedCommit | string | Yes | — |
sourceRoot | string | Yes | — |
databaseMode | string | Yes | — |
policy | string | Yes | — |
acknowledgeExecution | boolean | Yes | — |
idempotencyKey | string | Yes | — |
| Field | Type | Required | Description |
|---|
jobId | string | Yes | — |
proposalId | string | Yes | — |
state | string | Yes | — |
policy | string | Yes | — |
commit | string | Yes | — |
sourceRoot | string | Yes | — |
databaseMode | string | Yes | — |
childProjectId | string | No | — |
deploymentId | string | No | — |
verificationOnly | boolean | Yes | — |
publicAccess | string | Yes | — |
safeReason | string | No | — |
createdAt | string | Yes | — |
expiresAt | string | Yes | — |
replayed | boolean | No | — |
verification | ErrorFixPreviewVerification | No | — |
| Field | Type | Required | Description |
|---|
method | string | Yes | — |
path | string | Yes | Absolute path only, no query/body/auth/cookies/redirects. A private handler-only probe, not a public URL check. |
acknowledgeRequest | boolean | Yes | — |
idempotencyKey | string | Yes | — |
| Field | Type | Required | Description |
|---|
verificationId | string | Yes | — |
state | string | Yes | — |
method | string | Yes | — |
path | string | Yes | — |
requestId | string | No | — |
httpStatus | integer | No | — |
bodySha256 | string | No | — |
truncated | boolean | No | — |
observationSeconds | integer | Yes | — |
safeReason | string | No | — |
replayed | boolean | No | — |
| Field | Type | Required | Description |
|---|
id | string | Yes | — |
name | string | Yes | — |
enabled | boolean | Yes | — |
trigger | string | Yes | release sends one summary per observed live switch after its first 16 minutes: distinct new/regressed issue counts from the recorded transition ledger and at most 20 surviving issues. Opt-in; takes no threshold, window, digest or event filters. |
threshold | integer | No | — |
windowMinutes | integer | No | — |
cooldownMinutes | integer | Yes | — |
digestMinutes | integer | No | Optional explicit warning-level opt-in. Omitted or 0 stays immediate. 5/15/60 uses prospective fixed UTC windows; at most 20 issue summaries per project/rule/destination/current authorized audience, with stable retry identity. Requires level warning; no backfill or broader email recipients. |
environment | string | No | — |
origin | string | No | — |
level | string | No | — |
assigneeUserId | string | No | — |
tags | object | No | — |
destinations | string[] | Yes | — |
| Field | Type | Required | Description |
|---|
id | string | Yes | — |
name | string | Yes | — |
kind | string | Yes | — |
enabled | boolean | Yes | — |
secretPresent | boolean | Yes | — |
version | integer | Yes | — |
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
kind | string | Yes | — |
enabled | boolean | Yes | — |
secret | string | No | Write-only public HTTPS URL, PagerDuty routing key, or Opsgenie API key (prefix eu: for the EU instance). Empty on update preserves the existing secret. Email never takes a secret. |
acknowledgeExternalDisclosure | boolean | No | Required true when enabling an external destination. The endpoint receives minimal scrubbed issue data. |
| Field | Type | Required | Description |
|---|
alert | number | No | — |
warn | number | No | — |
alertRecovery | number | No | A group in alert stays there until it crosses this, when set. |
warnRecovery | number | No | — |
| Field | Type | Required | Description |
|---|
longMinutes | integer | Yes | — |
shortMinutes | integer | Yes | — |
factor | number | Yes | — |
state | string | Yes | — |
Only the fields of the monitor's type may be set. Series types (metric, change, anomaly, apm, database, infra) take source, metric (apm, database, infra) or name and aggregation (custom), and filter. log takes filter (level, source, event_type, contains); error takes filter.origin; uptime checkId; cron the expression; slo_burn sloId and burnWindows (default 1 h/5 min at 14.4x alert, 6 h/30 min at 6x warn); composite expression (&&, ||, !, parentheses) and monitors (identifier to monitor ID or key); issue an Errors alert rule.
| Field | Type | Required | Description |
|---|
source | string | No | — |
metric | string | No | apm: requests, errors, error_rate (percent), status_4xx, status_5xx, latency_avg, latency_p50, latency_p75, latency_p90, latency_p95, latency_p99, latency_p999. database: calls, errors, latency_avg, latency_p50, latency_p95, latency_p99, wait_share (percent of route wall time). infra: memory_pct, memory_bytes, psi_cpu_some, psi_mem_some, psi_mem_full, psi_io_some, oom_kills, oom_exits, high_events, cpu_throttled_us. |
name | string | No | — |
aggregation | string | No | — |
filter | object | No | — |
changeMinutes | integer | No | — |
changeMode | string | No | — |
direction | string | No | — |
checkId | string | No | — |
cron | string | No | — |
sloId | string | No | — |
burnWindows | MonitorBurnWindow[] | No | — |
expression | string | No | — |
monitors | object | No | — |
rule | object | No | An Errors alert rule (ErrorAlertRule without id, name, enabled and destinations, which come from the monitor). |
| Field | Type | Required | Description |
|---|
windowMinutes | integer | No | — |
frequencyMinutes | integer | No | — |
evaluationDelaySeconds | integer | No | — |
comparator | string | No | — |
thresholds | MonitorThresholds | No | — |
groupBy | string[] | No | One alert per group, e.g. [route]. |
noData | object | No | — |
renotifyMinutes | integer | No | — |
requireFullWindow | boolean | No | — |
muteAfterDeployMinutes | integer | No | — |
| Field | Type | Required | Description |
|---|
id | string | No | — |
key | string | No | Stable name; required in .runlot/monitors files. |
name | string | Yes | — |
type | string | Yes | — |
query | MonitorQuery | No | — |
options | MonitorOptions | No | — |
message | string | No | Template: {{value}}, {{threshold}}, {{state}}, {{monitor.name}}, {{project}}, {{link}} and each group dimension such as {{route}}. |
tags | string[] | No | — |
priority | integer | No | — |
destinations | string[] | No | Alert destination IDs or names. |
enabled | boolean | No | — |
source | string | No | — |
createdBy | string | No | — |
createdAt | string | No | — |
updatedAt | string | No | — |
Type: Monitor & object
| Field | Type | Required | Description |
|---|
key | string | Yes | — |
tags | object | No | — |
state | string | Yes | — |
since | string | Yes | — |
value | number | No | — |
lastEval | string | Yes | — |
lastDataAt | string | No | — |
notifiedAt | string | No | — |
Type: MonitorView & object
| Field | Type | Required | Description |
|---|
monitors | MonitorView[] | Yes | — |
limit | integer | Yes | — |
code | object | No | The last live deployment whose .runlot/monitors were applied, and why it was refused when it was. |
| Field | Type | Required | Description |
|---|
monitors | Monitor[] | Yes | — |
path | string | Yes | — |
| Field | Type | Required | Description |
|---|
events | object[] | Yes | — |
deliveries | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
queued | string[] | Yes | — |
| Field | Type | Required | Description |
|---|
id | string | No | — |
scope | object | Yes | — |
start | string | Yes | — |
end | string | No | — |
recurrence | object | No | — |
message | string | No | — |
createdBy | string | No | — |
createdAt | string | No | — |
active | boolean | No | — |
| Field | Type | Required | Description |
|---|
downtimes | Downtime[] | Yes | — |
| Field | Type | Required | Description |
|---|
id | string | No | — |
name | string | Yes | — |
description | string | No | — |
type | string | Yes | — |
target | number | Yes | Percent, e.g. 99.9. |
windows | integer[] | No | — |
definition | object | Yes | — |
tags | string[] | No | — |
createdBy | string | No | — |
createdAt | string | No | — |
updatedAt | string | No | — |
| Field | Type | Required | Description |
|---|
days | integer | Yes | — |
from | string | Yes | — |
to | string | Yes | — |
total | number | Yes | Requests (request SLO) or seconds (monitor SLO). |
bad | number | Yes | — |
sli | number | No | Percent good. |
budgetRemaining | number | No | Percent of the error budget left; negative when overspent. |
series | object[] | Yes | — |
Type: SLO & object
| Field | Type | Required | Description |
|---|
slos | SLOReport[] | Yes | — |
limit | integer | Yes | — |
| Field | Type | Required | Description |
|---|
rules | ErrorAlertRule[] | Yes | — |
destinations | ErrorAlertDestination[] | Yes | — |
windowSemantics | string | Yes | — |
customRulesReplaceDefaultMail | boolean | Yes | — |
outboxDropped | integer | Yes | — |
| Field | Type | Required | Description |
|---|
emailEnabled | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
id | string | Yes | — |
issueId | string | Yes | Issue UUID for an individual delivery; empty for a cross-issue digest. |
digestId | string | No | — |
digestMinutes | integer | No | — |
issueCount | integer | No | Bounded number of surviving digest member issues, not billing. |
release | integer | No | Deployment version of a release summary delivery. |
trigger | string | Yes | — |
state | string | Yes | — |
attempts | integer | Yes | — |
lastError | string | Yes | — |
createdAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
deliveries | ErrorAlertDelivery[] | Yes | — |
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
eventId | string | Yes | — |
requestId | string | Yes | — |
release | string | Yes | — |
pageHash | string | Yes | — |
ipHash | string | Yes | — |
docs/custom-sign-in.md §12.3. Every field optional; empty is the default.
| Field | Type | Required | Description |
|---|
name | string | No | — |
logo | string | No | http(s) URL |
color | string | No | — |
logoDark | string | No | https URL |
theme | string | No | — |
layout | string | No | — |
buttonShape | string | No | — |
background | object | No | — |
copy | object | No | — |
links | object | No | — |
defaultLang | string | No | — |
methods | string[] | No | — |
| Field | Type | Required | Description |
|---|
brand | SignInBrand | Yes | — |
effectiveMethods | string[] | Yes | — |
| Field | Type | Required | Description |
|---|
defaultBranch | string | Yes | The repository's current default branch. If this ever disagrees with Repo.defaultBranch, this value is the correct one. |
refs | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
path | string | Yes | Path relative to the repository root |
kind | string | Yes | — |
size | integer | Yes | Size in bytes. Files only — directories are 0 |
oid | string | Yes | — |
| Field | Type | Required | Description |
|---|
ref | string | Yes | — |
commit | string | Yes | — |
path | string | Yes | — |
entries | RepoTreeEntry[] | Yes | — |
truncated | boolean | Yes | True when the directory had more than 1000 entries and the list was cut short |
| Field | Type | Required | Description |
|---|
ref | string | Yes | — |
commit | string | Yes | — |
path | string | Yes | — |
oid | string | Yes | — |
size | integer | Yes | — |
binary | boolean | Yes | The file is binary (a NUL byte, or not valid UTF-8). content is empty |
tooLarge | boolean | Yes | The file exceeds 1 MiB, so content is not included |
content | string | Yes | — |
| Field | Type | Required | Description |
|---|
oid | string | Yes | — |
message | string | Yes | — |
author | string | Yes | — |
email | string | Yes | — |
timestamp | string | Yes | — |
A repository name. It becomes a URL path segment, so it cannot contain .. or a
slash, and it cannot start with a dot. It is broader than a project name — uppercase
letters, dots and underscores are allowed.
Type: string
Who can read the repository. New repositories are private. public means
anyone may clone it anonymously.
Type: string
What a token may do over git, derived from its scopes when it is issued. A token
inherits its owner's permissions and can only narrow them, never widen them.
repo:none is a token carrying no repository scope at all — a deploy-only CI
credential. It clones nothing private and pushes nothing.
Type: string
RFC 6749 §5.1.
| Field | Type | Required | Description |
|---|
access_token | string | Yes | An Ed25519 JWT (RFC 9068). Fifteen minutes. |
token_type | string | Yes | — |
expires_in | integer | Yes | Seconds. It is present so a client refreshes ahead of time instead of discovering expiry as a 401 in the middle of something. |
refresh_token | string | Yes | Rotated: using one invalidates it and returns the next. |
scope | string | Yes | — |
RFC 6749 §5.2. Not this document's error envelope: /oauth/token and
/oauth/revoke are read by generic OAuth clients that cannot parse ours.
| Field | Type | Required | Description |
|---|
error | string | Yes | — |
error_description | string | No | — |
One connected app, as /account/apps lists it (docs/studio.md §8.4).
| Field | Type | Required | Description |
|---|
sid | string | Yes | The grant's session id. It is the sid claim in every access token it minted, and what revocation is keyed by. |
clientId | string | Yes | — |
clientName | string | Yes | — |
deviceName | object | Yes | What the device called itself when it connected. Null for a client that did not say. |
scopes | ApiScope[] | Yes | — |
createdAt | string | Yes | — |
lastUsedAt | object | Yes | Null when the grant has never been used — a sign-in that was never followed by a call. |
One permission a personal access token carries. Scopes are checked on every route:
the token acts as its owner, subject to that person's organization role, and the scope
set then narrows what they may do with this particular credential.
| scope | what it opens |
|---|
project:read | projects, deployments, logs, usage, secret names, cron, queues (overview, history, peek), hostnames, the deployment access policy |
errors:read | error issues, events, settings and stored diagnoses, without other project reads |
errors:pii | admin-only masked replays. Implies errors:read, never deploy |
observability:read | a project's metrics, traces and logs, its caps, export destinations and data page. Implied by project:read |
observability:pii | user hashes and emails, IPs where stored, replays and unscrubbed fields in observability data. Implies observability:read |
observability:admin | observability configuration: exports, rehydration, per-project role overrides and the audit trail. Implies observability:read |
deploy | deploy, rollback, create a project, write and delete secrets, purge and redrive a queue |
db:read | the connection string, the wire credentials list, generations, operations |
db:write | issue a wire credential, export, restore, drop the database. Implies db:read |
repo:read | clone and fetch over HTTPS, and the repository browse routes |
repo:write | push, and create, rename or delete a repository. Implies repo:read |
org:admin | everything the person can do — members, billing, domains, DNS, granting storage/email/AI |
project:read continues to include ordinary error reads for compatibility, but not
errors:pii. Full org:admin tokens include both. Sensitive replay reads still
require the admin organization role. OAuth clients do not gain these PAT scopes.
Any route not listed in the table requires org:admin.
deploy does not include project:read. project:read opens your worker's logs,
which can contain anything your code prints, so a deploy credential does not get them
unless you ask. A CI token that needs both names both:
--scope deploy --scope project:read.
Type: string
| Field | Type | Required | Description |
|---|
repoId | string | Yes | — |
orgSlug | Slug | Yes | — |
project | Slug | Yes | The project this repository belongs to. Names are unique within a project. |
name | RepoName | Yes | — |
visibility | RepoVisibility | Yes | — |
defaultBranch | string | Yes | The repository's default branch. This is a cached copy; if it ever disagrees with the repository itself, the repository wins and this value is corrected later. |
sizeBytes | integer | Yes | Approximate repository size, used for quota enforcement. |
lastPushedAt | string | No | — |
createdAt | string | Yes | — |
cloneUrl | string | No | The HTTPS clone URL, https://<git-domain>/<org>/<project>/<repo>.git. Empty string when git hosting has no domain configured. |
sshUrl | string | No | The SSH clone URL, git@<git-ssh-host>:<org>/<project>/<repo>.git. Empty string when git hosting has no SSH host configured. |
| Field | Type | Required | Description |
|---|
ref | string | Yes | — |
old | string | No | The oid the ref pointed to before. Null means the ref was created. This is what you need to recover commits lost to a force-push. |
new | string | No | The oid the ref points to now. Null means the ref was deleted |
forced | boolean | Yes | The push was a non-fast-forward. There are no protected branches yet, so such a push is recorded rather than blocked. |
actorUser | string | No | — |
createdAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
enabled | boolean | Yes | — |
branch | string | Yes | The branch a push must update for a build to start. When configured is false this is the repository's default branch, offered as a suggested value rather than a setting that has been saved. |
rootDir | string | Yes | The subdirectory the build runs in. Empty is the repository root. |
configured | boolean | Yes | False when no hook has been set up. enabled: false with configured: true is a hook that was set up and then switched off. |
updatedAt | string | No | — |
| Field | Type | Required | Description |
|---|
buildId | string | Yes | — |
commitSha | string | Yes | — |
branch | string | Yes | — |
state | string | Yes | The build's current state. cancelled is not a failure: either someone stopped the build, or a newer push to the same branch superseded it while it was still queued. |
error | string | Yes | Why the build ended, as a code; empty on success — timeout, clone_failed, no_build_script, install_failed, build_failed, deploy_failed, minutes_exhausted, toolchain_missing, superseded, cancelled, internal. The full explanation is in the build log. |
minutes | number | Yes | Wall-clock minutes the build occupied a builder, not CPU minutes. This is what counts against your build allowance. |
startedAt | string | No | — |
finishedAt | string | No | — |
createdAt | string | Yes | — |
deploymentId | string | No | The deployment this build produced. Set only when the build succeeded. |
| Field | Type | Required | Description |
|---|
keyId | string | Yes | — |
name | string | Yes | — |
keyType | string | Yes | — |
fingerprint | string | Yes | The key's fingerprint. It is unique across all of Runlot, so the same key cannot be added twice. |
createdAt | string | No | — |
lastUsedAt | string | No | — |
| Field | Type | Required | Description |
|---|
tokenId | string | Yes | The token's id. It is also the middle part of the token string itself (runlot_pat_<id>_<secret>), so you can match a token you hold to a row here. |
name | string | Yes | — |
scope | TokenScope | Yes | — |
scopes | ApiScope[] | Yes | The token's full permission set. scope above is what these mean for git access. |
org | string | No | The org this token is restricted to, as a slug. null means the token is not restricted to any one org. |
project | string | No | The project this token is restricted to. Implies org. |
createdAt | string | Yes | — |
expiresAt | string | No | — |
lastUsedAt | string | No | When the token was last used. Recorded at most once per minute per token, so it can lag real use by up to a minute. |
revokedAt | string | No | — |
| Field | Type | Required | Description |
|---|
tokenId | string | Yes | — |
name | string | Yes | — |
scope | TokenScope | Yes | — |
scopes | ApiScope[] | Yes | — |
org | string | No | — |
project | string | No | — |
token | string | Yes | The token itself, returned in this response only and never again. Only a hash of it is stored, so it cannot be recovered later. Copy it now. |
expiresAt | string | No | — |
A short lowercase name. It becomes a single hostname label — a project is served at
<name>.<org>.<app-domain> — so it must follow DNS naming rules.
Type: string
| Field | Type | Required | Description |
|---|
error | object | Yes | — |
A finished login or half of one.
When the account has a confirmed authenticator app, the first factor does not issue
a session: token and user are absent, and mfa and pending are present
instead. Send pending to POST /v1/auth/totp with the six-digit code to get the
real session.
The two shapes never appear together: a response carries either a token or an
mfa marker, never both.
| Field | Type | Required | Description |
|---|
token | string | No | — |
expiresAt | string | No | When the session expires — or, on an mfa response, when pending expires |
user | User | No | — |
mfa | string | No | The second factor this account still needs. Present only on a half-finished login |
pending | string | No | A five-minute token proving the first factor succeeded. It is not a session and no other endpoint accepts it. |
| Field | Type | Required | Description |
|---|
accepted | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
enabled | boolean | Yes | Every login to this account requires a code from a confirmed authenticator app |
enrollmentPending | boolean | Yes | Enrollment was started but never confirmed. Finish it with the code from the QR already scanned; starting again invalidates that one. |
enabledAt | string | No | — |
recoveryCodesLeft | integer | Yes | How many unused recovery codes remain. The codes themselves cannot be listed again |
orgsRequiring | Slug[] | Yes | Slugs of this person's organizations that require the second factor |
| Field | Type | Required | Description |
|---|
secret | string | Yes | The base32 shared secret, for an app that cannot scan a QR code. Readable here and nowhere else. |
uri | string | Yes | otpauth://totp/runlot:<email>?secret=…&issuer=runlot — the string the QR encodes |
| Field | Type | Required | Description |
|---|
recoveryCodes | string[] | Yes | Ten single-use recovery codes, returned once. They cannot be read again, so save them somewhere safe now. |
| Field | Type | Required | Description |
|---|
userId | string | Yes | — |
provider | string | Yes | The oldest login method linked to this account, kept as its primary provider |
providers | string[] | Yes | All login methods linked to this user, oldest first |
subject | string | Yes | — |
email | object | No | — |
name | object | No | — |
| Field | Type | Required | Description |
|---|
orgId | string | Yes | — |
slug | Slug | Yes | — |
name | string | Yes | — |
personal | boolean | Yes | — |
Type: Org & object
Whether this organization's default app addresses can be opened yet.
A default address is three labels — <project>.<org>.<app-domain> — so a single
*.<app-domain> certificate cannot cover it and each organization gets its own
*.<org>.<app-domain>. That certificate is issued after the organization
exists, which leaves a window where an address we have already told you about
cannot be opened at all: the edge holds no certificate for that name and drops
the TLS handshake, which browsers report as
ERR_SSL_VERSION_OR_CIPHER_MISMATCH. Nothing can be written inside that error,
so this field is how you learn about the window — show it next to the address
rather than letting someone click through to a browser error page.
pending — being issued. The default addresses do not answer yet. It
normally clears in well under a minute; it is retried with backoff.
active — issued. The address answers.
failed — issuance gave up for now. It is retried when the control plane
restarts. Treat it as "will not open" rather than as a slow pending, and
contact support if it persists.
none — this deployment issues no wildcard for app addresses, which is the
local and development shape. Nothing to wait for — never render this as
"not ready".
A custom domain is not covered by this field. Those have their own per-name
certificate and their own state machine, and they appear in urls only once
they are serving.
Type: string
| Field | Type | Required | Description |
|---|
id | integer | Yes | — |
kind | string | Yes | What the notification is about. This is a stable value to branch on; the human-readable wording is produced separately by the dashboard and by email. |
projectName | string | No | If this is a project-related notification, the name of that project. Absent for org-level notifications (project_limit) |
key | string | Yes | A deduplication key within a kind. At most one notification is created per (kind, key) in 24 hours. |
detail | object | Yes | Extra values, which differ by kind. project_limit is {limit, count}, a usage alert is {bytes, capBytes}, an operation alert is {opId, opKind, reason?}, cron_failed is {cron, reason, scheduledAt}, queue_failed is {queue, reason, runs}, queue_ops_cap is {used, limit, plan}, new_device is {app, clientId, device}, error_issue_new is {issueId, shortId, title, origin} and app_out_of_memory is {issueId, limitMiB, peakMiB, release}. monitor_alert is {monitorId, monitorName, monitorKind, monitorState, monitorGroup, monitorValue, monitorThreshold, monitorMessage, monitorLink}. |
createdAt | string | Yes | — |
sentAt | string | No | When the notification email was sent. Absent if it is queued or none was sent. |
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
orgSlug | Slug | Yes | — |
name | Slug | Yes | — |
hostnames | string[] | Yes | — |
urls | string[] | No | hostnames as full, reachable URLs. The scheme and port depend on the environment (https://… in production, http://…:8787 locally), so use these rather than building URLs yourself. A default address is listed here while appCertState is pending — it is the address, and it is about to start working. Read that field before presenting one of these as something to click. |
appCertState | AppCertState | No | — |
createdAt | string | Yes | — |
disabledAt | string | No | Set while the project is disabled. A disabled project does not serve requests and takes no new backups; its data and its existing backups are kept. It does not count toward the plan's project limit. |
deleteAfter | string | No | When a disabled project is deleted for good — one year after disabledAt. Enabling it before then cancels this. Admins are emailed 30, 7 and 1 days ahead. |
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
disabled | boolean | Yes | — |
disabledAt | string | No | — |
deleteAfter | string | No | — |
changed | boolean | Yes | — |
Type: Project & object
| Field | Type | Required | Description |
|---|
state | string | Yes | — |
epoch | integer | Yes | — |
homeNode | object | No | — |
suspended | boolean | Yes | Whether the project is suspended. This is independent of state — a suspended project can still be active, and lifting the suspension returns it to serving. |
Everything the project home page shows, in one response.
| Field | Type | Required | Description |
|---|
live | OverviewDeployment | null | Yes | The deployment currently serving traffic. Null before the first deployment. |
deployments | OverviewDeployment[] | Yes | Recent deployments, newest first. Up to 5 — use listDeployments for all of them. |
deploymentCount | integer | Yes | Total number of deployments for this project. |
database | OverviewDatabase | Yes | — |
features | OverviewFeatures | Yes | — |
customHostnames | integer | Yes | How many custom hostnames the project has, including unverified ones. |
repos | integer | Yes | Number of repositories in this project. |
notifications | Notification[] | Yes | This project's recent notifications, newest first. Up to 5. |
A deployment in the overview. Same shape as Deployment, including actor.
Type: Deployment
| Field | Type | Required | Description |
|---|
granted | boolean | Yes | Whether the project has a database. Every project has one unless it was deleted. |
lastBackupAt | string | No | When the most recent backup generation was taken. Absent if there is none yet. |
lastCheckedAt | string | No | When backup last checked the database. If the database has not changed, no new generation is taken but this timestamp still moves — so a backup that is healthy but idle keeps updating it. |
generations | integer | Yes | How many backup generations exist |
Which of the project's resources are on. Every one is on unless somebody turned it off.
| Field | Type | Required | Description |
|---|
database | boolean | Yes | — |
storage | boolean | Yes | — |
email | boolean | Yes | — |
auth | boolean | Yes | — |
One entry of an incremental upload's file list. A regular file carries sha256
(lowercase hex) and size; a directory carries type: dir and a path ending in /.
| Field | Type | Required | Description |
|---|
path | string | Yes | — |
sha256 | string | No | — |
size | integer | No | — |
type | string | No | — |
| Field | Type | Required | Description |
|---|
uploadId | string | Yes | — |
missing | string[] | Yes | sha256 hashes the server does not hold yet. Upload these, then commit. |
expiresAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
deploymentId | string | Yes | — |
version | integer | Yes | — |
artifactSha | string | Yes | SHA-256 (hex) of the deployment bundle tarball |
createdAt | string | Yes | — |
createdBy | object | No | — |
live | boolean | Yes | — |
actor | string | No | Display name of the person who deployed — their name, else their email, else their provider subject. Returned in lists and overviews only, and empty when the deployer is not a known user. |
manifest | Manifest | No | The manifest exactly as it passed validation. Absent for older deployments. |
bundleBytes | integer | No | The bundle size after unpacking, not the compressed size. |
bundleFiles | integer | No | Number of entries in the bundle (files + directories). |
gitCommit | string | No | The commit hash the CLI reported at deploy time. For display only; not verified. |
gitMessage | string | No | The first line of the commit message, up to 200 characters. |
gitBranch | string | No | — |
gitDirty | boolean | No | Whether the deployment shipped with uncommitted changes. If true, gitCommit does not describe the deployed code exactly. |
warnings | string[] | No | Conditions that did not refuse the deploy: a declared framework the bundle contradicts, or a recognised framework deployed without runWorkerFirst: false. |
The one address Studio hands to a person who is not a developer
(docs/studio.md §6.9).
A preview's own hostname is <preview>--<project>.<org>.<app-domain>. The -- is what
keeps a preview name from colliding with a project name and it is right for a CLI user,
but it is not a link to send to somebody — and it carries the project's name, which the
author of a half-finished app may not want published. So a shared preview gets a second
hostname, and this is it.
The label is 12 characters of lowercase base32 ([a-z2-7], 60 bits). It contains no
hyphen — that is why the project name is not in it, since a slug may contain one — and
it is the only thing between the link and the app, so it is minted from a CSPRNG.
It lives under share.<app-domain>, not under an org, so it cannot collide with a
project or preview name. share is a reserved org slug for that reason.
| Field | Type | Required | Description |
|---|
label | string | Yes | The 12-character label. Minted once and kept across shares. |
hostname | string | Yes | <label>.share.<app-domain>. |
url | string | Yes | The address to hand out. Built by the server — the scheme and port are a deployment matter. |
preview | Slug | No | The preview the link currently resolves to (studio, or studio-<branch>). Present so that "the link works but shows the wrong branch" is diagnosable. |
createdAt | string | Yes | — |
rotatedAt | string | No | When the label was last re-minted. Absent if it never was. |
Whether the control plane applied this deployment's migrations/, and how far it got.
Present only on deployments the control plane migrates — today that is a preview
deployed with db=branch. Absent means the schema is the client's to apply, which is
what runlot deploy does.
applied with total: 0 is the answer for a bundle that carries no migrations at
all; it is a state rather than an absence so that a caller waiting on this can tell
"not started yet" from "there is nothing to run".
| Field | Type | Required | Description |
|---|
state | string | Yes | pending — not started, or waiting for the preview's database branch to finish being poured. A database that could not be reached also returns here, so that the next sweep retries: an unreachable node is not a failed migration. failed — one file threw, and it is named in failedName. Nothing after it ran. |
total | integer | Yes | How many migration files the bundle carries. |
applied | integer | Yes | How many of them went through. |
failedName | string | No | The file that threw, as 0003_posts. Only on failed. |
detail | string | No | The database's own message, truncated. Only on failed. |
startedAt | string | Yes | — |
finishedAt | string | No | Absent while pending or running. |
One preview of a project. A preview behaves like a project of its own — it has its
own hostname, deployments, access policy and usage — and this schema carries what is
specific to being a preview: its parent, its database mode, and when it expires.
Creating one past the plan's per-project preview limit answers 409
preview_limit.
| Field | Type | Required | Description |
|---|
previewId | string | Yes | — |
name | Slug | Yes | What the user called it (--preview feat-42). |
hostname | string | Yes | The preview's hostname, <preview>--<project>.<org>.<app-domain>. Preview and project are joined into a single label so the hostname stays covered by the organization's wildcard certificate. |
url | string | No | The preview's full URL — https:// plus hostname. Use this rather than building it yourself. |
dbMode | string | Yes | How the preview gets a database. branch gives it its own copy, poured from the parent's latest backup generation. shared points it at production's database, so a destructive statement in the preview is destructive in production. none gives it no env.db at all. |
state | string | Yes | The preview's lifecycle state. Copying a database takes as long as a restore, so a preview can sit in creating for a while and its hostname answers 503 until it is ready. Read this value rather than inferring readiness from the hostname. |
deploymentId | string | No | The deployment serving the preview. Null until its first deployment lands. |
version | integer | No | The preview's own version counter. It is independent of the parent's, and promoting does not carry it over. |
sourceGeneration | string | No | The backup generation the preview's database was copied from. Null for shared and none, and also for a branch preview of a project that had no generation yet — that preview simply starts with an empty database. |
createdAt | string | Yes | — |
expiresAt | string | No | When the preview will be deleted. Derived from lastRequestAt and the organization's current plan, and recomputed on every request — so upgrading the plan extends previews that already exist. |
lastRequestAt | string | No | When the preview last served a request. Expiry is measured from here, not from createdAt, so a preview you keep using keeps living. It starts at createdAt, so a preview nobody ever opened still expires. |
One run of one scheduled job. A run that never started — because the previous run
was still going, or because it came up past its grace period — is recorded too, with
outcome: skipped and no durationMs.
| Field | Type | Required | Description |
|---|
cron | string | Yes | The cron expression exactly as you wrote it. It identifies the schedule. |
name | string | No | The name the live deployment gives this expression in triggers.names. Absent when it has none. It is the current name, so renaming a schedule relabels its past runs too. |
scheduledAt | string | Yes | The time the expression named, and the value your handler receives as controller.scheduledTime. It identifies the run: the same run is never recorded twice. |
startedAt | string | Yes | When the run began. If the project was idle, this is before it woke up, and the wake time is included in durationMs. |
durationMs | object | No | Wall-clock duration of the run, wake-up time included. Null when nothing ran (outcome: skipped). |
outcome | string | Yes | How the run ended. ok succeeded. failed means your code is at fault — it threw, or the worker exports no scheduled handler. error means the run never reached your handler at all, for example the project could not be woken or the wall-clock bound was hit. skipped means the run was intentionally not started. |
reason | string | No | Why the run ended as it did, as a code. For failed it is workerd's own outcome (exception, canceled). Runlot's own codes are timeout, fire_failed, no_socket, wake_failed, overlap, too_late, schedule_changed and agent_shutdown. An agent_shutdown attempt was interrupted by the platform; the occurrence remains pending and may be retried under the same scheduledAt. |
detail | string | No | One line of extra human-readable context, when there is any. May be empty. |
requestId | string | No | The request ID of this run's invocation record — the same value the worker received as the runlot-request-id header, so the history row, the invocation record and the logs your handler wrote under it name one run. Absent on rows recorded before request IDs existed. |
| Field | Type | Required | Description |
|---|
cron | string | Yes | — |
name | string | No | The name from triggers.names, when the live deployment gives one. |
nextRunAt | string | No | When this schedule fires next. Absent when the expression can never fire again; deploys reject such expressions, so only an old deployment can carry one. |
lastRun | CronRun | No | The most recent run of this schedule, taken from the full history rather than the current page. |
monitor | CronMonitor | No | — |
Passive monitoring of the schedule's start check-ins and completion reports. This
does not run or retry the handler. A missed check-in means no start check-in was
received, not proof the job did not run. Platform observation gaps are unknown,
never successful checks. Always present for declared schedules on current servers.
| Field | Type | Required | Description |
|---|
state | string | Yes | — |
reason | string | No | The observation or gap code, such as no_start_checkin, no_completion_within_budget, not_judged_yet, cp_restart, platform_quarantine, redeploy, placement_change, node_agent_restart, node_not_active, project_not_active or catchup_limit. |
since | string | No | — |
lastObservedAt | string | No | The newest scheduled occurrence seen to start or complete. |
evaluatedUntil | string | No | — |
running | object | No | — |
missed | CronMonitorIncident | No | — |
timeout | CronMonitorIncident | No | — |
gap | object | No | — |
window | object | Yes | — |
| Field | Type | Required | Description |
|---|
issueId | string | No | The Runlot Errors issue opened for this incident. |
openedAt | string | Yes | — |
scheduledAt | string | No | — |
How the last windowHours went, counted by outcome.
| Field | Type | Required | Description |
|---|
windowHours | integer | Yes | — |
ok | integer | Yes | — |
failed | integer | Yes | — |
errored | integer | Yes | — |
skipped | integer | Yes | — |
| Field | Type | Required | Description |
|---|
eventsErased | integer | Yes | — |
issuesDeleted | integer | Yes | — |
replaysDeleted | integer | Yes | — |
aiOutputsRemoved | integer | Yes | — |
aggregatesPreserved | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
issueId | string | Yes | — |
shortId | string | Yes | A short, stable name within the project, such as ERR-1A2B |
title | string | Yes | — |
culprit | string | No | Where it happened: the top in-app frame, else the route |
type | string | Yes | The exception type, or a platform kind such as OutOfMemory |
origin | string | Yes | — |
level | string | Yes | — |
status | string | Yes | — |
substatus | string | Yes | new · ongoing · regressed · escalating, or empty when not unresolved |
firstSeen | string | Yes | — |
lastSeen | string | Yes | — |
count | integer | Yes | Every occurrence, including ones whose body was not stored |
userCount | integer | Yes | — |
firstRelease | integer | No | — |
lastRelease | integer | No | — |
resolvedAt | string | No | — |
resolvedInRelease | integer | No | — |
resolveCommit | string | No | Exact hosted-repository commit selected for resolution |
resolveCommitPending | boolean | No | Still unresolved until a clean live deployment contains this commit |
archiveMode | string | No | — |
archiveEvents | integer | No | — |
archiveUsers | integer | No | — |
archiveNewEvents | integer | No | Weighted new arrivals while this issue is an archived routing target; moving merge history does not advance it |
archiveNewUsers | integer | No | Distinct reported user IDs on new arrivals in this archive window, not lifetime-new customers; erasure preserves the anonymous count |
archivedUntil | string | No | — |
trend | integer[] | Yes | Occurrences per hour over the last 24 hours, oldest first |
assigneeUserId | string | No | The org member the issue is assigned to |
mergedInto | string | No | Set on a merged source: the issue that now receives its events |
titleCustom | boolean | No | The title came from a project fingerprint rule, not from the event |
| Field | Type | Required | Description |
|---|
commentId | string | Yes | — |
authorUserId | string | No | — |
author | string | Yes | — |
body | string | Yes | — |
createdAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
comments | ErrorComment[] | Yes | — |
| Field | Type | Required | Description |
|---|
label | string | Yes | Always "shared stack hints" |
issues | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
matchType | string | No | RE2 on the primary exception type |
matchMessage | string | No | RE2 on the primary exception message |
matchModule | string | No | RE2 on the innermost in-app frame's file |
matchFunction | string | No | RE2 on the innermost in-app frame's function |
tags | object | No | — |
fingerprint | string[] | Yes | "{{ default }}" stands for the built-in key |
title | string | No | — |
| Field | Type | Required | Description |
|---|
rules | ErrorFingerprintRule[] | Yes | — |
| Field | Type | Required | Description |
|---|
issues | ErrorIssue[] | Yes | — |
cursor | string | No | — |
keepDays | integer | Yes | — |
| Field | Type | Required | Description |
|---|
status | string | Yes | — |
resolveIn | string | No | — |
resolveCommit | string | No | Required with resolveIn commit; repository is selected by the server. Remains unresolved/pending until exact or descendant commit is clean and live. |
archiveEvents | integer | No | Archive until this many new weighted arrivals. Mutually exclusive with archiveUsers and archiveUntil. |
archiveUsers | integer | No | Archive until this many distinct reported IDs on new arrivals, not lifetime-new users. Erased identities are not retained or recounted in an older archive window. |
archiveUntil | string | No | escalating, or a duration such as 24h |
| Field | Type | Required | Description |
|---|
at | string | Yes | — |
kind | string | Yes | — |
actor | string | No | — |
detail | string | No | — |
| Field | Type | Required | Description |
|---|
value | string | Yes | — |
count | integer | Yes | — |
| Field | Type | Required | Description |
|---|
issue | ErrorIssue | Yes | — |
latestEvent | ErrorEvent | No | — |
activity | ErrorActivity[] | Yes | — |
tags | object | Yes | — |
| Field | Type | Required | Description |
|---|
eventId | string | Yes | — |
timestamp | string | Yes | — |
requestId | string | No | — |
release | integer | No | — |
message | string | Yes | — |
userId | string | No | — |
url | string | No | — |
| Field | Type | Required | Description |
|---|
events | ErrorEventSummary[] | Yes | — |
cursor | string | No | — |
| Field | Type | Required | Description |
|---|
function | string | No | — |
file | string | No | — |
line | integer | No | — |
column | integer | No | — |
in_app | boolean | Yes | — |
debug_id | string | No | Source map debug ID; resolved only inside this event's deployment |
mapped_file | string | No | — |
mapped_line | integer | No | — |
mapped_column | integer | No | — |
mapped_function | string | No | — |
context_line | string | No | — |
pre_context | string[] | No | — |
post_context | string[] | No | — |
| Field | Type | Required | Description |
|---|
type | string | Yes | — |
value | string | No | — |
mechanism | string | No | — |
handled | boolean | Yes | — |
frames | ErrorFrame[] | No | Outermost first, innermost last |
| Field | Type | Required | Description |
|---|
timestamp | string | Yes | — |
category | string | Yes | — |
level | string | No | — |
message | string | No | — |
data | object | No | — |
One stored error event (docs/customer-error-tracking.md §4). Field names are snake_case.
| Field | Type | Required | Description |
|---|
event_id | string | Yes | — |
project_id | string | Yes | — |
origin | string | Yes | — |
timestamp | string | Yes | — |
level | string | Yes | — |
request_id | string | No | — |
handler | string | No | — |
deployment | string | No | The deployment version the event came from |
environment | string | No | — |
message | string | No | — |
exceptions | ErrorException[] | No | Outermost last |
breadcrumbs | ErrorBreadcrumb[] | No | — |
request | object | No | — |
user | object | No | — |
tags | object | No | — |
contexts | object | No | — |
| Field | Type | Required | Description |
|---|
eventId | string | No | Actual stored occurrence analyzed. Explicit-selection clients require an exact match; omitted for no stored body or older CPs. |
available | boolean | Yes | — |
unavailable | string | No | no_event · no_frames · no_release · no_deployment · no_commit · dirty_tree · no_repo · ambiguous_repo · git_unavailable · repo_empty · git_error · commit_not_found |
reason | string | No | — |
release | integer | No | — |
commit | string | No | The deployment's full 40-hex commit; a short id is never resolved (commit_not_found) |
previousCommit | string | No | The previous deployment's commit, only when it is clean and full and bounds the suspect range |
repo | object | No | — |
sourceContexts | ErrorInsightSourceContext[] | Yes | — |
suspects | ErrorInsightSuspects | No | — |
codeownersFile | string | No | — |
owners | ErrorInsightOwners[] | Yes | — |
| Field | Type | Required | Description |
|---|
frame | integer | Yes | Ordinal in the server-filtered Git request, not an original/display stack index. |
exceptionIndex | integer | No | Optional zero-based exception index in the exact stored event. Absent on older CPs; never infer it from frame order. |
frameIndex | integer | No | Optional zero-based frame index in that stored exception's original frame array, before UI reversal/grouping. |
path | string | Yes | — |
line | integer | No | — |
preContext | string[] | No | — |
contextLine | string | No | — |
postContext | string[] | No | — |
unavailable | string | No | no_file · unsafe_path · too_large · binary · no_line |
| Field | Type | Required | Description |
|---|
commits | ErrorSuspectCommit[] | Yes | — |
rangeCommits | integer | Yes | — |
rangeTruncated | boolean | No | — |
hideTruncated | boolean | No | — |
noPrevious | boolean | No | No previous release commit: the range is the release's most recent ancestors |
unavailable | string | No | previous_release_unusable (the previous deployment has no clean, full commit, so no range and nobody named) · previous_commit_not_found · empty_range |
notes | string[] | No | — |
| Field | Type | Required | Description |
|---|
hash | string | Yes | — |
message | string | Yes | — |
authorName | string | Yes | The commit's own claim, unverified |
authorTime | string | Yes | — |
authorVerified | boolean | Yes | Always false |
memberUserId | string | No | Present only when the commit email is the verified email of exactly one org member |
authorEmail | string | No | Present only with memberUserId |
files | string[] | Yes | — |
filesTruncated | boolean | No | — |
confidence | string | Yes | line: the commit last changed the frame's line; file: it only touched the file |
frames | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
source | string | No | First matching .runlot/errors.json ownership rule, else the top in-app frame's CODEOWNERS rule. Unmapped handles grant nothing. |
path | string | Yes | — |
handles | string[] | Yes | Raw CODEOWNERS handles; email handles only when they map to a verified org member |
memberUserIds | string[] | No | — |
hiddenEmails | integer | No | — |
ruleLine | integer | No | — |
pattern | string | No | — |
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
url | string | Yes | https on port 443; the host must be one of the project's active addresses. |
method | string | No | Default GET. |
headers | object | No | Host, Cookie, Authorization, hop-by-hop and Runlot-* headers are refused. |
intervalMinutes | integer | No | Default 5 (15 on Free). Free runs at most every 15 minutes (403 plan_required). |
timeoutMs | integer | No | Default 10000. |
expectStatusMin | integer | No | Default 200. |
expectStatusMax | integer | No | Default 399. Redirects are not followed; a 3xx is the answer and is judged by this range. |
bodyContains | string | No | Must appear in the first 64 KiB of the body. GET only. |
maxLatencyMs | integer | No | — |
enabled | boolean | No | Default true. |
assertions | UptimeAssertion[] | No | Checked on the single request's answer. |
steps | UptimeStep[] | No | A multi-step API check: the steps replace the single request, run in order within timeoutMs, and carry extracted values forward as {{name}}. |
| Field | Type | Required | Description |
|---|
at | string | Yes | — |
ok | boolean | Yes | — |
status | integer | No | — |
latencyMs | integer | Yes | — |
reason | string | No | — |
certDaysLeft | integer | No | Days until the leaf certificate expires; within 14 a CertificateExpiring warning is raised, at most weekly. |
Type: UptimeCheckInput & object
| Field | Type | Required | Description |
|---|
checks | UptimeCheck[] | Yes | — |
limit | integer | Yes | Checks allowed per project on this plan. |
| Field | Type | Required | Description |
|---|
runs | UptimeRun[] | Yes | — |
| Field | Type | Required | Description |
|---|
userId | string | Yes | — |
label | string | Yes | Display label only, never identity proof. |
subject | string | Yes | Canonical positive signed-64-bit GitHub numeric ID. |
githubLogin | string | No | The account's current GitHub login, from a lookup no older than 24 hours. Absent when none is fresh. A CODEOWNERS @handle equal to it assigns to this member without a manual pin. |
| Field | Type | Required | Description |
|---|
deploymentId | string | Yes | — |
version | integer | Yes | — |
repoId | string | Yes | — |
commit | string | Yes | — |
| Field | Type | Required | Description |
|---|
deploymentId | string | Yes | — |
repoId | string | Yes | — |
commit | string | Yes | — |
selector | string | Yes | Literal individual @handle, normalized lowercase. No @org/team, whitespace or consecutive hyphens. |
userId | string | Yes | — |
subject | string | Yes | Existing linked GitHub ID belonging to this current org member. |
acknowledgeManualBinding | boolean | Yes | Manual policy pin, not provider-verified current handle proof. |
| Field | Type | Required | Description |
|---|
deploymentId | string | Yes | — |
repoId | string | Yes | — |
commit | string | Yes | — |
selector | string | Yes | — |
userId | string | Yes | — |
provider | string | Yes | — |
subject | string | Yes | — |
createdAt | string | Yes | — |
revokedAt | string | No | — |
| Field | Type | Required | Description |
|---|
identities | ErrorOwnershipIdentity[] | Yes | — |
snapshots | ErrorOwnershipSnapshot[] | Yes | — |
pins | ErrorOwnershipPin[] | Yes | — |
identitiesTruncated | boolean | Yes | — |
snapshotsTruncated | boolean | Yes | — |
pinsTruncated | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
version | integer | Yes | — |
consoleErrors | boolean | Yes | — |
retainUserEmail | boolean | Yes | Retain structured event user.email only, independently of feedback email. Requires acknowledgePII when enabled. |
retainFeedbackEmail | boolean | No | Defaults to false. Retain the optional unverified email explicitly supplied with browser feedback, independently of retainUserEmail. Not an account identity; Runlot sends no mail to it. Requires acknowledgePII when enabled. Ordinary feedback reads omit email; explicit admin/errors:pii reads may include it only while this option is enabled. |
scrubPatterns | string[] | Yes | — |
filters | object | Yes | — |
browserExcludedRoutes | string[] | Yes | — |
| Field | Type | Required | Description |
|---|
policy | ErrorCapturePolicy | Yes | — |
filtered | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
monthlyCap | object | No | — |
spanDailyCap | object | No | Completed delivered DB/HTTP spans per UTC day. null: plan allowance; -1: no cap (Pro). Counts do not estimate missing gateway batches; sampled detail does not change the unit. |
responseErrors | boolean | No | — |
browserEnabled | boolean | No | — |
autoAssign | boolean | No | Admin opt-in; default false. Only new/unassigned issues; omitted leaves existing settings unchanged. |
performance | ErrorPerformanceThresholds | No | — |
Per-project performance detector thresholds (docs/customer-error-tracking.md §10).
An absent field is the detector's default. On a PUT the object replaces the
stored overrides whole; {} resets every one. Omitting performance leaves them.
| Field | Type | Required | Description |
|---|
nPlusOneMinCalls | integer | No | Sequential calls of one statement shape (default 5) |
nPlusOneMinTotalMs | integer | No | Their total duration (default 50) |
consecutiveHttpMin | integer | No | Sequential outbound fetches (default 3) |
consecutiveHttpEachMs | integer | No | Each one at least this long (default 100) |
slowQueryP95Ms | integer | No | p95 over 24 hourly buckets must be past this bound (default 500); a histogram bound, never interpolated |
slowQueryMinCalls | integer | No | Calls in the window (default 50) |
disabled | string[] | No | — |
| Field | Type | Required | Description |
|---|
nPlusOneMinCalls | integer | Yes | — |
nPlusOneMinTotalMs | integer | Yes | — |
consecutiveHttpMin | integer | Yes | — |
consecutiveHttpEachMs | integer | Yes | — |
slowQueryP95Ms | integer | Yes | — |
slowQueryMinCalls | integer | Yes | — |
nPlusOneOff | boolean | Yes | — |
consecutiveHttpOff | boolean | Yes | — |
slowQueryOff | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
autoAssign | boolean | No | Off by default. Suggest owners from clean Git snapshots; autoassign new/unassigned issues only after admin opt-in. Never overwrites manual assignment or grants access. |
monthlyCap | object | Yes | null: the plan's included amount. -1: no cap (Pro and above). Platform events are never capped. |
included | integer | Yes | — |
usedMonth | integer | Yes | — |
spanDailyCap | object | No | — |
spansIncluded | integer | No | Daily per-project span allowance: Free 200000, Pro 2000000 |
spansObservedDay | integer | No | — |
spendingLimitCents | integer | No | Organization monthly overage spending limit in cents; includes errors/replays/spans |
spanSamplePercent | integer | No | Successful span detail sampling; error/candidate traces and counts are kept. |
plan | string | Yes | — |
responseErrors | boolean | Yes | Whether a 5xx answer without a thrown error becomes a ResponseError issue |
browserEnabled | boolean | No | Whether the browser agent may be injected into this project's pages (docs/customer-error-tracking.md §12). Defaults to true. It can only turn the agent off: injection also needs the org to be on Pro, a live deployment, and a manifest without observability.browser: false. A change reaches the app at the next routing-map refresh, with no deploy. Always present on a GET. On a PUT, absent leaves it unchanged; true below Pro is 403 plan_required, false is allowed on every plan. |
performance | ErrorPerformanceThresholds | No | — |
performanceEffective | ErrorPerformanceEffective | No | — |
| Field | Type | Required | Description |
|---|
proposalId | string | Yes | — |
issueId | string | Yes | — |
eventId | string | No | The stored event whose frames chose the files |
state | string | Yes | — |
model | string | Yes | — |
repoId | string | No | — |
repoName | string | No | — |
baseCommit | string | No | The full commit the files were read at |
proposalSha | string | No | SHA-256 over the repository, the base commit and every file's path, old and new content. An apply must quote it. |
files | object[] | Yes | — |
explanation | string | Yes | — |
usage | object | Yes | — |
charged | integer | Yes | Microcents |
balance | integer | No | The org's AI balance after the call, in microcents; only on the answer to the call that paid |
author | string | No | — |
createdAt | string | Yes | — |
finishedAt | string | No | — |
expiresAt | string | Yes | After this it cannot be applied |
replayed | boolean | No | — |
errorCode | string | No | Why a failed proposal failed: truncated, invalid_output, path_not_allowed, no_fix, … |
safeReason | string | No | — |
applied | object | No | — |
| Field | Type | Required | Description |
|---|
proposalId | string | Yes | — |
proposalSha | string | Yes | — |
branch | string | Yes | runlot/autofix/<proposal> |
commit | string | Yes | — |
baseCommit | string | Yes | — |
created | boolean | Yes | false when the same change was already on the branch |
| Field | Type | Required | Description |
|---|
hour | string | Yes | — |
metric | string | Yes | — |
samples | integer | Yes | — |
total | number | Yes | — |
minimum | number | Yes | — |
maximum | number | Yes | — |
histogram | integer[] | Yes | — |
upperBounds | number[] | Yes | — |
| Field | Type | Required | Description |
|---|
day | string | Yes | — |
accepted | integer | Yes | — |
feedback | integer | Yes | Accepted feedback observations including later expired or erased pending messages |
droppedAttempts | integer | Yes | CP technical-fuse refusal attempts, not unique people |
| Field | Type | Required | Description |
|---|
origin | string | Yes | — |
untrusted | boolean | Yes | — |
vitals | BrowserVitalBucket[] | Yes | — |
days | BrowserTelemetryDay[] | Yes | — |
technicalDailyLimit | integer | Yes | — |
technicalFeedbackDailyLimit | integer | Yes | — |
vitalRetentionDays | integer | Yes | — |
feedbackRetentionDays | integer | Yes | — |
percentiles | string | Yes | — |
pricing | string | Yes | — |
| Field | Type | Required | Description |
|---|
feedbackId | string | Yes | — |
eventId | string | Yes | — |
requestId | string | Yes | — |
release | integer | Yes | — |
message | string | Yes | — |
email | string | No | Optional unverified email explicitly supplied with feedback, not an account identity. Present only for an authorized includePII=true read while retainFeedbackEmail is enabled; omitted from ordinary replies. Runlot sends no mail to it. |
receivedAt | string | Yes | — |
origin | string | Yes | — |
verified | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
feedback | BrowserFeedback[] | Yes | — |
| Field | Type | Required | Description |
|---|
enabled | boolean | Yes | The project's replay switch. Defaults to true. |
monthlyCap | object | Yes | null: the plan's included amount. -1: no cap (Pro). 0: collection off. |
plan | string | Yes | — |
supported | boolean | Yes | Whether the plan has replay (Pro) |
browserEnabled | boolean | Yes | The browser agent's switch; off turns replay off |
effective | boolean | Yes | Whether pages are offered the recorder now |
included | integer | Yes | — |
usedMonth | integer | Yes | Complete replays this month |
billableMonth | integer | Yes | Replays this month past the included amount. Counted, not charged. |
retentionDays | integer | Yes | — |
pricing | string | Yes | No price is set; nothing is charged |
| Field | Type | Required | Description |
|---|
replayId | string | Yes | — |
eventId | string | Yes | The browser error event it was recorded for |
requestId | string | Yes | The request that rendered the page |
release | integer | Yes | — |
start | string | Yes | — |
end | string | Yes | — |
frames | integer | Yes | — |
chunks | integer | Yes | — |
bytes | integer | Yes | — |
maxLiveNodes | integer | Yes | — |
truncated | boolean | Yes | The page had more than 1,000 elements or deeper than 32, and the rest was not recorded |
expiresAt | string | Yes | — |
kind | string | Yes | — |
masking | string | Yes | — |
One batch of the masked structural replay format, version 1 (internal/errorreplay). It
names no project, user or URL. Frames carry the viewport, the scroll and nodes of
{id, p, tag, r: [x, y, w, h], s?, it?, txt?, val?}, where tag is one of a fixed list,
s holds only enums and numbers, and txt/val are always [masked].
| Field | Type | Required | Description |
|---|
v | integer | Yes | — |
replay_id | string | Yes | — |
event_id | string | Yes | — |
seq | integer | Yes | — |
last | boolean | Yes | — |
frames | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
diagnosisId | string | Yes | — |
issueId | string | Yes | — |
eventId | string | No | The stored event the diagnosis read |
state | string | Yes | — |
summary | string | Yes | — |
causes | object[] | Yes | — |
suggestedFix | string | Yes | — |
confidence | string | Yes | — |
model | string | Yes | — |
usage | object | Yes | — |
charged | integer | Yes | What the call cost, in microcents (1/1,000,000 of a cent) |
balance | integer | No | The organization's AI balance after this call, in microcents. Only on the answer to the call that paid. |
author | string | No | — |
createdAt | string | Yes | — |
finishedAt | string | No | — |
replayed | boolean | No | A stored answer returned for a repeated key; nothing was charged |
errorCode | string | No | Why a failed diagnosis failed |
errorMessage | string | No | — |
| Field | Type | Required | Description |
|---|
schedules | CronSchedule[] | Yes | The schedules the live deployment declares. Empty means the project has no schedules. |
runs | CronRun[] | Yes | Newest first. |
summary | CronSummary | Yes | — |
keepDays | integer | Yes | How far back the run history goes on this org's plan, in days. It always reflects the plan's current value. |
One delivered batch of one queue. There is one row per batch, not per message:
the four counters add up to the batch. A batch that never reached your handler has
delivered > 0 and zeros everywhere else, which means those messages went back to
the queue untouched.
| Field | Type | Required | Description |
|---|
queue | string | Yes | — |
startedAt | string | Yes | — |
finishedAt | string | No | Absent for a batch that never began (outcome: skipped). |
durationMs | object | No | Wall clock, wake included. null when nothing ran. |
delivered | integer | Yes | How many messages were leased into this batch. |
acked | integer | Yes | — |
retried | integer | Yes | — |
dead | integer | Yes | How many left for the dead-letter queue, or were dropped because there is none. |
outcome | string | Yes | The same four outcomes as CronRun.outcome, split by who has to act. failed is your code — it threw, or the worker exports no queue handler. error means the batch never reached your handler (no socket, a project that would not wake, a transport failure, or the time bound) and is ours to fix. skipped means delivery was deliberately not attempted. |
reason | string | No | A short code, never a sentence. For failed it is workerd's own outcome (exception, canceled). Runlot-side codes are no_socket, wake_failed, drive_failed, timeout, consumers_changed. |
detail | string | No | One line of human-readable context when there is one. May be empty. |
requestId | string | No | The request ID of this batch's invocation record — the same value the worker received as the runlot-request-id header, so the history row, the invocation record and the logs your handler wrote under it name one batch. Absent on rows recorded before request IDs existed. |
A consumer's settings as the deployment declares them, with defaults filled in.
| Field | Type | Required | Description |
|---|
maxBatchSize | integer | Yes | 1–100, default 10. |
maxBatchTimeout | integer | Yes | Seconds, 1–60, default 5. |
maxRetries | integer | Yes | 0–10, default 3. |
deadLetterQueue | string | No | Where a message goes once it is out of retries. Absent means it is deleted instead. |
Queue depth split three ways rather than given as one total. A queue that is all
delayed is working normally; a queue that is all inflight is stuck. A single
number cannot tell those apart.
| Field | Type | Required | Description |
|---|
visible | integer | Yes | Could be delivered right now. |
delayed | integer | Yes | Waiting on its own delay or backoff. |
inflight | integer | Yes | Leased to a handler that has not answered yet. |
| Field | Type | Required | Description |
|---|
queue | string | Yes | — |
producers | string[] | Yes | The binding names (env.<BINDING>) that send into this queue. |
consumer | QueueConsumer | No | Absent for a queue nothing drains — a fan-out target, or a dead-letter queue nobody consumes. |
deadLetterFor | string[] | No | The queues whose dead-letter queue this one is. Non-empty is what makes redrive apply to this row. |
depth | QueueDepth | No | Absent when the project's database could not be read (QueueOverview.depthError). |
deadLetters | integer | No | How many messages sit in this queue's dead-letter queue. Absent without one, or when the depth is unknown. |
lastRun | QueueRun | No | The most recent batch of this queue, taken from the whole history and not just the page below it. |
How the last windowHours went, counted by outcome.
| Field | Type | Required | Description |
|---|
windowHours | integer | Yes | — |
ok | integer | Yes | — |
failed | integer | Yes | — |
errored | integer | Yes | — |
skipped | integer | Yes | — |
| Field | Type | Required | Description |
|---|
queues | QueueStatus[] | Yes | The queues the live deployment declares, in declaration order. Empty means no queues. |
runs | QueueRun[] | Yes | Newest first, across every queue. |
summary | QueueSummary | Yes | — |
keepDays | integer | Yes | How far back the history goes on this org's plan, in days (30 free, 365 pro). |
opsToday | integer | Yes | The project's queue operations today (UTC). A send is one, a delivery is one. 0 when the depth could not be read. |
opsCap | integer | Yes | The plan's daily bound (free 10,000, pro 1,000,000). Past it, send throws QueueLimitError until 00:00 UTC. |
depthError | string | No | Present when the project's database could not be read. The declarations and the history are still answered. |
One message as peekQueue shows it. preview is a clipped rendering of the body, never the body.
| Field | Type | Required | Description |
|---|
id | string | Yes | The message id, as a string. It is valid only while the message exists. |
attempts | integer | Yes | Deliveries so far in this queue. |
contentType | string | Yes | — |
enqueuedAt | string | Yes | — |
visibleAt | string | Yes | When it becomes deliverable. In the past for a visible message. |
inflight | boolean | Yes | Leased to a handler right now. |
preview | string | Yes | The first 200 characters of the body, or <n bytes> for a binary one. |
| Field | Type | Required | Description |
|---|
namespace | string | Yes | — |
count | integer | Yes | — |
dimensions | integer | No | The width every vector in the namespace has. Absent when the namespace holds more than one width, which search refuses. |
Durable Object counts and storage sizes for this project. Counts are always exact. Sizes are summed from the nodes holding your objects, so read them together with complete and measuredAt.
| Field | Type | Required | Description |
|---|
count | integer | Yes | How many Durable Objects this project has placed, across every node. |
limit | integer | Yes | The maximum number of Durable Objects this project can place. |
bytes | integer | Yes | Total size of the object stores, summed over the nodes that have reported. Read it with complete. When complete is false this is a lower bound, not the project's full size. |
files | integer | Yes | Store files counted the same way, under the same caveat. It is not the object count — an object that has never written has no file. |
complete | boolean | Yes | Whether every node holding this project's objects has reported its sizes. When false, bytes and files cover only part of your objects and are a lower bound. A project with no objects at all is true with zero. |
measuredAt | string | No | The oldest measurement included in the totals, so it tells you how stale they may be. Absent when nothing has been reported. |
nodes | object | Yes | The per-node breakdown, keyed by node id. Use it to see which node is near nodeLimit, and which node's numbers are missing or stale. |
nodeLimit | integer | Yes | The maximum number of this project's Durable Objects a single node can hold. It applies in addition to limit, so a placement can be refused while the project-wide cap still has room. |
| Field | Type | Required | Description |
|---|
namespaces | VectorNamespace[] | Yes | Every namespace with vectors in it, sorted by name. Empty means nothing stored, not unknown. |
count | integer | Yes | Vectors across every namespace. 0 when the store could not be read. |
limit | integer | Yes | The plan's bound on vectors per project (free 5,000, pro 25,000). Past it, upsert throws VectorsError with code vector_limit. |
dimensionsMax | integer | Yes | The widest vector the store accepts (3,072). |
plan | string | Yes | — |
exact | boolean | Yes | Always true — search is exact k-NN; there is no approximate index. |
readError | string | No | Present when the project's database could not be read. The bounds are still answered. |
| Field | Type | Required | Description |
|---|
host | string | Yes | — |
port | integer | Yes | — |
database | string | Yes | — |
sslmode | string | Yes | — |
| Field | Type | Required | Description |
|---|
user | string | Yes | — |
expiresAt | string | Yes | — |
createdAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
user | string | Yes | — |
password | string | Yes | Included only in this response. |
expiresAt | string | Yes | — |
connect | ConnectInfo | Yes | Same format as DatabaseConnect.connect; user/password are the values of this token. |
| Field | Type | Required | Description |
|---|
host | string | Yes | The project's hostname. Connections are routed to the right project by SNI, which is why this is a hostname and not a UUID. |
port | integer | Yes | The port that accepts PostgreSQL wire connections for this project. |
database | string | Yes | The project UUID. Use it as the database name in your connection string. |
user | string | Yes | The initial database role. Each project database has its own roles, so names never collide. |
password | string | Yes | — |
sslmode | string | Yes | Connections with sslmode=disable are rejected. TLS is required, so a client configured to disable it never connects at all. |
| Field | Type | Required | Description |
|---|
db | boolean | Yes | — |
keyVersion | integer | No | The version of this project's data encryption key. Returned only when the database is created, and the field is absent entirely if the key could not be secured. It is not returned as 0, because keyVersion=0 already means "plaintext generation" and would wrongly suggest the backup is confirmed plaintext. When absent, the backup scheduler secures the key later. |
connect | ConnectInfo | Yes | — |
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
epoch | integer | Yes | The incarnation that created the image. Even within one project, a different epoch means a different database, so this value matters as much as the key. |
node | string | Yes | Node that took the image |
export | object | Yes | — |
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
epoch | integer | Yes | The currently running incarnation. Rows in the list can belong to an older epoch. |
state | string | Yes | Placement status (active, cold, restoring, and so on) |
lastCheckedAt | string | No | When the database was last checked for changes, even if nothing had changed. Empty means it has never been checked. This is what tells a stalled generation apart from a dead backup. |
generations | GenerationRow[] | Yes | Newest first. An empty array is an array, not null |
objects | ObjectBackupSet | No | — |
What a Durable Object restore would select, alongside the database generations it
is not consistent with.
Unavailable is not empty. If the object half cannot be read, available is
false, complete is false, and the lists are empty — which is not the same as
having no object backups. The database listing is still answered either way.
| Field | Type | Required | Description |
|---|
available | boolean | Yes | Whether the object half could be read at all. |
atomic | boolean | Yes | Always false. The database and the objects are not restored to one consistent instant, so do not present a single restore time for both. |
restorable | boolean | Yes | available && complete — eligibility, not a success guarantee. The restore call (POST /orgs/{orgSlug}/projects/{projectName}/database/restore) refuses outright when missing or gaps is non-empty, so false here means the call is not worth attempting. true means only that the preflight would pass; the restore can still fail afterwards on a holder's own store (unreachable node, a lost or corrupted archive, a digest mismatch found only when the file is read). It is also computed at this response's at, which is one instant for the whole project — a restore targets one generation's own lastAt, so re-query with ?at=<that generation's lastAt> before trusting this field for that restore. |
at | string | No | — |
holders | string[] | Yes | Every node holding an initialized object of this project. |
components | object[] | Yes | The newest component at or before at, one per node. |
missing | string[] | Yes | Nodes holding initialized objects with nothing archived at or before at. Their current bytes are not substituted — a restore that quietly used live bytes for a historical component would return a state that never existed. |
gaps | object[] | Yes | Nodes with an object initialized strictly after their selected component but at or before at — the object existed at the restore target and the archive has no file for it. An object initialized after at is not a gap: it did not exist at the target, and a restore removes its placement instead. It is separate from missing because the two mean different things. missing is "this node has no backup"; this is "this node's backup predates some of the objects that existed at the restore target". A restore to this point would leave those objects unopenable. |
complete | boolean | Yes | available with neither missing nor gaps. The pieces are identified and cover every object that existed at at. See restorable for whether the restore preflight would accept them; neither field promises the restore itself will succeed. |
keepDays | integer | Yes | The retention window in days, from the org plan's value. |
One backup generation of a project's database.
| Field | Type | Required | Description |
|---|
epoch | integer | Yes | — |
seq | integer | Yes | Increases monotonically within an epoch. Restore identifies a generation by (epoch, seq). |
key | string | Yes | Offsite key (gen/<project>/<epoch>/<stamp>-<seq>.log) |
bytes | integer | Yes | The size of the object stored offsite. An encrypted backup is larger than the plaintext. For a commit log this is the size of the logged page versions only — see imageBytes for the size of the database a restore produces. |
full | boolean | Yes | true when this object alone restores the database; false for a commit log, which is replayed on top of the chain that ends at prevTxnId. Restoring a log pours its whole chain (full first); the chain is resolved by the server and never crosses an epoch. |
prevTxnId | integer | No | For a commit log, the last commit of the backup it links to. 0 for a full. |
imageBytes | integer | Yes | The size of the database a restore of this generation produces. |
firstTxnId | integer | Yes | The first commit this backup carries. A backup is an ordered log of the commits since the previous one, so every commit in [firstTxnId, txnId] is a restore point (RestoreRequest.txnId). A historical full may carry a range. Equal to txnId for a single-commit full or a backup with no commits. |
commitCount | integer | Yes | How many commits this backup carries. A full backup may preserve multiple pending commits. Zero means no writes since the previous backup. |
firstAt | string | No | Wall-clock time of the first commit carried. Absent when commitCount is 0. |
lastAt | string | No | Wall-clock time of the last commit carried. Absent when commitCount is 0. |
sha256 | string | Yes | — |
plainBytes | integer | No | The size of the plaintext (feather image) inside the encrypted data. For plaintext generations, this equals bytes |
keyVersion | integer | No | The encryption key version used. 0 means plaintext (a generation created without a key) |
txnId | integer | Yes | Commit number that the image contains. 0 means unknown. |
kind | string | No | Why the generation was created. Not used for decisions. park, evict and deploy are the shipment taken right before the process stops. |
createdAt | string | Yes | — |
node | string | No | The node that captured the generation |
latest | boolean | Yes | Marks the generation the project's latest-backup pointer refers to. The pointer only ever moves forward, so a later generation from an older epoch cannot claim it. |
final | boolean | Yes | A safety copy taken right before eviction, deletion, or restore. It is listed with regular generations, but pruning does not count it. |
A restore point, given in exactly one of three ways. (epoch, seq) restores to the
end of that backup. txnId restores to that commit, which may be inside a backup — every
backup carries the commits between it and the previous one in order, so any of them is a
restore point (GenerationRow.firstTxnId … txnId). at uses stored millisecond timestamps and restores to the last commit at
or before that time (RFC 3339); the resolution is one backup interval.
| Field | Type | Required | Description |
|---|
epoch | integer | No | — |
seq | integer | No | — |
txnId | integer | No | A commit to restore to. Must lie inside some backup's [firstTxnId, txnId]. |
at | string | No | Restore to the last commit at or before this time. |
| Field | Type | Required | Description |
|---|
confirm | string | Yes | Must match the project name exactly. This is the only confirmation a script running with --yes has to pass, so it is checked on the server. |
This response means the multi-step operation was queued (202). It does not mean it
finished — check progress at …/database/operations/{opId}.
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
opId | string | Yes | — |
kind | string | Yes | — |
epoch | integer | Yes | — |
node | string | No | — |
purgeAfter | string | No | Project deletion only. When the project's data is actually destroyed. The project is already gone from every surface — this is the date the bytes stop existing. Read this value rather than computing it from a retention window. |
| Field | Type | Required | Description |
|---|
opId | string | Yes | — |
kind | string | Yes | — |
projectId | string | Yes | — |
phase | string | Yes | The step currently in progress (draining, sealing, committing, and so on). It only changes when real progress is made, so it is safe to print on change. |
attempt | integer | No | — |
deferrals | integer | No | — |
owner | string | No | — |
terminalCode | string | No | The reason it ended. aborted means a person stopped it, and any other value is a failure. Empty with done means success. |
failedAt | string | No | — |
error | string | No | — |
done | boolean | Yes | Does not proceed further. terminalCode distinguishes success, failure, and abort |
retryAfterSeconds | integer | No | Seconds remaining until the next attempt. 0 means it is ready to process now, so this value tells waiting-for-backoff apart from actively running. |
The runlot.json inside your deployment bundle. It does not travel in the HTTP body,
but it is part of the contract, so it is documented here.
| Field | Type | Required | Description |
|---|
main | object | No | The worker entry point's path within the bundle. If absent, this is a pure static site (the same model as Workers Static Assets). |
assets | object | No | Path to the static assets directory within the bundle |
compatibilityDate | string | No | — |
notFound | string | No | The answer for a path that is not in the assets. With spa, a path without an extension is served /index.html (client-side routing). The default is 404. A path with an extension is still a 404 under spa, so a missing bundle never becomes a silent 200. |
observability | object | No | Observability switches (docs/customer-error-tracking.md, docs/customer-observability.md). Error capture runs in the worker's own isolate and is on unless errors is false: uncaught exceptions, rejected waitUntil promises, console.error(err) and runlot:errors reports become error events. Platform failures (out of memory, crashes, boot and build failures) are recorded either way. logs and traces collect each sampled invocation's console lines, exceptions and spans. Both are off unless enabled is true; the dashboard's settings take precedence over them. tags are added to every env.metrics point; routes are declared route templates such as /users/:id/orders. browser is an opt-out only (docs/customer-error-tracking.md §12): the browser agent is on by default for Pro projects, and the plan is the control plane's decision, never the bundle's. false turns injection off; true or absent changes nothing, and never turns it on for a plan that does not include it. monitors is the repository's .runlot/monitors/*.json, embedded by the CLI (docs/customer-observability.md §17.8). Each needs a key; when the deployment goes live they replace the project's repository monitors by key. Absent changes nothing; an empty list removes every repository monitor. |
tail_consumers | object[] | No | Exports of the main module that receive this worker's traces through workerd's tail mechanism (docs/customer-observability.md §12). The plan bounds how many. |
runWorkerFirst | boolean | No | Who sees a request first when the project has both a worker and an assets directory. The default is true: the worker is the entry point and the disk is not consulted ahead of it. With false an exact file wins and everything else is handed to the worker — which is the order a framework's own server build (React Router, Astro, SvelteKit, Nuxt) is written against. |
compatibilityFlags | string[] | No | The workerd compatibility flags to enable for the worker. Only flags on the allow list are accepted; anything else is rejected at deploy time. Do not include experimental — it is added for you. nodejs_compat: for libraries (TypeORM, Sequelize, Knex) that require Node built-in modules (node:events, node:util, …). The CLI adds this when the bundle imports a Node built-in. runlot_isolated_preview_http_v1 is a reserved server seal found only on isolated preview artifacts. Ordinary customer deployments cannot supply it, and the flag alone grants no policy or execution permission. |
modules | ManifestModule[] | No | A workerd module loaded separately next to the entry point. Currently only wasm — workerd blocks compiling WASM inside the bundle (for example, Prisma 7's query compiler), so WASM can only enter this way. name is exactly the specifier the worker code imports, and path is the file inside the bundle. The CLI writes one entry per .wasm import left by the bundle. |
framework | string | No | A marker that the deploy tool bundled with a framework adapter. If next, the two bindings OpenNext looks for are also rendered (ASSETS alias, WORKER_SELF_REFERENCE). Unknown values cause the deployment to be rejected. |
triggers | ManifestTriggers | No | — |
queues | ManifestQueues | No | — |
durable_objects | ManifestDurableObjects | No | — |
migrations | ManifestDurableObjectMigration[] | No | The append-only history that creates this project's Durable Object classes. It is top-level rather than part of a binding: a class stays created after the binding that reached it is deleted. The array is the history and its order is the order it happened in. Nothing sorts it and nothing rewrites a tag. A tag is unique across the history, every step has to create at least one class no earlier step created, and a project may have at most 32 distinct classes. Every binding's class_name has to appear in one of these steps or the deployment is refused; a class no binding reaches is accepted with a warning. Only new_classes and new_sqlite_classes are supported. renamed_classes, deleted_classes and transferred_classes are refused by name rather than ignored, so a dropped migration key can never report a successful deploy while the class the worker exports has no objects under it. |
email | boolean | No | Declares email sending and receiving. When true, the worker receives env.email, and export default { email() } becomes the receiving handler. This only makes sense if main is present — static assets alone have no code to send or receive with. |
ai | boolean | No | Declares the AI runtime binding. When true and the project has an AI grant, the worker receives env.ai. Declare it here so each deployment states for itself whether its code asked for the binding. |
trustedCertificates | string[] | No | PEM files inside the bundle whose certificates are added to the trust store used for outbound TLS by this project's worker. Use it to reach an origin that omits its intermediate certificate. Such an origin cannot be reached at all otherwise: the handshake fails before any JavaScript runs, so nothing in the app can repair it. Every entry must sit under certs/. Each file is parsed at deploy time and an expired certificate is rejected; one inside its last 90 days is accepted with a warning. The system trust store is always kept, so this adds trust and never replaces it. Requires main. |
access | ManifestAccessRule[] | No | Path rules that narrow the project's access policy (runlot access) for this deployment. Each request is checked against every rule whose path matches it, and every matching rule must hold; a refused request gets 403 access_rule_denied. The rules only apply while the policy is org or password. On a public project they are ignored (the deploy warns), because there is no identity to test. A visitor admitted by the shared password or the automation bypass secret satisfies only a rule with an empty require. The rules move with the deployment: rolling back restores the old list. |
One manifest path rule (access[]).
| Field | Type | Required | Description |
|---|
path | string | Yes | An absolute path. An exact path, or a prefix ending in /*, which also covers the prefix itself (/admin/* covers /admin and /admin/x). * is accepted nowhere else. Matching is case-insensitive on the cleaned request path. |
require | object | Yes | What the visitor must satisfy. Every field that is set must hold; {} admits anyone the project policy already admitted. |
Scheduled execution. It ships in the bundle exactly as you wrote it in
runlot.json.
Cron is the only trigger today, but it is accepted as an object so that adding
other trigger kinds later will not change what you write.
| Field | Type | Required | Description |
|---|
crons | string[] | No | A 5-field cron expression (minute hour day month weekday), in UTC. It has 1-minute granularity, with up to 5 schedules per project; the org-wide limit comes from the plan. The expression is parsed at deploy time — invalid syntax, or an expression that never fires in the future (0 0 30 2 *), returns 400. Anything that merely looks like a cron expression would otherwise deploy fine and never run. If triggers is set, main must also be set: a deployment with only static assets has no scheduled handler. |
names | object | No | A name for each schedule, keyed by its expression, shown in the dashboard and in runlot cron. Optional and per expression. Every key must be one of crons; a name is one line of at most 80 bytes. |
Queues. Two lists. A project may produce into a queue it does not consume, and
consume a queue it never produces into — a dead-letter queue is that case — so
neither list implies the other.
Every distinct name across both lists, dead-letter queues included, counts against
the per-project bound of 5; the org-wide bound comes from the plan (free 5,
pro 25) and a deployment past it is refused with 400 queue_limit. Requires main
and database: the messages are rows in the project's own database.
| Field | Type | Required | Description |
|---|
producers | object[] | No | — |
consumers | object[] | No | — |
Durable Objects. One list of bindings, spelled with snake_case keys, which
the rest of this manifest does not use, so that a durable_objects block can be
copied in as a whole.
It ships in the bundle because the class a binding points at is a property of your
code. Requires main: a Durable Object is a class the worker exports, and
static-only deployments export none.
| Field | Type | Required | Description |
|---|
bindings | object[] | No | — |
One step of the Durable Object migration history.
The two kinds are not the same class. Both are stored on SQLite, but a class
created as new_classes has enableSql false and never gains a SQL surface. That
split follows the upstream compatibility contract and survives into the deployed
configuration.
| Field | Type | Required | Description |
|---|
tag | string | Yes | Names this step, ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$, unique across the history. Compare tags between two deployments to see what moved; keep it printable in a log line without quoting. |
new_classes | string[] | No | Classes created without ctx.storage.sql (enableSql = false). |
new_sqlite_classes | string[] | No | Classes created with ctx.storage.sql. |
| Field | Type | Required | Description |
|---|
name | string | Yes | The specifier the worker imports. Alphanumeric and ._-, slash-separated, does not start with .. worker cannot be used because it is the entry module. |
type | string | Yes | — |
path | string | Yes | File path inside the bundle |
Roles contain one another — anything a viewer can do, a member can also do, and
anything a member can do, an admin can also do.
Type: string
| Field | Type | Required | Description |
|---|
userId | string | Yes | — |
provider | string | Yes | — |
subject | string | Yes | — |
email | object | No | — |
name | object | No | — |
role | Role | Yes | — |
addedAt | string | Yes | — |
The answer to deleting an org. The org is already gone from every surface;
purgeAfter is when its rows are erased for good. Read that date here rather than
computing it, so a later settings change cannot restate it.
| Field | Type | Required | Description |
|---|
orgId | string | Yes | — |
slug | string | Yes | — |
purgeAfter | string | Yes | — |
One kind of thing the org still holds (the org_not_empty details).
| Field | Type | Required | Description |
|---|
kind | string | Yes | — |
count | integer | Yes | — |
names | string[] | No | Only the first few, so the error message stays readable. |
expired is the result of a time comparison, not a stored state — an invite is
never marked expired, its expiry time has simply passed.
Type: string
No token. The plaintext invite token is only ever sent in the invitation email
and is never returned by the API.
| Field | Type | Required | Description |
|---|
inviteId | string | Yes | — |
email | string | Yes | — |
role | Role | Yes | — |
state | InviteState | Yes | — |
invitedBy | string | No | The inviter's name or email. |
createdAt | string | Yes | — |
expiresAt | string | Yes | — |
sentAt | string | No | If empty, the invitation email is still queued to be sent. |
sendError | string | No | The reason the last send failed. This can remain set even after a success. |
The invite as seen by whoever holds the invite link. No authentication needed.
| Field | Type | Required | Description |
|---|
orgSlug | string | Yes | — |
orgName | string | Yes | — |
role | Role | Yes | — |
email | string | Yes | The address the invite was sent to. It can differ from the address of the account that accepts it, and the UI should say so. |
invitedBy | string | No | — |
state | InviteState | Yes | — |
expiresAt | string | Yes | — |
Becomes the worker's env.<NAME>. DB and ASSETS are reserved, because they are the
uppercase counterparts of the env.db and env.assets bindings, and so is any name
beginning with RUNLOT_.
Type: string
| Field | Type | Required | Description |
|---|
name | SecretName | Yes | — |
version | integer | Yes | Increases by 1 each time you replace the secret with a PUT. |
updatedAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
secrets | SecretMeta[] | Yes | — |
A single line of the log stream. Distinguished by type — line is an output line,
ping is a 15-second heartbeat, and end is the reason the server ended it.
| Field | Type | Required | Description |
|---|
type | string | Yes | — |
ts | string | No | When the line was produced (line events only) |
epoch | integer | No | — |
generation | integer | No | The worker process generation. Increments each time the process is replaced. |
stream | string | No | runlot is a line written by the platform rather than your worker — events such as startup, exit code, and the number of dropped lines. |
line | string | No | Without a trailing newline. Past 64 KiB it is truncated and truncated is set. |
truncated | boolean | No | — |
reason | string | No | Reason for end: process_exited, client_gone, node_shutdown |
One stored log line. It is not a LogEvent: there is no type, because a stored line
is never a heartbeat or an end-of-stream, and there is a seq, because the page cursor
needs a tiebreaker for lines that share a timestamp.
| Field | Type | Required | Description |
|---|
ts | string | Yes | When the line was produced, not when it was stored. |
seq | integer | Yes | Monotonic insert order. With ts it forms the page cursor. |
epoch | integer | No | — |
generation | integer | No | The worker process generation. Increments each time the process is replaced. |
stream | string | Yes | runlot is a line written by the platform rather than your worker — startup, exit code, dropped-line counts, and the daily-cap marker. |
line | string | Yes | — |
| Field | Type | Required | Description |
|---|
lines | LogHistoryLine[] | Yes | Newest first. |
cursor | string | No | Pass back as cursor for the next (older) page. Absent means there is nothing older — an empty lines with a cursor present never happens. |
keepDays | integer | Yes | This org's log retention, in days (Free 3, Pro 7). Use it to tell an empty page that means "nothing happened" apart from one that means "that is older than we keep". |
linesPerDay | integer | Yes | This org's daily stored-line cap (Free 200000, Pro 2000000). |
| Field | Type | Required | Description |
|---|
projectId | string | Yes | — |
hours | integer | Yes | — |
rows | UsageRow[] | Yes | — |
totals | object | Yes | — |
dbBytes | integer | Yes | The most recently observed database size, in bytes. 0 if there is no observation. |
objBytes | integer | Yes | The most recently observed object storage size, in bytes. This is a gauge, not a sum — adding it up across time buckets counts the same bytes once per hour. |
| Field | Type | Required | Description |
|---|
sql | string | Yes | The statement, exactly as typed. Nothing is appended to it. |
readOnly | boolean | No | Absent means true. Read-only runs inside BEGIN … READ ONLY and rolls back unconditionally; write mode runs outside a transaction so the statement commits on its own. |
params | object[] | No | Values for $1, $2, … They are sent separately from the statement text rather than pasted into it, so you never have to quote or escape a value yourself. |
| Field | Type | Required | Description |
|---|
columns | string[] | Yes | Column names in the order the server returned them. Empty for a statement with no result set. |
rows | string[][] | Yes | One entry per listed row, each an array parallel to columns. Every value is a string or null — JSON numbers are IEEE doubles, so a bigint past 2^53 would arrive rounded. null is SQL NULL; "" is the empty string. |
rowCount | integer | Yes | What the statement reported — rows produced or rows touched. Not rows.length: when the response is truncated the two differ, and that difference is what truncated is about. |
truncated | boolean | Yes | the 500-row response cap cut the result short |
command | string | Yes | the server's command tag (SELECT, UPDATE, CREATE TABLE …) |
readOnly | boolean | Yes | the mode that actually ran, which can differ from the mode you asked for (absent is read-only) |
elapsedMs | integer | Yes | The round trip as the control plane measured it. It includes connecting, so it is not the statement's own execution time. |
| Field | Type | Required | Description |
|---|
hour | string | Yes | start of the time window (UTC, on the hour) |
requests | integer | Yes | — |
cpuMs | integer | Yes | — |
dbBytes | integer | Yes | — |
objBytes | integer | Yes | gauge (last observed value) |
objOps | integer | Yes | cumulative (sum of deltas) |
mailOut | integer | Yes | cumulative (sum of deltas) |
mailIn | integer | Yes | cumulative (sum of deltas) |
aiCalls | integer | Yes | cumulative (sum of deltas) |
aiTokensIn | integer | Yes | cumulative (sum of deltas) |
aiTokensOut | integer | Yes | cumulative (sum of deltas) |
errors5xx | integer | Yes | cumulative; a subset of requests |
p50Ms | integer | Yes | this hour's median duration, derived from its histogram at read time |
p99Ms | integer | Yes | this hour's 99th percentile, same derivation |
latSamples | integer | Yes | How many request durations this hour's histogram holds. 0 means the hour has no percentile, which is a different fact from "the percentile is 0 ms" — a chart that cannot tell them apart draws a flat floor that never happened. |
memPeakBytes | object | Yes | The hour's highest memory reading of the project's cgroup, in bytes. Null when nothing measured the hour — a different fact from zero, which a chart must not draw as a floor. |
memLimitBytes | object | Yes | The memory limit (memory.max) in force that hour, in bytes. Null when not measured; 0 is no limit. |
oomKills | integer | Yes | Workers stopped that hour for exceeding the memory limit (cumulative). |
memHighEvents | integer | Yes | Times that hour the project was throttled at its soft memory mark (memory.high) before anything was stopped — slow answers rather than failed ones (cumulative). |
One model in the AI catalog.
| Field | Type | Required | Description |
|---|
id | string | Yes | The string you write in env.ai.run() or env.ai.embed(). Frontier models are <provider>/<model>, value models are @runlot/<model> |
kind | string | Yes | What the model does. chat is env.ai.run — tokens in, tokens out. embedding is env.ai.embed — text in, a vector out: maxOutputTokens and outPerMTok are 0, and dimensions says how wide the vector is. |
dimensions | integer | No | Embedding models only: the width of the vector the model answers by default. |
dimensionOptions | integer[] | No | Embedding models only: every width env.ai.embed(model, input, { dimensions }) may ask for. Absent when only the default is answered. |
taskTypes | string[] | No | Embedding models only: every value env.ai.embed(model, input, { taskType }) may carry. A task type tells the model what the vectors are for, and the same text embedded under two of them is a different vector — so a namespace has to be filled under one choice and queried under the same one. Absent when the model has no such notion (Titan has none). Leaving taskType out sends the model's own default, which is what every vector stored before this option existed was embedded under. |
effortLevels | string[] | No | Chat models only: every value env.ai.run(model, { reasoning: { effort } }) may carry. Absent when the model has no reasoning-effort control (@runlot/… have none), in which case asking for one is 400 bad_effort rather than a silently ignored field. The vocabularies differ by family — the OpenAI rows include none, the Claude rows do not, and Gemini has only low/medium/high. Leaving reasoning out sends the model's own default. |
structuredOutput | boolean | No | Chat models only, present when true: env.ai.run(model, { responseFormat }) is honoured on this model. False or absent means asking for a response format is 400 format_unsupported rather than prose wearing the caller's schema. Read off each model card, so it is a per-row fact and not a family rule — Claude Haiku 4.5 has it and Claude Sonnet 5 does not, on the same endpoint. |
lane | string | Yes | — |
display | string | Yes | — |
vendor | string | Yes | who built the model (Anthropic, Google, Meta, and so on) |
provider | string | No | The provider the call is served by. Included for frontier models only — the provider behind a value model can change. |
contextTokens | integer | Yes | the model's own context window |
maxInputTokens | integer | Yes | The input limit runlot allows for this model. It is the same as contextTokens for most models; where it is lower it marks a price boundary — the OpenAI models are 272,000 and Gemini 3.1 Pro is 200,000, the point past which the provider switches the whole request to a higher rate. |
maxOutputTokens | integer | Yes | — |
inPerMTok | integer | Yes | microcents per million input tokens |
outPerMTok | integer | Yes | — |
cachedInPerMTok | integer | No | The price of cached input. Absent means the model has no cache discount and cached tokens are billed at the full input price |
listPrice | boolean | Yes | When true, this is the provider's list price, passed straight through with no margin added. |
| Field | Type | Required | Description |
|---|
granted | boolean | Yes | — |
perMinute | integer | Yes | calls per minute, per project |
concurrent | integer | Yes | concurrent calls, per project |
maxOutputTokens | integer | No | 0 means the model decides |
maxInputTokens | integer | No | 0 means the model decides |
creditMicroCents | integer | Yes | the org balance (can be negative) |
freeDailyMicroCents | integer | No | the daily allowance, for value models only |
byos | boolean | No | anthropic/* and openai/* calls from the deployed app are served by a Claude or Codex subscription signed in on a Studio desktop of one of your organization's members, and no credit is charged. A desktop only serves apps whose own user turned lending on and enabled that model. |
byosCreditFallback | boolean | No | What happens when no desktop can take the call. On, the ordinary credit path runs and the call is billed as usual; off, the call is a 503 byos_unavailable and nothing is charged. |
calls24h | integer | No | — |
tokensIn24h | integer | No | — |
tokensOut24h | integer | No | — |
spentMicroCents24h | integer | No | What the org spent on AI in the last 24 hours (positive = amount spent) |
| Field | Type | Required | Description |
|---|
belowMicroCents | integer | Yes | — |
microCents | integer | Yes | — |
| Field | Type | Required | Description |
|---|
enabled | boolean | Yes | false means AI credit is not available here — the top-up endpoints answer 501 |
sandbox | boolean | Yes | — |
microCents | integer | Yes | the balance (can be negative) |
heldMicroCents | integer | No | The part of the balance your running apps have set aside for calls in progress. It is still yours — what a call does not use returns to the balance. Zero when nothing is held |
lowMicroCents | integer | No | — |
freeDailyMicroCents | integer | No | — |
tiers | integer[] | Yes | The top-up amounts you can choose from. Auto top-up uses the same list |
hasPaymentMethod | boolean | Yes | When false, auto top-up cannot be turned on — your first top-up is what saves the card |
autoTopup | AIAutoTopup | No | — |
autoTopupsToday | integer | Yes | — |
autoTopupPerDay | integer | Yes | the most automatic top-ups that can run in one day |
| Field | Type | Required | Description |
|---|
key | string | Yes | The key as the worker writes it, without the internal project prefix. |
size | integer | Yes | — |
type | string | Yes | the stored content type |
modified | string | Yes | — |
public | boolean | Yes | Whether this key sits under one of the project's published prefixes. |
url | string | No | The unsigned public address, present only when public is true and this installation has a public object front. It is never a signed URL. |
| Field | Type | Required | Description |
|---|
entries | StorageObject[] | Yes | — |
prefixes | string[] | Yes | The directories one level under the requested prefix, each ending in /. Pass one back as prefix. |
cursor | string | No | Pass it back to get the next page. Absent means the end. |
publicPrefixes | string[] | Yes | The project's published prefixes, carried on every page so a client can explain the public marks without a second call. |
publicBase | string | No | https://<objects host>/<org>/<project>. Absent when this installation has no public object front. |
| Field | Type | Required | Description |
|---|
key | string | Yes | — |
url | string | Yes | A signed GET. Fetch it directly; the bytes do not pass through this API. |
expiresAt | string | Yes | When the signature stops working. It travels with the URL so a client does not learn the lifetime from documentation and then cache past it. |
size | integer | Yes | — |
type | string | Yes | — |
modified | string | Yes | — |
public | boolean | Yes | — |
One end user of the app (runlot_auth.users, docs/auth.md §6).
| Field | Type | Required | Description |
|---|
id | string | Yes | — |
email | string | Yes | Lowercased. Empty for an account that has only a social identity. |
name | string | No | — |
providers | string[] | Yes | password, github, google, runlot, OIDC ids … sorted, from the linked identities. |
createdAt | string | Yes | — |
lastSignIn | string | No | Absent for somebody who has never signed in. |
blocked | boolean | Yes | banned_at is set. Changing it is not on this surface. |
sessions | integer | Yes | Live sessions only. Expired rows stay until the sweeper runs and counting them would show a signed-out person as signed in. |
| Field | Type | Required | Description |
|---|
users | AppUser[] | Yes | — |
cursor | string | No | Pass it back to get the next page. Absent means the end. |
| Field | Type | Required | Description |
|---|
kind | string | Yes | — |
lane | string | Yes | Which caller spent it. It is present on every row including a top-up, where it is app and means nothing. |
model | string | No | — |
project | string | No | — |
tokensIn | integer | No | — |
tokensOut | integer | No | — |
microCents | integer | Yes | call rows are negative |
at | string | Yes | — |
The project's email status.
| Field | Type | Required | Description |
|---|
granted | boolean | Yes | Whether email is turned on for this project. |
address | string | Yes | The project's mail domain. It receives everything at *@<address>. |
from | string | Yes | Sender address. The From of mail sent by env.email.send. |
perHour | integer | Yes | Hourly send limit. Authentication email counts against the same limit. |
sentLastHour | integer | Yes | number sent in the current time window |
receivedLastHour | integer | Yes | number received in the current time window |
sent24h | integer | Yes | number sent in the last 24 hours |
received24h | integer | Yes | number received in the last 24 hours |
mailDomain | string | Yes | The mail domain suffix for this installation. Email cannot be enabled if it is empty. |
One record you publish in your own DNS. The values are computed by the server, so the
dashboard, the CLI, and the documentation always agree on them.
| Field | Type | Required | Description |
|---|
type | string | Yes | — |
name | string | Yes | — |
value | string | Yes | — |
required | boolean | Yes | true for the three DKIM CNAMEs — verification does not pass without them. false for SPF and DMARC: they improve alignment and do not gate anything, and if you already have your own SPF record you should keep it. |
One custom sending domain and its verification state.
| Field | Type | Required | Description |
|---|
domain | string | Yes | — |
state | string | Yes | pending — the identity exists and DKIM is not signing yet. verified — the only state env.email.send({ from }) accepts. failed — the provider gave up, or the records were not visible within 72 hours. |
isDefault | boolean | Yes | At most one per project. |
dkimOk | boolean | Yes | Whether DKIM is signing. This is what state is computed from. |
spfOk | boolean | Yes | Checked but never gating — a missing SPF record does not stop delivery. |
lastError | string | No | A readable reason for the current state. Empty once the domain is verified. |
createdAt | string | Yes | — |
verifiedAt | string | No | Stamped once; it does not move on re-verification. |
lastCheckedAt | string | No | — |
records | EmailDNSRecord[] | Yes | Served in every state — when a domain fails, compare what you published against this. |
published | boolean | Yes | True when the records already live in a zone we host, so there is nothing for you to publish. |
One line of the email log.
| Field | Type | Required | Description |
|---|
mailId | string | Yes | — |
projectId | string | Yes | — |
direction | string | Yes | — |
at | string | Yes | — |
from | string | Yes | — |
to | string[] | Yes | — |
subject | string | Yes | — |
outcome | string | Yes | Outbound: sent → delivered, bounced, complained (feedback from the receiving side), or failed / Inbound: ok, rejected, no_handler, exception |
detail | string | No | rejection sentence or error sentence — a human-readable line |
authResults | string | No | Authentication-Results of the received message |
sizeBytes | integer | Yes | — |
hasRaw | boolean | Yes | whether the original message text is kept |
requestId | string | No | Inbound only: the request ID of the delivery's invocation record — the value the worker received as the runlot-request-id header. Absent for outbound mail and on deliveries recorded before request IDs existed. |
| Field | Type | Required | Description |
|---|
entries | MailLogEntry[] | Yes | — |
cursor | string | No | next page. absent means the end |
keepDays | integer | Yes | number of days this org retains |
| Field | Type | Required | Description |
|---|
enabled | boolean | Yes | billing is configured for this deployment |
sandbox | boolean | Yes | test billing environment — no real charges |
plan | string | Yes | — |
status | string | No | The Pro status. Canceled stays Pro until the period ends. Granted is Pro provided by Runlot — no subscription, no charges. Free has none |
periodEnd | string | No | end of the current billing period |
hasPortal | boolean | Yes | has billing history, so the portal can be opened |
projectCount | integer | Yes | Current project count. If an org is over the Free limit after downgrading, existing projects are kept — only creating new ones is blocked |
limits | object | Yes | — |
The limits that apply to one plan
| Field | Type | Required | Description |
|---|
projects | integer | Yes | — |
storageBytes | integer | Yes | — |
dbCapBytes | integer | Yes | The project Postgres size cap for this plan (Free 500 MiB, Pro 8 GiB). The dashboard's usage meter and chart read this value, and you are notified when a project passes 90% of it. |
backupKeep | integer | Yes | how many database generations are retained |
crons | integer | Yes | — |
mailPerHour | integer | Yes | — |
The state of the project's dedicated object storage.
Objects are not part of database generations — runlot pg restore does not roll back
files. Read-after-write is guaranteed, but list may lag.
| Field | Type | Required | Description |
|---|
granted | boolean | Yes | Whether object storage is turned on for this project. When it is off, there is no bucket at all, and prefix and quotaBytes are empty. |
prefix | string | Yes | The prefix every object of this project is stored under. It is added for you, so your own keys stay relative to it and no key you send can reach another project's storage. Empty when storage is not configured. |
quotaBytes | integer | Yes | The quota (10 GiB on Free, 100 GiB on Pro). Once you exceed it, only put and presign(PUT) are rejected — get, list, and delete keep working, so you can always delete your way back under the cap. Without storage enabled, it is 0. |
usedBytes | integer | Yes | The last observed byte count. It lags a little behind your writes, so usage can briefly go past the quota in between. 0 if there is no observation yet. |
One key prefix to publish or unpublish.
| Field | Type | Required | Description |
|---|
prefix | string | Yes | The prefix, relative to the project's own storage — assets, assets/, or avatars/img. It is stored with a trailing slash, because matching is a plain string prefix test and assets without the slash would also open assets-private/. / means every key in the project. The empty string is refused, so an accidentally empty argument cannot publish everything by looking like a default. |
The prefixes this project serves without a signature. All three verbs answer with the
full list, so a screen never has to guess what the list became after a change.
| Field | Type | Required | Description |
|---|
prefixes | object[] | Yes | — |
publicBase | string | No | https://<objects host>/<org>/<project> — the address every prefix in the list is readable under (a key assets/logo.png is at <publicBase>/assets/logo.png). It is the same value env.storage.publicUrl builds on. Absent when this deployment has no public object host, in which case nothing is served unsigned and publicUrl answers null everywhere. |
Deployment access policy. Only non-secret state is returned. Passwords and bypass
keys are stored as hashes, and their values are never returned by a read.
A project that has never set a policy reads as mode: public with no updatedAt.
| Field | Type | Required | Description |
|---|
mode | string | Yes | public means anyone, org means a member or higher of the org that owns the project, password means one shared password for the project, and app means only people signed in to this app through env.auth (docs/auth-access-unify.md §3). |
hasPassword | boolean | Yes | Whether a password is set. The value itself is never returned. |
hasBypass | boolean | Yes | Whether a bypass key for automation exists. The key is shown only once, when it is issued. |
updatedAt | string | No | Omitted if never set |
A bypass key for automation. It is returned only in this response. You cannot view
it again, and issuing a new one immediately invalidates the previous key.
| Field | Type | Required | Description |
|---|
secret | string | Yes | Passed through as-is in the Runlot-Access-Bypass header |
The URL back to the protected deployment. It carries a one-time code (60 seconds, single
use, scoped to that project); following it sets a cookie and then redirects to the
original URL without the code, so the code never stays in the address bar.
| Field | Type | Required | Description |
|---|
redirect | string | Yes | — |
A login provider id. github and google are your own OAuth apps, runlot is
Runlot's sign-in (email, Google and GitHub at Runlot), and any other id is an OIDC
provider the project registered under that name.
Type: string
End-user authentication settings for the project.
| Field | Type | Required | Description |
|---|
allowSignup | boolean | Yes | Whether new signups are accepted. Turn it off to let only existing users log in — useful for invite-only apps or closing off a beta. |
requireVerifiedEmail | boolean | Yes | Whether email verification is required to log in. When enabled, unverified users cannot get a session from env.auth.user(request). |
sessionDays | integer | Yes | The lifetime of the session cookie, in days. Longer sessions also mean more session rows in your project database, which has a size cap: 10,000 active users on three devices each is roughly 6 MB of session data. |
brand | AuthBrand | Yes | — |
rls | boolean | Yes | Automatic row level security. When on, env.db statements from a signed-in user run as that user (runlot_authenticated), from a signed-out visitor as runlot_anon, and from cron and queue as the owner. Tables without row level security are closed to app users. Off by default. |
password | boolean | Yes | The email-and-password method. Off makes the password routes answer 404 method_disabled and hides the form; stored password hashes stay. |
magicLink | boolean | Yes | The email-link method. Off makes sign-in/email answer 404 method_disabled. |
Branding for the hosted login page. For finer-grained branding, build your own
page and call the JSON login endpoints instead. If all values are empty
strings, the project name and the default design are used.
| Field | Type | Required | Description |
|---|
name | string | Yes | The name shown on the page. Falls back to the project name if empty |
logo | string | Yes | Logo image URL. Nothing is drawn if empty |
color | string | Yes | Accent color #rrggbb. Falls back to the default accent colour when empty. |
A single registered login provider. Secrets are not included. The client ID is a
public value the browser sees anyway; the client secret is stored encrypted and is never
returned in any response.
| Field | Type | Required | Description |
|---|
provider | AuthProvider | Yes | — |
kind | string | Yes | builtin is your own GitHub or Google OAuth app, oidc a generic OpenID Connect provider, and runlot Runlot's sign-in (no callback URL to register). |
clientId | string | Yes | The public id given by the provider. Empty for runlot |
updatedAt | string | Yes | When it was last registered or replaced |
issuer | string | No | For github, the base URL of your own GitHub Enterprise Server installation (absent means github.com). For oidc, the issuer URL. |
displayName | string | No | OIDC only. The button label on the hosted sign-in page |
iconUrl | string | No | OIDC only. The button icon on the hosted sign-in page |
scopes | string | No | OIDC only. Space-separated scopes requested at sign-in |
The project's end-user authentication status.
This API does not serve the end-user table. Those accounts live in the
runlot_auth schema of the project's own Postgres, so they travel with project
deletion, pg export, generational backup, and restore.
| Field | Type | Required | Description |
|---|
granted | boolean | Yes | Whether end-user authentication is turned on for this project. While it is off, settings holds default values and providers is an empty array. |
settings | AuthSettings | Yes | — |
providers | AuthProviderMeta[] | Yes | Registered login providers. Sorted alphabetically by name, not by registration order |
hosts | string[] | Yes | Every hostname this project answers on. Each host needs its own callback URL registered in the login provider's console — https://<host>/__runlot/auth/callback/<provider>. Add the callback URL to the login provider every time you connect a host. On a host you miss, login fails on that host alone, and the reason is visible only in the provider's console. The default hostname is <project>.<org>.<domain>. Register a callback URL for every host in this list — it is exactly the set of hosts this project answers on. |
A partial update of the settings. Only the fields you send change, so two people
editing different switches at the same time do not overwrite each other.
| Field | Type | Required | Description |
|---|
settings | object | Yes | A subset of AuthSettings. An empty object changes nothing |
The whole provider row; three shapes by kind:
- builtin (default;
github and google): {clientId, clientSecret}, and
issuer on github only. Both credentials are required every time.
- oidc (any other id):
{kind:"oidc", issuer, clientId, clientSecret, displayName?, iconUrl?, scopes?}. issuer must be https; the CP fetches
<issuer>/.well-known/openid-configuration when saving and pins its endpoints.
- runlot (id
runlot only): {kind:"runlot"} and no other field.
{"source":"managed"} is no longer accepted (400 managed_removed); use the
runlot provider.
| Field | Type | Required | Description |
|---|
kind | string | No | — |
clientId | string | No | The public id given by the provider. Required for builtin and oidc |
clientSecret | string | No | Required for builtin and oidc. Stored encrypted. It is never returned in any response. If you lose it, issue a new one from the login provider's console and PUT it again. |
issuer | string | No | On github: the base URL of your own GitHub Enterprise Server installation, for example https://github.acme.example; empty means github.com. This PUT is the whole row, so send it on every call. On google it is a 400. On oidc: required, the https issuer URL. |
displayName | string | No | OIDC only. The button label |
iconUrl | string | No | OIDC only. An https URL of the button icon |
scopes | string | No | OIDC only. Space-separated; defaults to openid email profile |
A single hostname attached to the project. state progresses from
pending_dns (verifying ownership) → pending_tls (issuing the certificate) →
active (connected), and the failure state is error. Only records with
active are included in routing.
| Field | Type | Required | Description |
|---|
hostname | string | Yes | Name normalized to punycode and lowercase |
kind | string | Yes | default is the default name <project>.<org>.<app-domain>. custom is a domain of your own |
state | string | Yes | — |
role | string | No | app serves your app. login is the project's login domain: it serves the Runlot sign-in page for this project on your own name, and never the app |
lastError | string | No | The reason the last check failed. Read it to fix your own DNS |
createdAt | string | Yes | — |
verify | HostnameVerify | No | — |
The two records you can add to your own DNS. Getting either one right proves
ownership — the CNAME also carries the traffic, so it is the recommended option. The
values are computed and returned here; read them rather than hardcoding them, because
they can change.
| Field | Type | Required | Description |
|---|
cname | HostnameRecord | Yes | — |
txt | HostnameRecord | Yes | — |
| Field | Type | Required | Description |
|---|
name | string | Yes | record name |
target | string | No | CNAME target |
value | string | No | TXT value |
| Field | Type | Required | Description |
|---|
hostnames | Hostname[] | Yes | — |
A zone in Runlot's authoritative DNS. serial increases on every change, and once
publishedSerial catches up, the nameservers are answering with that content.
| Field | Type | Required | Description |
|---|
zoneId | string | Yes | — |
orgId | string | Yes | — |
name | string | Yes | example.com (lowercase punycode, no trailing dot) |
serial | integer | Yes | — |
publishedSerial | integer | Yes | The serial last written to the zone file. If it is smaller than serial, propagation is still in progress (usually 2 seconds) |
dnssec | string | Yes | — |
ds | string[] | Yes | The DS record for the parent zone. If Runlot is the registrar we submit it for you; otherwise it is shown here to submit yourself. |
delegation | string | Yes | Result of a periodic check: whether the registrar's NS records point to us |
delegationCheckedAt | string | No | — |
nameservers | string[] | Yes | The nameservers to enter at the registrar |
createdAt | string | Yes | — |
A single zone and all its records.
Type: Zone & object
A (name, type) value pair. If managedBy is set, the row was created for you and is
locked in the editor — system (the zone's NS), hostname:<host> (a connected app),
acme (a certificate).
| Field | Type | Required | Description |
|---|
name | string | Yes | relative name. @ is the apex |
type | string | Yes | — |
ttl | integer | Yes | — |
records | string[] | Yes | — |
managedBy | string | No | — |
updatedAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
zones | Zone[] | Yes | — |
Availability and price of a single name.
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
available | boolean | Yes | — |
premium | boolean | Yes | A name the registry prices separately. Registration and renewal prices can differ a lot |
priceCents | integer | Yes | first registration, 1 year (in cents, not KRW) |
renewalCents | integer | Yes | renewal, 1 year |
The registrant's contact information. It belongs to you — ICANN's verification
email goes to this address, and the domain is suspended if it is not confirmed within
15 days.
| Field | Type | Required | Description |
|---|
firstName | string | Yes | — |
lastName | string | Yes | — |
org | string | No | — |
email | string | Yes | — |
phone | string | Yes | — |
address1 | string | Yes | — |
address2 | string | No | — |
city | string | Yes | — |
state | string | No | — |
zip | string | Yes | — |
country | string | Yes | ISO 3166-1 alpha-2 |
A single domain. Expiry date, lock state, and nameservers are copies of the
registrar's record and are refreshed every 6 hours.
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
zoneId | string | No | The Runlot zone for this domain. Always created on purchase or import |
registrar | string | Yes | external is a domain held in someone else's account — renewal and locking are not handled here |
state | string | Yes | This is derived from the expiration date: expiring starts 30 days before expiration, expired covers the 30-day grace period after expiration, redemption (redemption fee) covers the following 30 days, and released comes after that. transferred_out is when the registrar reports that it is no longer in our account. |
expiresAt | string | No | — |
autoRenew | boolean | Yes | This is your decision. Auto-renewal on the registrar side is always on — we renew first and bill afterwards. |
locked | boolean | Yes | Transfer lock |
nameservers | string[] | Yes | — |
years | integer | Yes | — |
priceCents | integer | No | the price paid, in cents |
sagaStep | string | Yes | If it is not done, the purchase is still in progress |
sagaError | string | No | reason it stopped. can be present even if the status is not failed |
createdAt | string | Yes | — |
One line of the domain's history (append-only). kind is one of purchase,
register_attempt, register, register_reconciled, zone, ds, done, renew,
lock, unlock, auto_renew, auth_code, state, transfer_out, import,
error, and so on. Auth codes and secrets are never stored here.
| Field | Type | Required | Description |
|---|
eventId | integer | Yes | — |
kind | string | Yes | — |
detail | object | No | — |
at | string | Yes | — |
Type: Domain & object
| Field | Type | Required | Description |
|---|
domains | Domain[] | Yes | — |
sandbox | boolean | Yes | If true, the registrar is a sandbox environment — nothing on this list was really registered. It is returned on the listing as well as on search, so a screen that only ever lists never shows names that look bought and are not. |
The licence payload minus its signature, the state computed from it, and the counts
against each ceiling. docs/onprem-delivery.md §6.2 is the payload's definition and
§6.3 the state machine.
| Field | Type | Required | Description |
|---|
onPrem | boolean | Yes | Whether this deployment is licensed at all — true when a licence file is configured. False is SaaS, and then state is none and every surface draws nothing. |
state | string | Yes | valid — in force. expiring — within 30 days of expiresAt; a banner and a daily notification. grace — past expiresAt and inside graceDays; nothing is refused yet. restricted — past grace, or the file is missing, or it does not parse or verify; new nodes, projects, deploys and sign-ups are refused and everything already running keeps running (§6.4). none — not an on-prem deployment. |
reason | string | No | Why the state is what it is, for the states that have a why: signature, expired, kid unknown, missing. Empty when there is nothing to explain. It is a code, not a sentence — the surfaces translate it, and a sentence from the server would arrive in one language on a trilingual screen. |
customer | string | No | The licensee's name, as it is printed in the footer on every page. |
tier | string | No | eval, single or ha (§6.1). eval is watermarked as an evaluation. |
expiresAt | string | Yes | When the term ends. Null when there is no licence. |
graceEnd | string | Yes | expiresAt plus the licence's grace days — the date new deploys stop. Null when there is no licence. |
maxNodes | integer | Yes | The node ceiling. Never 0 — the node is the unit of price (§6.1). |
maxProjects | integer | Yes | The project ceiling. 0 means unlimited. |
maxUsers | integer | Yes | The user ceiling. 0 means unlimited. |
features | string[] | Yes | The licensed feature names, from a closed set the binary knows (git, durable_objects, ai_byok). An unknown name is a parse error at issuance, not a silent grant of nothing. |
counts | object | Yes | What the installation is actually using, for nodes 1/1 and projects 42/∞. |
One panel. Exactly one source is set, and which one depends on type: timeseries, query_value, top_list, heatmap and distribution take a calculations query or a metric; table takes any query or a metric; log_stream an events or invocations query; issue_list issues; slo sloId; monitor_status monitors; markdown text; service_map nothing. A string value "$name" in a filter or a metric param is a template variable.
| Field | Type | Required | Description |
|---|
id | string | No | Default w<position>. |
type | string | Yes | — |
title | string | No | — |
position | object | No | — |
display | object | No | — |
query | object | No | A §7 query: view, filters, search, calculations, groupBy, orderBy, limit, granularity. Its timeframe is ignored; the dashboard's range wins. |
metric | object | No | — |
issues | object | No | — |
sloId | string | No | — |
monitors | object | No | — |
text | string | No | — |
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
key | string | Yes | The tag key it narrows: env, version, route, region, or any tag. |
default | string | No | "*" or empty is any value. |
label | string | No | — |
| Field | Type | Required | Description |
|---|
key | string | No | Stable name within the project; dashboards as code are upserted by it. May not start with builtin. |
title | string | Yes | — |
description | string | No | — |
layout | object | No | — |
widgets | DashboardWidget[] | Yes | — |
variables | DashboardVariable[] | No | — |
Type: DashboardInput & object
| Field | Type | Required | Description |
|---|
id | string | Yes | — |
key | string | Yes | — |
title | string | Yes | — |
description | string | No | — |
source | string | Yes | — |
widgets | integer | Yes | — |
public | boolean | Yes | — |
shared | boolean | Yes | — |
updatedAt | string | No | — |
| Field | Type | Required | Description |
|---|
dashboards | DashboardSummary[] | Yes | — |
limit | integer | Yes | Custom dashboards allowed per project; -1 is unlimited. |
custom | integer | Yes | — |
publicDashboards | boolean | Yes | — |
builtinVersion | integer | Yes | — |
| Field | Type | Required | Description |
|---|
token | string | Yes | Shown once. The link is /shared/dashboards/<token>. |
public | boolean | Yes | — |
publicDashboards | boolean | Yes | The project switch; while off the link answers 404. |
| Field | Type | Required | Description |
|---|
publicDashboards | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
from | string | No | — |
to | string | No | — |
variables | object | No | — |
| Field | Type | Required | Description |
|---|
widgetId | string | Yes | — |
type | string | Yes | — |
from | string | Yes | — |
to | string | Yes | — |
data | object | Yes | Shaped by the source: {step, series:[{name, group, points:[{t,v}]}]} for metrics, the query API's answer for queries, {issues} for issue lists, {edges} for the service map, {text} for markdown. |
| Field | Type | Required | Description |
|---|
title | string | Yes | — |
description | string | No | — |
layout | object | No | — |
widgets | DashboardWidget[] | Yes | — |
variables | DashboardVariable[] | No | — |
updatedAt | string | No | — |
metricKeepDays | integer | Yes | — |
| Field | Type | Required | Description |
|---|
kind | string | Yes | — |
at | string | Yes | — |
version | integer | No | — |
previousVersion | integer | No | — |
deploymentId | string | No | — |
commit | string | No | — |
peakBytes | integer | No | — |
limitBytes | integer | No | — |
| Field | Type | Required | Description |
|---|
from | string | Yes | — |
to | string | Yes | — |
markers | Marker[] | Yes | — |
| Field | Type | Required | Description |
|---|
id | string | Yes | — |
kind | string | Yes | — |
metric | string | Yes | p95_latency, error_rate, request_rate, memory_peak, db_time, failed_requests, or pattern:<id>. |
route | string | No | — |
startedAt | string | Yes | — |
endedAt | string | No | — |
magnitude | number | Yes | A ratio, a z-score or a count; hints.scale says which. |
deploymentId | string | No | — |
version | integer | No | — |
hints | object | Yes | — |
state | string | Yes | — |
createdAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
insights | Insight[] | Yes | — |
full | boolean | Yes | false on Free: deploy regressions only. |
| Field | Type | Required | Description |
|---|
source | string | Yes | — |
property | string | No | The header name or the JSON path ($.a.b[0]). |
op | string | Yes | — |
value | string | No | — |
| Field | Type | Required | Description |
|---|
name | string | No | — |
method | string | No | — |
host | string | No | One of the project's active addresses; default the check URL's host. |
path | string | Yes | Starts with /. May use {{name}} values extracted by earlier steps. |
headers | object | No | Authorization and Cookie are allowed in steps; Host, hop-by-hop and Runlot-* are not. |
secretHeaders | string[] | No | Headers whose values are sealed and read back empty; an empty value on replace keeps the stored one. |
body | string | No | — |
expectStatusMin | integer | No | — |
expectStatusMax | integer | No | — |
assertions | UptimeAssertion[] | No | — |
extract | object | No | — |
| Field | Type | Required | Description |
|---|
from | string | Yes | — |
to | string | Yes | — |
step | integer | No | Bucket width in seconds. |
resolution | string | Yes | — |
clamped | boolean | No | from was moved to the plan's retention. |
env | string | No | production, or preview:<branch>. |
| Field | Type | Required | Description |
|---|
requests | integer | No | — |
errors | integer | No | — |
errorRate | number | No | — |
status | object | No | — |
meanMs | number | No | — |
p50 | number | No | — |
p75 | number | No | — |
p90 | number | No | — |
p95 | number | No | — |
p99 | number | No | — |
p999 | number | No | — |
Type: ObsWindow & object
| Field | Type | Required | Description |
|---|
t | string | No | — |
invocations | integer | Yes | — |
meanMs | number | No | — |
p50 | number | No | — |
p95 | number | No | — |
p99 | number | No | — |
Type: ObsWindow & object
Type: ObsWindow & object
Type: ObsWindow & object
| Field | Type | Required | Description |
|---|
names | object[] | No | — |
usage | object | No | — |
| Field | Type | Required | Description |
|---|
template | string | No | — |
source | string | No | — |
learnedBy | string | No | — |
pinned | boolean | No | — |
rejected | boolean | No | — |
firstSeen | string | No | — |
lastSeen | string | No | — |
| Field | Type | Required | Description |
|---|
template | string | Yes | Segments: literal, :name, :name?, :name* or *. |
state | string | Yes | — |
| Field | Type | Required | Description |
|---|
deployment | object | No | — |
learned | ObsLearnedRoute[] | No | — |
Type: ObsWindow & object
| Field | Type | Required | Description |
|---|
route | string | No | — |
requests | integer | No | — |
wallMs | number | No | — |
spanMs | number | No | — |
basis | string | No | — |
overlapping | boolean | No | — |
parts | object[] | No | — |
Type: ObsWindow & object
Type: ObsWindow & object
| Field | Type | Required | Description |
|---|
env | string | No | — |
from | string | No | — |
to | string | No | — |
next | string | No | — |
traces | object[] | No | — |
| Field | Type | Required | Description |
|---|
traceId | string | No | — |
tier | string | No | — |
invocation | object | No | — |
spans | object[] | No | — |
logs | object[] | No | — |
Every criterion given must match.
| Field | Type | Required | Description |
|---|
route | string | No | — |
handler | string | No | — |
status | string | No | error, a class (5xx) or a code (502). |
minDurationMs | number | No | — |
attrs | object | No | — |
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
filter | ObsTraceFilterSpec | Yes | — |
enabled | boolean | No | — |
| Field | Type | Required | Description |
|---|
filterId | string | No | — |
name | string | No | — |
filter | ObsTraceFilterSpec | No | — |
enabled | boolean | No | — |
createdAt | string | No | — |
updatedAt | string | No | — |
| Field | Type | Required | Description |
|---|
filters | ObsTraceFilter[] | No | — |
available | boolean | No | — |
longRetentionDays | integer | No | — |
limit | integer | No | — |
| Field | Type | Required | Description |
|---|
from | string | No | — |
to | string | No | — |
clamped | boolean | No | — |
retentionHours | integer | No | — |
queries | object[] | No | — |
droppedCalls | integer | No | — |
waits | object | No | — |
plans | object | No | — |
| Field | Type | Required | Description |
|---|
fingerprint | string | No | — |
sample | string | No | — |
series | object[] | No | — |
plans | object | No | — |
| Field | Type | Required | Description |
|---|
available | boolean | No | — |
reason | string | No | — |
sizeBytes | integer | No | — |
growth | object | No | — |
tables | object[] | No | — |
indexes | object[] | No | — |
deferredHnswTombstones | object[] | No | — |
connections | integer | No | — |
errors | object | No | — |
| Field | Type | Required | Description |
|---|
logsEnabled | boolean | No | — |
logSampleRate | number | No | — |
tracesEnabled | boolean | No | — |
traceSampleRate | number | No | — |
| Field | Type | Required | Description |
|---|
plan | string | Yes | — |
allowed | boolean | Yes | Whether the plan has the profiler (Pro). |
default | boolean | Yes | What a project that has not chosen gets. |
setting | boolean | Yes | The stored choice; null is the default. |
enabled | boolean | Yes | What the next generation launches with. |
| Field | Type | Required | Description |
|---|
enabled | boolean | Yes | true, false, or null for the default. |
| Field | Type | Required | Description |
|---|
profileId | string | Yes | — |
ts | string | Yes | When the window started. |
deploymentVersion | integer | Yes | — |
route | string | No | — |
durationMs | integer | Yes | — |
samples | integer | Yes | CPU samples (idle excluded). |
attributedSamples | integer | No | Samples attributed to a route: taken while every request in flight had that one route. The rest are counted in the window but under no route. |
intervalUs | integer | Yes | — |
symbolicated | boolean | Yes | Whether any frame was mapped through a source map. |
| Field | Type | Required | Description |
|---|
views | integer | Yes | — |
sessions | integer | Yes | New browser sessions (page loads) among these views. |
lcpP75 | number | No | ms; null without a sample. |
inpP75 | number | No | — |
clsP75 | number | No | Unitless. |
ttfbP75 | number | No | — |
lcpSamples | integer | No | — |
inpSamples | integer | No | — |
clsSamples | integer | No | — |
ttfbSamples | integer | No | — |
longTasks | integer | No | — |
longTaskMsPerView | number | No | — |
resources | integer | No | — |
resourceMsAvg | number | No | — |
fetches | integer | No | — |
fetchMsAvg | number | No | — |
durationMsAvg | number | No | — |
| Field | Type | Required | Description |
|---|
from | string | Yes | — |
to | string | Yes | — |
step | integer | Yes | — |
resolution | string | Yes | — |
clamped | boolean | Yes | — |
env | string | No | — |
note | string | No | — |
Type: ObsRUMWindow & object
| Field | Type | Required | Description |
|---|
kind | string | Yes | — |
party | string | Yes | — |
count | integer | Yes | — |
msAvg | number | No | — |
buckets | integer[] | Yes | Counts at or under 100, 300, 1000, 3000 ms, and above. |
Type: ObsRUMWindow & object
Type: ObsRUMWindow & object
| Field | Type | Required | Description |
|---|
viewId | string | Yes | — |
ts | string | Yes | — |
sessionId | string | Yes | — |
requestId | string | Yes | — |
traceId | string | No | — |
serverRequestId | string | No | Document views only: the request that rendered the page. |
release | integer | Yes | — |
template | string | Yes | — |
device | string | Yes | — |
nav | string | Yes | — |
soft | boolean | Yes | An SPA route change. |
seq | integer | Yes | — |
durationMs | number | Yes | — |
lcpMs | number | No | — |
inpMs | number | No | — |
cls | number | No | — |
ttfbMs | number | No | — |
longTasks | integer | Yes | — |
longTaskMs | number | Yes | — |
resources | integer | Yes | — |
resourceMs | number | No | — |
thirdPartyResources | integer | No | — |
fetches | integer | Yes | — |
fetchMs | number | No | — |
Type: ObsRUMWindow & object
| Field | Type | Required | Description |
|---|
requestId | string | Yes | — |
ts | string | Yes | — |
method | string | No | — |
route | string | No | — |
status | integer | No | — |
wallMs | number | No | — |
link | string | Yes | — |
Type: ObsRUMViewSummary & object
| Field | Type | Required | Description |
|---|
from | string | Yes | — |
to | string | Yes | — |
profiles | ObsProfileSummary[] | Yes | — |
| Field | Type | Required | Description |
|---|
name | string | Yes | — |
self | integer | Yes | Samples whose leaf is this frame here. |
total | integer | Yes | Every sample under this node. |
children | ObsFlameNode[] | No | — |
| Field | Type | Required | Description |
|---|
from | string | Yes | — |
to | string | Yes | — |
version | integer | No | — |
route | string | No | — |
samples | integer | Yes | — |
truncated | boolean | Yes | — |
root | ObsFlameNode | Yes | — |
| Field | Type | Required | Description |
|---|
function | string | Yes | — |
self | integer | Yes | — |
total | integer | Yes | — |
selfShare | number | Yes | — |
| Field | Type | Required | Description |
|---|
from | string | Yes | — |
to | string | Yes | — |
version | integer | No | — |
samples | integer | Yes | — |
functions | ObsProfileFunction[] | Yes | — |
| Field | Type | Required | Description |
|---|
function | string | Yes | — |
aSelf | integer | Yes | — |
bSelf | integer | Yes | — |
aShare | number | Yes | — |
bShare | number | Yes | — |
delta | number | Yes | bShare minus aShare. |
| Field | Type | Required | Description |
|---|
from | string | Yes | — |
to | string | Yes | — |
a | integer | Yes | — |
b | integer | Yes | — |
aSamples | integer | Yes | — |
bSamples | integer | Yes | — |
functions | ObsProfileCompareRow[] | Yes | — |
| Field | Type | Required | Description |
|---|
snapshotId | string | Yes | — |
state | string | Yes | — |
deploymentVersion | integer | No | — |
bytes | integer | Yes | — |
requestedBy | string | No | — |
createdAt | string | Yes | — |
finishedAt | string | No | — |
expiresAt | string | Yes | — |
error | string | No | Why it failed, in a sentence a customer can act on. |
| Field | Type | Required | Description |
|---|
snapshots | ObsHeapSnapshot[] | Yes | — |
Type: string
| Field | Type | Required | Description |
|---|
role | string | Yes | — |
grants | ObservabilityPermission[] | Yes | — |
overridden | boolean | Yes | A project override replaces the role's default |
effective | ObservabilityPermission[] | Yes | The grants this credential can use |
| Field | Type | Required | Description |
|---|
userId | string | Yes | — |
email | string | No | — |
name | string | No | — |
role | string | Yes | — |
default | ObservabilityPermission[] | Yes | — |
grants | ObservabilityPermission[] | Yes | — |
overridden | boolean | Yes | — |
| Field | Type | Required | Description |
|---|
auditId | integer | Yes | — |
actor | string | No | The person's email, or the operator's for a Runlot read |
actorKind | string | Yes | — |
action | string | Yes | — |
target | string | No | — |
detail | object | Yes | — |
at | string | Yes | — |
| Field | Type | Required | Description |
|---|
region | string | Yes | Where this control plane keeps the data; empty when unnamed |
store | string | Yes | — |
retention | object | Yes | — |
exports | object[] | Yes | — |
| Field | Type | Required | Description |
|---|
cap | object | Yes | null: the included amount; -1: no cap |
effective | integer | Yes | -1 is unlimited |
included | integer | Yes | — |
used | integer | Yes | — |
period | string | Yes | — |
unitPriceMicroCents | integer | Yes | 0 on Free |
billableMonth | integer | Yes | — |
projectedMonthMicroCents | integer | Yes | The month at the current rate |
ceilingMonthMicroCents | object | Yes | The most this cap allows in a month; null when unlimited |
| Field | Type | Required | Description |
|---|
plan | string | Yes | — |
liftable | boolean | Yes | Whether caps can be raised or removed (Pro) |
spendingLimitCents | integer | Yes | The organization's monthly overage limit, which bounds every meter |
logEventsDaily | ObservabilityCapMeter | Yes | — |
customSeries | ObservabilityCapMeter | Yes | — |
rumSessions | ObservabilityCapMeter | Yes | — |
| Field | Type | Required | Description |
|---|
logEventsDaily | object | No | — |
customSeries | object | No | — |
rumSessions | object | No | — |
| Field | Type | Required | Description |
|---|
target | string | Yes | s3: a bucket you name; storage: the project's env.storage bucket |
endpoint | string | No | https address of an S3-compatible service; empty is AWS |
bucket | string | No | — |
prefix | string | No | — |
region | string | No | — |
accessKeyId | string | No | — |
secretAccessKey | string | No | — |
pathStyle | boolean | No | — |
| Field | Type | Required | Description |
|---|
exportId | string | Yes | — |
projectId | string | Yes | — |
kind | string | Yes | — |
name | string | Yes | — |
signals | string[] | Yes | — |
endpoint | string | No | — |
headerNames | string[] | Yes | Header names only; values are sealed and never returned |
persist | boolean | Yes | — |
enabled | boolean | Yes | — |
bucket | ObservabilityExportBucket | No | — |
state | string | Yes | — |
failures | integer | Yes | — |
lastError | string | No | — |
lastAttemptAt | string | No | — |
lastSuccessAt | string | No | — |
nextAttemptAt | string | Yes | — |
sentRows | integer | Yes | — |
droppedRows | integer | Yes | persist:false rows dropped from a full queue |
createdAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
kind | string | Yes | — |
name | string | No | — |
signals | string[] | Yes | — |
endpoint | string | No | otlp: the collector's base address; /v1/logs, /v1/traces and /v1/metrics are appended |
headers | object | No | — |
persist | boolean | No | otlp only; false exports logs and traces without storing them |
bucket | ObservabilityExportBucket | No | — |
| Field | Type | Required | Description |
|---|
name | string | No | — |
signals | string[] | No | — |
endpoint | string | No | — |
headers | object | No | — |
persist | boolean | No | — |
enabled | boolean | No | — |
bucket | ObservabilityExportBucket | No | — |
| Field | Type | Required | Description |
|---|
jobId | string | Yes | — |
exportId | string | Yes | — |
from | string | Yes | — |
to | string | Yes | — |
state | string | Yes | — |
objects | integer | Yes | — |
rowsLoaded | integer | Yes | — |
bytesRead | integer | Yes | — |
truncated | boolean | Yes | The job stopped at its row bound |
error | string | No | — |
expireAt | string | No | When the loaded rows leave the store again |
createdAt | string | Yes | — |
updatedAt | string | Yes | — |
| Field | Type | Required | Description |
|---|
message | string | No | — |
project | string | No | The project name; required when requestIds are given |
requestIds | string[] | No | — |
since | string | No | A window such as 30m or 2h (at most 24h; default 1h) |
noLogs | boolean | No | Attach invocation skeletons and worker exits only |
lastCommand | object | No | — |
cli | object | No | — |
runlotJson | object | No | runlot.json without secret values |
| Field | Type | Required | Description |
|---|
reportId | string | Yes | — |
orgId | string | Yes | — |
orgSlug | string | No | — |
projectId | string | No | — |
projectName | string | No | — |
authorUserId | string | No | — |
authorEmail | string | No | — |
message | string | Yes | — |
state | string | Yes | — |
plan | string | Yes | — |
counts | object | Yes | requests, invocations, logs, spans, failing, exits, issues, deployments, lastCommand |
noLogs | boolean | Yes | — |
snapshotBytes | integer | Yes | — |
acknowledgedAt | string | No | — |
createdAt | string | Yes | — |
updatedAt | string | Yes | — |
replies | object[] | No | — |
snapshot | object | No | What Runlot copied when the report was filed |