dropto.run docs
Drop2Run.Api | v1

AcceptInviteRequest

Body of `POST /account/invites/accept`.
token
​string · maxLength: 200 · required

The token from the invitation link.

AcceptInviteResponse

What the accepter joined.
accountId
​string · required

The account they are now a member of.

accountName
​null | string · required

What it calls itself, or null when nobody has named it.

requiresTwoFactor
​boolean · required

Whether the account joined requires two-factor, so the page can say so before the gate does (IMPLEMENTATION-PLAN §5.3.6).

role
​string · required

What they may do there.

AccountLinkResponse

Response of `POST /auth/link`.
email
​string · required

The address the link is about: the account's for a confirmation or a reset, the new one for a change of address.

kind
​string · required

Which kind of link it is — verify, reset or change — so the page says what its button will do.

AccountResponse

The account itself, as its members see it.
accountId
​string · required

Its ULID.

kind
​string · required

Whether it belongs to one person or is shared.

name
​null | string · required

What it calls itself, or null when nobody has named it.

AccountSecurityResponse

Response of `PATCH /account/security`.
requireTwoFactorAt
​null | string · date-time · required

Since when two-factor is required, or null while it is not.

AccountSummary

One account, as the switcher lists it.
accountId
​string · required

What the account header carries to act on it.

kind
​string · required

Personal or Team, which is what the switcher labels the entry with.

name
​null | string · required

What it is called, or null for a personal account nobody has named.

role
​string · required

What the caller may do there. The same string /me reports for the current one.

stopped
​boolean · required

Whether the account has been stopped, directly or through one of its owners.

AccountTokenSummary

Somebody else's token, as an owner of the account may see it.
email
​string · required

Whose it is.

id
​string · required

ULID of the token, which is what an owner revokes it by. A handle, not a credential.

lastUsedAt
​null | string · date-time · required

When a request last authenticated with it, or null if never.

name
​string · required

What they called it, which is what makes a list of them readable.

revoked
​boolean · required

Whether it has been revoked, as a flag rather than a date.

AccountsResponse

Response of `GET /api/accounts`.
​AccountSummary[] · required

Every account the caller may act on, oldest membership first. Never empty for a signed-in person: signing in creates an account for them, and they are its owner.

AddSiteDomainRequest

Body of `POST /sites/{siteId}/domains`.
alreadyServing
​null | boolean · required

Whether a site is already answering on this hostname, which is what decides how many records the customer is asked for.

False, or absent, takes the one-record path: the certificate provider proves ownership from the CNAME and answers the challenge from the edge, at the cost of a few minutes where the hostname has no certificate. True takes the older path — two TXT records first, certificate issued before the CNAME moves, no gap — which is worth its extra steps only to somebody with traffic to lose.

Asked rather than guessed because the answer is not visible from here: a hostname that resolves somewhere today may be a live business or a parked page, and the two want opposite things.

hostname
​null | string · required

The hostname to serve the site on, as the customer typed it. Normalized and validated on the server; what is stored is never this string directly (invariant I4).

AddSiteUpstreamRequest

Request of `POST /sites/{siteId}/upstreams`.
​null | array · required

Headers to attach to every call, values in plain text — sealed on arrival.

methods
​null | array · required

Methods visitors may send; GET only when left out.

origin
​null | string · required

https://host the site's _redirects sends calls to.

AddSiteViewersRequest

Request body of `POST /sites/{siteId}/viewers`.
emails
​string[] · required

The addresses to add, as typed. Each is trimmed and lower-cased before it is stored; repeats collapse.

notify
​null | boolean

Whether to mail each address added, defaulting to yes. Undo sends false: putting back somebody just removed should not mail them twice.

role
​null | string

What every address added may do: View (the default) or Comment, in any case. Comment is refused on a plan without comments. Addresses already listed keep the role they have.

AddSiteViewersResponse

Response of `POST /sites/{siteId}/viewers`.
added
​string[] · required

The addresses newly put on the list, as stored.

alreadyListed
​string[] · required

The addresses sent that were on the list already, left as they were.

total
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many people the list now holds, the owner included.

AnnouncementResponse

Body of `GET /api/announcement`.
​required

ApproveCliDeviceRequest

Request body of `POST /api/auth/cli/device/approve`.
approved
​boolean · required

True to hand the command line a token, false to refuse it.

userCode
​string · minLength: 1 · maxLength: 32 · required

The short code as typed, in any case and with or without the dash.

ApproveCliDeviceResponse

Response of `POST /api/auth/cli/device/approve`.
approved
​boolean · required

What was decided, echoed so a page rendering the result cannot disagree with the server.

clientName
​string · required

What the command line calls itself, so the page can name it in the outcome.

AuthConfigResponse

Response of `GET /auth/config`.
googleClientId
​string · required

OAuth 2.0 client id, safe to embed in client-side code.

passwordMinimumLength
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Fewest characters a password may have, so the page's rule list says the server's number.

turnstileSiteKey
​null | string · required

Key the sign-up form renders its Turnstile widget with, or null when this deployment has none — in which case sign-up with a password is unavailable and the page should offer Google alone.

AuthorizeCliRequest

Request body of `POST /api/auth/cli/authorize`.
challenge
​string · minLength: 43 · maxLength: 43 · required

Unpadded base64url SHA-256 of the verifier the command line kept.

clientName
​string · minLength: 1 · maxLength: 64 · required

What the command line calls itself; becomes the token's name.

callback
​null | string · minLength: 1 · maxLength: 16

A named server-side callback instead of a port — mcp for the remote MCP server. Never a URL.

port
​null | integer | string · int32 · min: 1024 · max: 65535 · pattern: ^-?(?:0|[1-9]\d*)$

The loopback port the command line is listening on. Exactly one of this and Callback.

AuthorizeCliResponse

Response of `POST /api/auth/cli/authorize`.
code
​string · required

The one-time code. Returned exactly once and recoverable nowhere.

expiresAt
​string · date-time · required

When the code stops being exchangeable.

redirectUri
​string · required

Where the consent page should send the browser, code appended as a query.

BatchFile

One file inside a batch.
path
​string · required

Normalized path, which the client uses to find the bytes and to name a failure.

sha256
​string · required

Digest, which is also how the layout line and the object's key are built.

BillingActionResponse

Response of the billing actions that only ask the provider for something.
accepted
​boolean · required

Always true; the provider took the request.

BlockSiteCommenterRequest

Request body of `POST /sites/{siteId}/feedback/blocked`.
commentId
​string · maxLength: 26 · required

A comment the person wrote on the site.

removeComments
​boolean · required

Whether to delete every comment they wrote on the site as well.

BlockSiteCommenterResponse

Who was blocked.
commentsRemoved
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many of their comments were deleted now.

userId
​string · required

The person, as the Blocked list names them.

CancelDeletionRequest

Request body of `POST /auth/deletion/cancel`.
token
​string · maxLength: 128 · required

The token the mailed link carried.

ChallengeResponse

Response of `GET /auth/2fa`.
email
​string · required

Whose sign-in is waiting, so somebody on a shared computer can see it is not theirs.

expiresAt
​string · date-time · required

When the step closes.

ChallengeResult

What finishing the code step answers.
returnTo
​null | string · required

Where the sign-in was going, for a Google sign-in, whose destination the server carried; null for the other ways in, whose page kept its own.

ChangePasswordRequest

Request body of `POST /me/password`.
currentPassword
​string · maxLength: 512 · required

The password the account uses now.

newPassword
​string · maxLength: 512 · required

The password to replace it with.

ChangePlanRequestBody

Request body of `POST /api/billing/plan`.
interval
​string · maxLength: 8 · required

Billing interval, month or year.

planId
​string · maxLength: 32 · required

Id of the plan to move onto.

timing
​null | string · maxLength: 16

now, or absent, which means the same thing: the change is applied immediately and the difference is settled against the unused remainder of the current period. Kept in the contract only so that period_end — which this route offered until the provider was found to have no way of deferring anything — can be refused by name instead of being read as now and charging a customer who was told nothing would be charged.

ChangeRoleRequest

Body of `PATCH /account/members/{userId}`.
role
​string · maxLength: 16 · required

The role to give them: Owner or Member.

ChangeSeatsRequestBody

Request body of `POST /api/billing/seats`.
seats
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many seats to be billed for from now on — the total, not a difference. A delta would make the request depend on what the client last read, so two owners pressing "add a seat" at once would buy two seats each.

ChangeSiteSubdomainRequest

Body of `POST /sites/{siteId}/subdomain`.
subdomain
​null | string · required

The new subdomain, as typed. Normalised the way a new site's is.

ChangeSiteViewerRoleRequest

Request body of `PATCH /sites/{siteId}/viewers`.
role
​null | string · required

The role to give: View or Comment, in any case.

ChangeSiteViewerRoleResponse

Response of `PATCH /sites/{siteId}/viewers`.
email
​string · required

The address, as it is stored.

role
​string · required

The role it now has.

CheckoutRequestBody

Request body of `POST /api/billing/checkout`.
interval
​string · maxLength: 8 · required

Billing interval, month or year.

planId
​string · maxLength: 32 · required

Id of the plan to buy.

CheckoutResponse

Response of `POST /api/billing/checkout`.
checkoutUrl
​string · required

The provider-hosted page to send the buyer to.

ClaimSitesRequest

Request body of `POST /sites/claim`.
​SiteClaim[] · minItems: 1 · maxItems: 50 · required

Every site the caller holds a token for.

ClaimSitesResponse

Response of `POST /sites/claim`.
​ClaimedSite[] · required

Sites now owned by the caller.

​RejectedClaim[] · required

Sites that were not claimed, each with a reason. A batch can be partly successful, so this is not an error case — the caller shows what it got and drops the rest from local storage.

ClaimedSite

A site the caller now owns.
siteId
​string · required

ULID of the site.

subdomain
​string · required

Its subdomain.

url
​string · required

Its public URL.

ClientAddressResponse

Response of the client-address probe.
address
​string · required

The address the API will rate-limit this caller by.

clientIpHeader
​string · required

Header the address was taken from. X-Forwarded-For means the chain was walked and TrustedHops is what decided the answer; any other name means that header was read directly and the hop count did not apply.

trustedHops
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Configured number of proxies in front of the API.

CompleteDeployRequest

Request body of `POST /deploys/{deployId}/complete`.
name
​null | string

A display name for the site, read by the client from the <title> of the index.html being published.

Applied only to a site that has no name yet, and only on the call that takes a deploy live — so a redeploy never renames a site, and a retried completion never renames one either.

Cleaned by SiteNames before it is stored, and dropped silently when nothing usable is left. It is not worth failing a deploy whose files have already been verified over the contents of a title tag, and the owner can type a name on the settings page regardless.

CompleteDeployResponse

Response of `POST /deploys/{deployId}/complete`.
deployId
​string · required

ULID of the deploy that is now live.

docsMode
​boolean · required

Whether the site is read through the documents viewer rather than served as files.

Reported for the same reason as Name: the server decides it, from the files this deploy actually holds (SiteModeDetection), and a client that guessed from what it uploaded would be wrong exactly when it matters — the web app that went live inside the reader because its index.html sat one folder too deep, with nothing on the finished card saying so.

edge
​string · required

live when the edge has the deploy, pending when the deploy is live but the edge write did not land yet — Cloudflare refused it or its API budget is spent. A pending deploy is not a failure: it reaches the edge on its own, usually within the Retry-After the response carries, and calling complete again is safe but not needed.

fileCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Number of verified files.

modeIsManual
​boolean · required

Whether the owner chose the mode by hand, in which case no deploy changes it.

name
​null | string · required

What the site is called now, or null when it has none and its subdomain should be shown instead.

Reported rather than left for the client to infer, because only the server knows the answer: it cleans the name it is sent, and it refuses to overwrite a name the site already had. A client that assumed the title it sent is the name now stored would be wrong on every redeploy.

What the anonymous flow needs. A site is remembered in the browser before its first deploy starts — the claim token is returned once and storing it cannot wait — so the name is not known at that point and arrives here instead.

spaMode
​boolean · required

Whether unmatched paths are answered with the site's index.html.

status
​string · required

Always live on success.

totalBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Total verified size in bytes.

url
​string · required

Public URL the site answers on. Content may take up to a minute to reach every edge.

CreateSiteFolderRequest

Body of `POST /site-folders`.
name
​null | string

What to call the folder. Cleaned the way a site's name is.

parentId
​null | string

Folder to create it inside. Omit it, or send "root", to create it at the top level — see string SiteFolderAccess.RootToken for why a literal token rather than null.

CreateSiteRequest

Request body of `POST /sites`. The whole body is optional.
subdomain
​null | string · required

The caller's own choice of subdomain, checked by SubdomainFormat and ReservedNames and counted against int? Plan.MaxCustomSubdomains. Null or empty falls back to a generated one.

folderId
​null | string

The folder to file the new site in: a folder id of the caller's account, or root. Null or empty means the top level, which is where every site started before this field existed. Naming a folder the account does not hold is site_folder_not_found, and so is naming one at all without an account.

CreateSiteResponse

Response of `POST /sites`.
claimToken
​null | string · required

Plaintext claim token, present only for an anonymous site and returned only here. The server keeps nothing but its hash, so a client that loses it cannot recover ownership.

expiresAt
​null | string · date-time · required

When an unclaimed anonymous site is removed. Null once the site has an owner.

siteId
​string · required

ULID of the new site.

subdomain
​string · required

Allocated subdomain, without the parent domain.

url
​string · required

Public HTTPS URL the site will answer on once a deploy goes live.

CreateTokenRequest

Request body of `POST /api/tokens`.
expiresInDays
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How long it should last, or null for a token that never expires on its own.

name
​string · minLength: 1 · maxLength: 64 · required

What to call the token, so its owner can tell it from their others.

CreateTokenResponse

Response of `POST /api/tokens`.
createdAt
​string · date-time · required

When it was issued.

expiresAt
​null | string · date-time · required

When it stops working on its own, or null.

id
​string · required

ULID of the new token.

name
​string · required

The name it was given.

prefix
​string · required

Its first characters, which is what every later listing shows.

token
​string · required

The plaintext. Returned exactly once and recoverable nowhere.

CurrentAnnouncement

The bar a page shows.
icon
​null | string · required

The mark drawn before it — ProductHunt, Gift, Sparkles or Megaphone — or null for none. A page that does not know a value draws no mark.

id
​string · required

Which bar this is.

linkLabel
​null | string · required

The link's words, or null for no link.

linkUrl
​null | string · required

Where the link goes — an https URL or a path on this site — or null.

message
​string · required

The sentence, plain text.

DeleteMeRequest

Body of `DELETE /me`.
confirmEmail
​null | string · required

The address the person signs in with, typed again as confirmation.

code
​null | string · maxLength: 16

An authenticator code, the other proof an immediate deletion accepts.

currentPassword
​null | string · maxLength: 512

The password, asked for only when Immediately is true.

immediately
​boolean

True to skip the grace period: erased within minutes, with no way back.

Default: false

DeleteMeResponse

Response of `DELETE /me`.
deletionDueAt
​string · date-time · required

When the deletion takes effect. Until then it can be called off.

DeleteSiteFolderResponse

Response of `DELETE /site-folders/{folderId}`.
folderId
​string · required

The folder that was removed.

foldersMoved
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many folders were lifted one level.

movedTo
​null | string · required

Where its contents went: the deleted folder's own parent, or null when they are now at the root.

sitesMoved
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many sites were lifted one level. Reported so the dashboard can say what happened rather than leaving somebody to find their sites somewhere they did not put them.

DeleteSiteResponse

Response of `DELETE /sites/{siteId}`.
siteId
​string · required

ULID of the deleted site.

subdomain
​string · required

Its subdomain, which stays reserved.

DeployDetail

Response of `GET /sites/{siteId}/deploys/{deployId}`.
completedAt
​null | string · date-time · required

When it reached a terminal state, or null while in flight.

createdAt
​string · date-time · required

When it was prepared.

deployId
​string · required

ULID of the deploy.

error
​null | string · required

Why it failed, when it did.

fileCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Files it holds.

isLive
​boolean · required

Whether this is the deploy currently being served.

siteId
​string · required

ULID of its site.

status
​string · required

Lowercase status name.

totalBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Its size.

url
​null | string · required

The site's URL, present only when this deploy is live.

DeployFileContent

Response of `GET /sites/{siteId}/deploys/{deployId}/file`.
path
​string · required

The path, normalized — which is the spelling the manifest holds.

sha256
​string · required

Digest of the content as stored.

Sent so the editor can publish a change without re-reading anything: the new manifest is the old one with this entry's digest replaced, and every other file is reused by prepare.

size
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Size in bytes, as the manifest records it.

text
​null | string · required

The file's text, or null when the bytes are not valid UTF-8.

Null rather than a lossy decode, so the dashboard can say the file cannot be edited here instead of offering an editor whose contents would overwrite the original with replacement characters.

DeployManifestPage

Response of `GET /sites/{siteId}/deploys/{deployId}/manifest`.
deployId
​string · required

ULID of the deploy the files belong to.

fileCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Files in the whole deploy, whatever the filter matched.

​ManifestFile[] · required

This page of matches, ordered by path.

filesKept
​boolean · required

Whether the deploy is inside the retention window with its objects still on storage, the same answer as filesKept on the site's version list. The list is answerable either way — it is read from the row — so this is what separates "these files are here" from "these files were here".

matchingBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Their total size, on the same terms.

matchingFiles
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Files the filter matched, equal to FileCount without one.

nextCursor
​null | string · required

Path to pass back as cursor for the following page, or null when this page was the last.

status
​string · required

Lowercase status name of that deploy.

totalBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Size of the whole deploy, whatever the filter matched.

DeploySummary

One deploy in a site's history.
completedAt
​null | string · date-time · required

When it reached a terminal state, or null while in flight.

createdAt
​string · date-time · required

When it was prepared.

deployId
​string · required

ULID of the deploy.

error
​null | string · required

Why it failed, when it did.

fileCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Files it holds.

filesKept
​boolean · required

Whether this version is inside the retention window with its files still on storage, and therefore whether it can be previewed or rolled back to.

It is a field rather than something a client works out because it cannot be worked out from the rest of the response. site.trim_deploys keeps the plan's retainedDeploys most recently live deploys, a rollback counting as going live, and deletes the objects of the rest, leaving the rows. A version outside that window reads false at once, before the trim has run, because promote refuses it by the same rule. The dashboard used to redraw that rule from a deploy's position in this list, and disagreed with the server in both directions — and a plan whose retention was lowered then raised has versions inside the window whose files went weeks ago.

string DeploySummary.Status does not answer it either: a superseded deploy may be fully stored or entirely gone. Nothing about the row changes when its objects are deleted except this.

previewUrl
​null | string · required

URL serving this deploy on its own hostname, or null when there is no reachable preview of it.

Two reasons for null, and they are unrelated. The site's subdomain may be too long to leave room for a preview hostname (see int PreviewHostFormat.MaxSubdomainLength). Or the site's hostnames may not be answering at all — see bool SiteLifecycle.HostnamesServe(Site site): a preview resolves through the site's own hostname, so a tombstoned site has no reachable preview of any version, however sound the deploy behind it is. A site an administrator restores is exactly that, and reporting a URL for it was how the dashboard came to offer a history of versions none of which opened.

It works for any deploy whose files are still on storage, including one that was never published, and stops working once retention removes them — the same condition promote reports as a 410. Nobody is asked to log in: the URL is unlisted rather than access-controlled, and what protects it is the 80 bits of randomness in a ULID. A password-protected site's previews are behind that password like the rest of it.

status
​string · required

Lowercase status name.

totalBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Its size.

DisableTwoFactorRequest

Body of `DELETE /me/2fa`. One of the two is enough.
code
​null | string · required

Six digits from the app.

password
​null | string · required

The account's password.

EnableTwoFactorRequest

Body of `POST /me/2fa/enable`.
code
​null | string · required

Six digits from the app; spaces are ignored.

EnforcingAccount

An account that requires two-factor of its members.
accountId
​string · required

Its ULID.

accountName
​string · required

What it is called.

EnvVarView

One variable as the dashboard sees it.
createdAt
​string · date-time · required

When it was first set.

last4
​string · required

The value's last four characters, or empty for a short value.

name
​string · required

The name.

updatedAt
​string · date-time · required

When its value last changed.

ExchangeCliCodeRequest

Request body of `POST /api/auth/cli/token`.
code
​string · required

The one-time code the browser handed to the loopback listener.

verifier
​string · minLength: 43 · maxLength: 128 · required

The verifier the command line generated and never sent through the browser.

ExchangeCliCodeResponse

Response of `POST /api/auth/cli/token`.
createdAt
​string · date-time · required

When it was issued.

email
​null | string · required

That account's address, so the command line can say who it signed in as.

name
​string · required

The name it was given, which is what the command line called itself.

prefix
​string · required

Its first characters, which is what every later listing shows.

token
​string · required

The plaintext access token. Returned exactly once and recoverable nowhere.

tokenId
​string · required

ULID of the token, so it can be matched to a row on the tokens page.

userId
​string · required

The account it speaks for.

ExportAccount

An account the person is in.
id
​string · required

The account's id.

​ExportInvoice[] · required

Its invoices, when they own it.

joinedAt
​string · date-time · required

When they joined it.

kind
​string · required

Personal or team.

name
​null | string · required

The team's name.

planId
​string · required

The plan the account is on.

role
​string · required

Their role there.

​ExportSubscription[] · required

Its subscriptions, when they own it.

ExportDeploy

A version of a site.
completedAt
​null | string · date-time · required

When it finished.

createdAt
​string · date-time · required

When publishing started.

fileCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many files.

id
​string · required

The version's id.

status
​string · required

Where it stands.

totalBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many bytes.

ExportDomain

A custom domain.
createdAt
​string · date-time · required

When it was added.

hostname
​string · required

The hostname.

status
​string · required

Where it stands.

ExportFormSubmission

One form submission.
fields
​JsonElement · required

What the visitor typed, as sent.

formName
​string · required

The form's name.

receivedAt
​string · date-time · required

When it arrived.

siteId
​string · required

The site it was sent to.

ExportInvoice

An invoice.
amountCents
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

What was charged, in cents.

amountRefundedCents
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

What was refunded, in cents.

currency
​string · required

The currency.

issuedAt
​string · date-time · required

When it was issued.

providerInvoiceId
​string · required

The payment provider's reference.

status
​string · required

Where it stands.

ExportOnboarding

The first-visit answers.
completedAt
​null | string · date-time · required

When they answered.

marketingOptInAt
​null | string · date-time · required

When they agreed to product mail, if they did.

marketingOptOutAt
​null | string · date-time · required

When they last unsubscribed from it, if they did.

role
​null | string · required

What they said they do.

source
​null | string · required

Where they said they heard of it.

sourceDetail
​null | string · required

What they typed about that.

useCase
​null | string · required

What they said they would use it for.

ExportPerson

The person, without any credential.
createdAt
​string · date-time · required

When they signed up.

email
​string · required

The address they sign in with.

emailVerifiedAt
​null | string · date-time · required

When the address was confirmed.

googleLinked
​boolean · required

Whether Google is a way in.

hasPassword
​boolean · required

Whether a password is a way in.

id
​string · required

Their id.

lastSeenAt
​string · date-time · required

When they last used the dashboard.

name
​null | string · required

Their name, if they gave one.

​required

ExportSite

A site of an account the person owns.
accountId
​string · required

The account it belongs to.

createdAt
​string · date-time · required

When it was made.

​ExportDeploy[] · required

Its versions, without their files.

​ExportDomain[] · required

Its custom domains.

id
​string · required

The site's id.

name
​null | string · required

The name its owner gave it.

status
​string · required

Where it stands.

subdomain
​string · required

Its address under the content domain.

ExportSubscription

A subscription.
canceledAt
​null | string · date-time · required

When it was cancelled, if it was.

createdAt
​string · date-time · required

When it started.

currentPeriodEnd
​null | string · date-time · required

When the paid period ends.

planId
​string · required

What it pays for.

seats
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many seats.

status
​string · required

Where it stands.

FindCliDeviceRequest

Request body of `POST /api/auth/cli/device/find`.
userCode
​string · minLength: 1 · maxLength: 32 · required

The short code as typed, in any case and with or without the dash.

FindCliDeviceResponse

Response of `POST /api/auth/cli/device/find`.
clientName
​string · required

What the waiting command line calls itself.

expiresAt
​string · date-time · required

When the request stops being approvable.

fromThisAddress
​boolean · required

Whether it asked from the same address as the browser now looking.

requestedAt
​string · date-time · required

When the command line asked.

requestedFromCountry
​null | string · required

The two-letter country of that address, or null when not known.

requestedFromIp
​null | string · required

The address it asked from, or null when that is not known.

ForgotPasswordRequest

Request body of `POST /auth/password/forgot`.
email
​string · maxLength: 320 · required

The address the account signs in with.

FormSubmissionPage

Response of `GET /api/sites/{siteId}/forms/{formName}/submissions`.
page
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Zero-based index of the page returned.

pageSize
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many rows a page holds, after the cap was applied.

​FormSubmissionRow[] · required

The page, newest first.

total
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many this form has in total, so the reader knows there is more.

FormSubmissionRow

One submission, as the table shows it.
deployId
​string · required

Which deploy was live at the time, which is what explains a column being empty: the field did not exist in the HTML that was serving then.

fields
​string · required

What the visitor typed, as the JSON object it was stored as.

id
​string · required

ULID minted at the edge when the submission arrived.

meta
​string · required

Page, host, country, truncation and the Turnstile verdict, as stored.

receivedAt
​string · date-time · required

When the edge accepted it, not when the row was written.

spamSource
​null | string · required

Who called it spam — system, user, or nobody.

FormerSubdomain

One name a site used to answer on.
retiredAt
​string · date-time · required

When the site stopped answering on it.

subdomain
​string · required

The former subdomain, which redirects to the current one.

FunctionsUsageResponse

How much of its function allowance an account is using.
callsThisMonth
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Function calls this calendar month across every site, up to about an hour and a half behind. Resets with filesResetAt.

maxCallsPerMonth
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Calls the account's sites may make together each calendar month, seats included.

maxSites
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Sites that may run functions at once. A deploy that would add one past it is refused.

sites
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Sites whose live version has functions, which is what maxSites bounds.

suspended
​boolean · required

Whether this month's calls are spent and every function of the account answers 429.

GoogleOneTapRequest

Request body of `POST /auth/google/one-tap`.
credential
​string · required

The ID token (JWT) Google's Identity Services callback handed the browser.

GrantResponse

One piece of extra quota this account holds on top of its tier.
accountBytes
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra storage it adds, in bytes, or null when it adds none.

allowsFeedback
​boolean · required

Whether it switches on comments, for the same reason.

allowsInvitedViewers
​boolean · required

Whether it switches on private sharing by email, so the page can say where that came from on a tier that does not include it.

allowsPasswordProtection
​boolean · required

Whether it switches on password protection, for the same reason.

expiresAt
​null | string · date-time · required

When it runs out, or null when it does not.

maxCustomDomains
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra custom domains it adds.

maxSites
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra sites it adds, or null when it adds none.

name
​string · required

What to call it. The campaign's name where it came from one, and a generic label otherwise — never the administrator's own note, which is written for the console.

suppressesBadge
​boolean · required

Whether it takes the Drop2Run badge off this account's sites.

writeOpsPerMonth
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra publishing operations a month, or null.

HealthResponse

Health check response.
database
​string · required

Postgres connectivity: up or down.

status
​string · required

Overall status: ok or degraded.

InspectAccountLinkRequest

Request body of `POST /auth/link`.
purpose
​string · required

verify for a confirmation link, reset for a password reset link, change for a change-of-address link.

token
​string · maxLength: 128 · required

The token the mailed link carried.

InviteMemberRequest

Body of `POST /account/invites`.
email
​string · maxLength: 320 · required

Address to invite. Compared against the accepter's own before they are let in.

role
​null | string · maxLength: 16

What accepting grants: Owner or Member. Absent means member.

Absent rather than required, and defaulting to the lesser of the two, because an omitted field must not hand out authority nobody asked for — the same rule every capability column on a plan follows.

InviteResponse

An invitation, as its sender sees it once.
acceptUrl
​string · required

The link. Returned here and nowhere else — only its hash is stored, so this response is the one chance to copy it, which is what lets an owner pass it on when mail does not arrive.

email
​string · required

The address it was sent to.

expiresAt
​string · date-time · required

When it stops working.

id
​string · required

Its id, for revoking.

InviteRow

One invitation nobody has accepted yet.
email
​string · required

The address it was sent to. The link only works for this one.

expiresAt
​string · date-time · required

When it stops working on its own.

id
​string · required

Its id, which is what withdrawing it names.

role
​string · required

What accepting it would grant.

InvoiceRow

One invoice, as the invoices page renders it.
amountCents
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Amount in the smallest unit of Currency.

amountRefundedCents
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How much of it has been given back. Shown beside the charge rather than instead of it, so a partial reversal reads as what it is — a status alone cannot say how much of the money came back.

currency
​string · required

ISO 4217 code.

hostedUrl
​null | string · required

Link to the provider's own copy, or null.

id
​string · required

Our own id for the invoice.

issuedAt
​string · date-time · required

When the provider issued it.

periodEnd
​null | string · date-time · required

End of the period covered, or null.

periodStart
​null | string · date-time · required

Start of the period covered, or null.

status
​string · required

One of the InvoiceStatus names.

InvoicesResponse

Response of `GET /api/billing/invoices`.
​InvoiceRow[] · required

The account's invoices, newest first.

JsonElement

No data returned

ListSitesResponse

One page of `GET /sites`.
page
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Zero-based index of this page.

pageSize
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many rows a full page holds.

​SiteSummary[] · required

The rows on this page, in the order that was asked for.

total
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many sites match, across every page — which is what the pager is against. Equal to TotalOwned when no search was asked for.

totalOwned
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many sites the caller owns, ignoring any search.

Both numbers, because the listing says both: the page header counts what the account holds and the line above a searched list counts what matched. One number cannot carry that sentence, and a client holding the other from an earlier response has a number that a deletion can make wrong.

ListTokensResponse

Response of `GET /api/tokens`.
​AccountTokenSummary[] · required

What colleagues hold on the same account, and only what an owner is entitled to know about them. Empty for a member, and empty for an owner whose colleagues have none.

A separate list rather than the same rows with fields blanked out, because a row that is sometimes missing its prefix is a row whose type is a lie — and the screen showing it has to branch on something either way.

​TokenSummary[] · required

The caller's own tokens on this account, newest first, including revoked ones.

ManifestEntry

One entry in the client's manifest. Entirely untrusted until validated.
path
​null | string · required

Path relative to the deploy root, as the client sees it.

sha256
​null | string · required

SHA-256 of the content, lowercase hex.

size
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Exact length of the content in bytes — the length that will be uploaded. 0 only for an empty file, whose checksum is the SHA-256 of zero bytes.

ManifestFile

One file in a deploy's verified manifest.
path
​string · required

Its path within the site, already normalized and always /-separated.

sha256
​string · required

SHA-256 of the content, lowercase hex — what the upload was verified against.

size
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Its size in bytes.

MeExport

Response of `GET /me/export`: everything held about one person.
​ExportAccount[] · required

Every account they are in, with billing for the ones they own.

exportedAt
​string · date-time · required

When the file was made.

​ExportFormSubmission[] · required

What visitors sent through those sites' forms, as kept (ninety days).

​ExportPerson · required

The person.

​ExportSite[] · required

The sites of the accounts they own.

MeResponse

Response of `GET /me`.
accountId
​null | string · required

The account this session is acting on.

accountName
​null | string · required

What the account is called, or null for a personal one nobody has named.

Sent because every screen under /account is now about an account rather than about the person reading it, and a page headed with somebody's own name while describing a shared tier is the exact confusion the team screens were redesigned to remove.

email
​string · required

Email from Google.

​GrantResponse[] · required

Extra quota this account holds outside its tier, one entry each, oldest first.

The figures in Plan already include these — every one of them is the effective number the server enforces — so this is not a second set of limits to add up. It is what lets a page say why a figure is larger than the tier it names, which is the difference between a benefit and an apparent bug in the dashboard. Empty for almost every account.

name
​null | string · required

Display name from Google, if any.

onboarding
​string · required

pending while this person has neither answered nor skipped the first-visit questions, and done once they have.

On the person rather than the account, like the name and the address beside it: somebody in two accounts is asked once. Everybody who had an account before the questions existed reads as done, because the migration that added the table gave them a skipped row (A14).

overLimitUntil
​null | string · date-time · required

When the account's grace for being over its plan runs out, or null while it fits.

Non-null means something will be cut on that date — the oldest sites are put to sleep and the oldest custom domains are removed, only as far as it takes to fit. It is served so the dashboard can say so beforehand: nobody should learn about this from a site going quiet.

​PlanResponse · required

The quota tier currently applied to this user.

recoveryCodesLeft
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many unused two-factor recovery codes this person has, or null while two-factor is off. On the session rather than only on the profile because the reminder it drives — three or fewer — is shown on the site list, which does not read the profile.

role
​string · required

What the signed-in person may do on that account: Owner or Member.

Served so the dashboard can leave out controls the caller cannot use — a delete button, the billing pages — rather than showing them and reporting a refusal afterwards. It is not the permission: every one of those actions is refused at the handler regardless of what the page drew, and a client that ignored this field would gain nothing but a worse error message.

seats
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many seats the account is paying for, which is what its raised ceilings were computed from.

One on every tier not sold by the seat, where it is a constant rather than a measurement. It is not the number of members: seats are bought and members are people, and the two moving independently is the whole reason inviting somebody does not silently change an invoice.

​UsageResponse · required

How much of the plan is currently used.

userId
​string · required

ULID of the signed-in user.

MemberRow

One person on the account.
email
​string · required

Their address, which is how a colleague recognises them.

founder
​boolean · required

Whether they created the account. A founder cannot be removed or demoted while the plan is held in their name, so the members screen offers neither for this row.

joinedAt
​string · date-time · required

When they were added.

name
​null | string · required

Their display name, or null when Google gave none.

role
​string · required

What they may do here.

twoFactor
​boolean · required

Whether they have two-factor on — the column an owner reads before requiring it, and a member reads to see whether the rule would block them.

userId
​string · required

Their ULID, which is what removing them names.

MembersResponse

Who is on the account, and who has been asked.
​InviteRow[] · required

Invitations still standing. Spent and withdrawn ones are history, not a list.

​MemberRow[] · required

People who may act on it, oldest first.

requireTwoFactorAt
​null | string · date-time · required

Since when the owner has required two-factor of every member, or null while they have not.

tokensOfUnprotectedMembers
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Access tokens on this account held by members without two-factor. Requiring two-factor does not stop them, so the owner is told before turning it on.

MoveSiteFolderItemsRequest

Body of `POST /site-folders/move`.
folderIds
​null | array

Folders to move under it. May be empty when only sites move.

siteIds
​null | array

Sites to file there. May be empty when only folders move.

targetId
​null | string

Where everything goes: a folder id, or "root" for the top level. Required — see string SiteFolderAccess.RootToken for why the root is a token rather than an absent value.

MoveSiteFolderItemsResponse

Response of `POST /site-folders/move`.
foldersMoved
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Folders that changed parent, counted the same way.

sitesMoved
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Sites that changed folder. Fewer than were sent when some were already there, which is not an error.

targetId
​null | string · required

The folder everything is now in, or null for the top level.

OfferedPromotion

One campaign this account may claim.
allowsFeedback
​boolean · required

Whether claiming it switches on comments.

allowsInvitedViewers
​boolean · required

Whether claiming it switches on private sharing by email.

allowsPasswordProtection
​boolean · required

Whether claiming it switches on password protection.

code
​null | string · required

Its code, or null when there is none to type.

deltaAccountBytes
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra storage it gives, or null when it gives none.

deltaMaxCustomDomains
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra custom domains it gives.

deltaMaxSites
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra sites it gives, or null when it gives none.

deltaSitesPerDay
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra sites a day the account may create, or null. Only ever set on a campaign aimed at named accounts, so only an account the operator chose ever reads a figure here.

deltaWriteOpsPerDay
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra publishing operations a day, or null.

deltaWriteOpsPerMonth
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Extra publishing operations a month, or null.

endsAt
​null | string · date-time · required

When claiming closes, or null when it does not.

grantExpiresAfterDays
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How long what it gives lasts, or null for good.

id
​string · required

The campaign, which is what a button with no code to type sends back.

name
​string · required

What to call it on the banner.

placesLeft
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many accounts may still claim it, or null when any number may. Read a moment ago and acted on a moment later, so it is a number to show rather than a number to trust — the redeem endpoint is what decides, and it decides in one statement.

suppressesBadge
​boolean · required

Whether claiming it takes the Drop2Run badge off.

OfferedPromotionsResponse

Response of `GET /promotions`.
​OfferedPromotion[] · required

What this account can claim, the ones closing soonest first and the open-ended ones last.

PasswordSignInRequest

Request body of `POST /auth/login`.
email
​string · maxLength: 320 · required

The address the account was created with.

password
​string · maxLength: 512 · required

The password.

turnstileToken
​null | string · maxLength: 4096 · required

A bot check token, needed only after turnstile_required.

PendingCheckoutRow

A checkout still being confirmed, as the billing page renders it.
createdAt
​string · date-time · required

When the checkout began.

interval
​string · required

The billing interval chosen.

planId
​string · required

The plan the checkout is for.

status
​string · required

open or completed.

PendingEmailResponse

An address change that has been asked for and not yet confirmed.
email
​string · required

The address being moved to.

expiresAt
​string · date-time · required

When the link stops working.

requestedAt
​string · date-time · required

When it was asked for, so the page can say how long ago the link went out.

PlanChangeRow

One movement between tiers, as a page renders it.
fromInterval
​null | string · required

The billing term before, or null when there was none.

fromPlanId
​string · required

The tier before.

fromSeats
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Seats paid for before; one on every tier not sold by the seat.

occurredAt
​string · date-time · required

When it happened.

reason
​string · required

Why it moved: one of PlanChangeReason.

toInterval
​null | string · required

The billing term after, or null when there is none.

toPlanId
​string · required

The tier after.

toSeats
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Seats paid for afterwards.

PlanHistoryResponse

Response of `GET /api/billing/plan-history`.
​PlanChangeRow[] · required

The account's tier changes, newest first.

PlanResponse

One quota tier. Field for field the `plans` row, so no mapping table is needed anywhere.
allowAnalyticsExport
​boolean · required

Whether the dashboard offers to save this tier's traffic figures as files.

Another statement about what the tier is sold with rather than a lock: the files are assembled in the browser from the traffic response the page already holds, so a reader who can see the page can read the same numbers off it — see bool Plan.AllowAnalyticsExport.

allowBrowserEdit
​boolean · required

Whether the dashboard lets an owner edit a file of their site in the browser.

A gate rather than packaging, like the flag above: the endpoint the editor reads a file through is refused outright for a tier without it.

allowFeedback
​boolean · required

Whether a site on this tier can take comments on its pages (docs/IMPLEMENTATION-PLAN.md §16.7).

Served so the pricing page and the marketing pages say which tiers include comments from the table, never from a sentence: the tiers that carry it are set in the admin console and change without a release.

allowInvitedViewers
​boolean · required

Whether a site on this tier may be shared with named people, each signing in with their own account. A capability beside AllowPasswordProtection — the two are the paid answers to "who can see this site" — and served for the same reason: the pricing page lists it beside the password.

allowPasswordProtection
​boolean · required

Whether a site on this tier may be put behind a password. The first capability on this record rather than a quantity, so it reads as a boolean instead of a limit of zero: the tier either offers the feature or does not, and "0 passwords" would describe a countable resource nobody has any of.

Served here for the same reason every number above is — the pricing page and the site settings form both have to know, and a client that hardcoded which tiers had it would be wrong the first time an operator flipped the column.

allowQrCode
​boolean · required

Whether the dashboard offers a QR code for the addresses of sites on this tier.

Served rather than decided in the browser for the same reason the flag above is, and for one more: this is the only thing that decides the feature at all. The code is drawn from an address that is already public, so the tier's answer is a statement about what the tier is sold with, not a lock — see bool Plan.AllowQrCode.

allowScheduledExpiry
​boolean · required

Whether an owner on this tier may schedule when one of their sites comes down.

Unlike the two flags above, this one is a real gate rather than a statement about packaging: the server refuses to set a date for a tier without it. Served all the same, so the pricing page can list it and the dashboard can explain the absence rather than failing on submit.

allowTrafficBreakdown
​boolean · required

Whether this tier's traffic page lists top pages, referrers, countries and broken links, and filters by them. Served so the pricing page and the locked panels can name the tier that includes them.

allowTrafficDetail
​boolean · required

Whether this tier's traffic page splits people from bots and AI, and shows devices, browsers, campaigns and edge speed.

analyticsDays
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many days of a site's own traffic this tier lets its owner see, or zero when it includes none.

A count where bool PlanResponse.AllowPasswordProtection is a flag, because there is something to meter here: the difference between tiers is how far back the history reaches, and a boolean would need a second field to say that. Zero reads as "not on this tier" rather than as a quantity nobody has, which is why the pricing page renders it as words rather than as the number.

badgeText
​null | string · required

Short label shown against the tier, or null for none. See string? Plan.BadgeText.

currency
​string · required

ISO 4217 code the two price fields are counted in.

displayOrder
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Where the tier sits on the pricing page, lowest first.

id
​string · required

Plan id, as stored.

isExclusive
​boolean · required

Whether this tier is not on the pricing page, and reaches the caller only because it was agreed with them.

Always false on the anonymous route, which returns the listed tiers and therefore has nothing to say here. It exists so the dashboard can label the card: a reader meeting a price nobody else is offered, beside prices everybody is, would otherwise have no way to tell which is which — and would reasonably wonder why they cannot find it on the pricing page.

Not the same question as bool PlanResponse.IsPurchasable. A tier can be agreed before its prices are set, which is exclusive and not yet buyable, and the card has to say both.

isPurchasable
​boolean · required

Whether the tier can be bought right now. Separate from being listed: a tier that is listed and not purchasable shows its price and its limits with no button, which is how a tier is announced before there is a checkout behind it. See bool Plan.IsPurchasable.

isTeam
​boolean · required

Whether the two prices are the cost of one seat rather than of one period.

Served publicly because the pricing page cannot render the tier without it: fifteen dollars a seat and fifteen dollars a period are the same number in the same field and three times apart in what a customer pays. A page that showed the column would put this tier beside the one above it at an identical price.

lifetimeDays
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Days before the site is deleted, or null when it is kept for good.

maxAccountBytes
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum bytes the account may hold across every site and every kept version, or null when the tier has no total. Null on the anonymous tier, which has no owner to total by. See long? Plan.MaxAccountBytes.

maxAccountWriteOpsPerMonth
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

New or changed files the account may publish in a calendar month, or null when the tier is not bounded by month. The one limit on this page that is a cost rather than a capacity: republishing a file that has not changed spends nothing against it.

maxCustomDomains
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum hostnames of the customer's own that one account may be served on, counted across every site it owns. Zero means the tier does not include the feature, which is what both free tiers are seeded with — so the pricing page reads this as a capability rather than as a quantity. Never null, unlike the quotas above it: there is no unlimited version of a resource billed monthly per unit. Distinct from int? PlanResponse.MaxCustomSubdomains, which counts names on our own content domain. See int Plan.MaxCustomDomains.

maxCustomSubdomains
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum sites one owner may have picked their own subdomain for, or null when the tier does not limit that at all. See int? Plan.MaxCustomSubdomains.

maxFileBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum size of a single file, in bytes.

maxFiles
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum files in one deploy.

maxFormSubmissionsPerMonth
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum form submissions one account may take in a calendar month, across every site it owns. Zero means the tier does not include the feature, and every tier is seeded zero — the figure worth selling is not known yet, so it ships off and an operator raises it per row once the counter has something to read. The pricing page therefore renders this as a capability until somebody sets a number. See int Plan.MaxFormSubmissionsPerMonth.

maxProxyRequestsPerMonth
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Requests one account's sites may proxy to their owners' upstreams in a calendar month. Zero means the tier does not include the proxy. See int Plan.MaxProxyRequestsPerMonth.

maxSeats
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Most seats it can be held with, or null for no ceiling.

maxSiteBytes
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum total size of one deploy of one site, in bytes, or null when the tier does not bound a single publish and lets the account total do it instead. Not a storage limit either way: it is weighed against a single publish, and every kept version is stored whole. MaxAccountBytes is the storage one.

maxSiteComments
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The most comments one site on this tier may hold, deleted ones not counted. Only meaningful where AllowFeedback is on; served on every tier like the other ceilings.

maxSiteViewers
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many people one invite-only site may list, its owner included. Read only where AllowInvitedViewers is on; a figure on a tier without the feature describes nothing.

maxSites
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum sites one owner may have, or null when the tier has no owner to count by — the anonymous tier, whose sites belong to nobody.

minSeats
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Fewest seats the tier is sold with, which is what turns a seat price into an entry price.

name
​string · required

What the tier is called on screen, falling back to the id when a row has never been named. Served rather than written into the pricing page so that a tier added to the table appears with its own name instead of an id, which is what makes a new tier a database insert rather than a release.

parentPlanId
​null | string · required

The tier this one is built on, or null when it stands alone.

Every quota above is already the effective one — inheritance is materialised on the row, so nothing reading this response has to resolve anything. This field is here for what the pricing page says rather than for what it computes: a tier built on another is listed as everything that one includes plus what it adds, and the rows that repeat the parent's figures are left off the card. Without the link the page would have to guess that relationship from the numbers, and two tiers that happen to share a figure are not the same claim as one built on the other.

Null on the card when the parent is not itself public: there is no listed tier to name, so the card falls back to listing every row.

perSeatAccountBytes
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Storage each seat past the minimum adds, or null when storage does not scale with seats.

The per-seat figures are served for one reason, and it is not decoration. This endpoint is public, so it has no account and therefore no seat count — it can only state the tier's base. The dashboard states the effective figure for the account reading it. Without the delta beside the base, the two pages say different numbers for the same plan and the promise that the pricing page shows what the service enforces stops being true.

perSeatMaxCustomDomains
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Hostnames of the customer's own each seat past the minimum adds. Zero says a seat buys none, which is where every tier starts and what the free tiers stay at.

perSeatMaxFormSubmissionsPerMonth
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Form submissions a month each seat past the minimum adds to the account's allowance. Zero says a seat buys none, which is every tier but Team.

perSeatMaxProxyRequestsPerMonth
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Proxied requests a month each seat past the minimum adds. Zero says a seat buys none.

perSeatMaxSites
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Sites each seat past the minimum adds, or null when they do not scale.

perSeatWriteOpsPerDay
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Daily budget each seat adds, or null when it does not scale.

perSeatWriteOpsPerMonth
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Monthly budget each seat adds, or null when it does not scale.

priceCentsMonth
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Price of one month in the smallest unit of Currency, or null when the tier is not sold by the month. Null rather than zero on the free tiers: they are not priced at zero, they are not on sale.

priceCentsYear
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Price of one year, or null when the tier is not sold by the year.

prioritySupport
​boolean · required

Whether support requests from accounts on this tier are answered ahead of the queue.

Served because the pricing page lists it, and for no other reason: nothing in the API branches on it. It is the one field here that no endpoint enforces, because what it describes is a promise kept by whoever answers the mail — see bool Plan.PrioritySupport.

retainedDeploys
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many recent deploys stay available.

showsBadge
​boolean · required

Whether sites on this tier carry the Drop2Run badge in their served HTML.

The one field on this record that describes something the platform does to a site rather than something the site is allowed to do, which is why it reads as "shows" rather than "allows". The pricing page states it as a row like any other limit, because it is a difference between the tiers a reader has to know before they upload rather than after.

sitesPerIpPerDay
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Maximum new sites one network may create per day, or null when the tier is not counted by address. Abuse protection rather than a product limit, so nothing is expected to display it.

tagline
​null | string · required

One line under the name, or null to show none. See string? Plan.Tagline.

PlansResponse

Response of `GET /plans`.
anonymousPlanId
​string · required

Tier applied to a site created without signing in.

contentDomain
​string · required

Apex domain a site's subdomain sits under, for example dropto.live. Served here rather than hardcoded in the frontend for the same reason every number above is: it is server configuration, and a client that guessed it would show the wrong suffix the moment the domain changed.

​PlanResponse[] · required

Every tier, smallest first.

signedInPlanId
​string · required

Tier applied once the visitor has an account.

PollCliDeviceRequest

Request body of `POST /api/auth/cli/device/token`.
deviceCode
​string · required

The long code the command line was given when it opened the request.

PollCliDeviceResponse

Response of `POST /api/auth/cli/device/token` once the request has been approved.
createdAt
​string · date-time · required

When it was issued.

email
​null | string · required

That account's address, so the command line can say who it signed in as.

name
​string · required

The name it was given, which is what the command line called itself.

prefix
​string · required

Its first characters, which is what every later listing shows.

token
​string · required

The plaintext access token. Returned exactly once and recoverable nowhere.

tokenId
​string · required

ULID of the token, so it can be matched to a row on the tokens page.

userId
​string · required

The account it speaks for — whoever approved the request.

PortalResponse

Response of `GET /api/billing/portal`.
portalUrl
​string · required

Where to send the customer to manage their card and receipts.

PrepareDeployRequest

Request body of `POST /deploys/prepare`.
​ManifestEntry[] · minItems: 1 · required

Every file the client intends to upload.

batches
​boolean

Whether the client can send batch permits — several small files in one request. A client that does not set it receives one permit per file. Setting it is a request, not a guarantee: the server may still answer with single permits only.

Default: false

PrepareDeployResponse

Response of `POST /deploys/prepare`.
​UploadBatch[] · required

Batch permits, each covering several small files sent as one body. Empty unless the request asked for batches and they are enabled; a file is in exactly one of Upload and this.

deployId
​string · required

ULID of the new deploy; part of every R2 key it writes.

reused
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many files the live deploy already holds byte-identical. These are absent from Upload and are copied server-side when the deploy completes.

total
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Files in the whole deploy: Reused plus what must be uploaded.

​UploadTarget[] · required

One upload permit per file sent on its own.

uploadUrl
​string · required

The single endpoint every permit is presented to. Sent with the response rather than compiled into the client, because it is a different host in development, in tests and in production — and because a client that knew the address without being told would still know it after we moved.

batchConcurrency
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$

How many of Batches to send at once; null when there are none. The upload Worker can hold only six R2 writes open per request, so this is what decides how fast many small files go, and it is set here so it can be tuned without a client release. Single permits are not affected.

unchanged
​boolean

True when the manifest describes exactly what is already live, so no deploy was created. The caller has nothing to upload and must not call complete: DeployId is the deploy already serving, and completing it again would only rewrite the mapping to where it already points.

Default: false
url
​null | string

Public URL of the site, sent only when Unchanged is true. That answer is the end of the deploy, and without it the caller would have to ask a second endpoint just to show the link.

warnings
​null | array

Things about this deploy the caller should be told although it was accepted, or null when there are none — today only that _functions/ will not run on this site (docs/briefs/FUNCTIONS-BRIEF.md D23).

PreviewPromotionRequest

Body of `POST /promotions/preview`.
code
​string · maxLength: 64 · required

The code, as typed. Folded to upper case here, so the case somebody used does not matter. Bounded by the same length an operator may give one.

PreviewTicket

Response of `POST /sites/{siteId}/deploys/{deployId}/preview-ticket`.
action
​string · required

The URL to post the ticket to, as the form field ticket, targeting the preview frame.

expiresAt
​string · date-time · required

When the frame's access runs out and a new ticket is needed.

ticket
​string · required

The signed ticket. Accepted for one minute.

ProblemDetails

detail
​null | string
instance
​null | string
status
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$
title
​null | string
type
​null | string

ProfileResponse

Response of `GET /me/profile`.
accountCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many accounts they are a member of. Sent because it is the sentence that tells a reader why this page is separate from the account pages, and one number is cheaper than a list nobody reads here.

createdAt
​string · date-time · required

When they first signed in here.

email
​string · required

The address they are written to and sign in with.

emailVerified
​boolean · required

Whether that address has been proven to reach them.

googleLinked
​boolean · required

Whether Google is one of their ways in.

googleLinkedAt
​null | string · date-time · required

When Google became one, or null when it is not one — or when it became one before this was recorded.

hasPassword
​boolean · required

Whether a password is one of their ways in. False for somebody who has only ever used Google, for whom the page offers to set one rather than to change one.

name
​null | string · required

Their display name, shown to people on their teams, or null when they have none.

passwordChangedAt
​null | string · date-time · required

When the password was last set, or null when there is none.

​required
productEmail
​boolean · required

Whether they get product email now: consent given and not withdrawn since. Mail about their account and sites is not affected either way.

​required
userId
​string · required

The person's ULID, which is the identifier worth quoting in a support mail.

PromoteDeployResponse

Response of `POST /sites/{siteId}/deploys/{deployId}/promote`.
deployId
​string · required

ULID of the deploy that is now live.

edge
​string · required

live when the edge has the deploy, pending when the rollback is committed but the edge write did not land yet; it gets there on its own, as on complete.

fileCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Files in the promoted deploy.

status
​string · required

Always live on success.

totalBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Its total size in bytes.

url
​string · required

Public URL the site answers on. Content may take up to a minute to reach every edge.

ProxyAllowance

An account's proxy allowance for the month.
perMonth
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Requests the plan allows a month; zero on a plan without the proxy.

resetsAt
​string · date-time · required

When the count starts again: the first instant of next month, UTC.

suspended
​boolean · required

Whether the month is spent and every proxy route of the account answers 429.

used
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Requests counted so far this month, every site of the account together. Runs up to about an hour and a half behind.

ProxyLogRow

One proxied request as the owner's log shows it. Never a query string, an IP or a header.
aborted
​boolean · required

Whether the visitor left before the response ended.

at
​string · date-time · required

When it was answered.

bytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Response bytes passed on.

durationMs
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Milliseconds from the proxy receiving it to the response ending.

error
​string · required

The proxy's own error code, or empty when the status came from the upstream.

method
​string · required

Request method.

path
​string · required

Site path, without the query.

status
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Status returned to the visitor.

ProxyRouteView

One proxy route of the live version.
from
​string · required

The site path, ending in /* or holding :name segments.

to
​string · required

The target, https://host/path.

RecoverTwoFactorRequest

Body of `POST /auth/2fa/recovery`.
code
​null | string · required

One recovery code; case, spaces and dashes do not matter.

RecoveryCodesResponse

A new set of recovery codes, shown once.
recoveryCodes
​string[] · required

Ten codes, each XXXX-XXXXXX.

RedeemPromotionRequest

Body of `POST /promotions/redeem`. Exactly one of the two says which campaign.
code
​null | string · required

The code, as typed. Folded to upper case here, so the case somebody used does not matter.

promotionId
​null | string · required

The campaign's id, for an offer that was listed — a button rather than something to type. Refused for a campaign whose audience is Code: there the code is the only way in.

RedeemPromotionResponse

What was claimed.
expiresAt
​null | string · date-time · required

When the grant runs out, or null when it does not.

name
​string · required

Its name, so the page can say what was applied without a second call.

promotionId
​string · required

The campaign claimed.

RejectedClaim

A claim that did not succeed.
reason
​string · required

One of the Errors codes: site_not_found or quota_exceeded.

siteId
​string · required

ULID that was attempted.

RemoveSiteDomainResponse

Response of `DELETE /sites/{siteId}/domains/{domainId}`.
hostname
​string · required

The hostname that stopped serving.

id
​string · required

ULID of the domain that was removed.

RemoveSiteViewerResponse

Response of `DELETE /sites/{siteId}/viewers`.
email
​string · required

The address removed, as it was stored.

total
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many people the list still holds, the owner included.

RemovedResponse

What was taken away.
id
​string · required

The user or invitation that is gone.

RenameAccountRequest

Body of `PATCH /account`.
name
​null | string · maxLength: 255 · required

What to call the account, or null to clear the name.

ReplyToSiteFeedbackRequest

Request body of `POST /sites/{siteId}/feedback/threads/{threadId}/comments`.
body
​null | string · required

The reply, plain text.

resolve
​boolean

Whether to resolve the thread with the reply; false by default.

Default: false

ReportAbuseRequest

Request body of `POST /abuse`.
reason
​string · minLength: 3 · maxLength: 2000 · required

What is wrong with it.

url
​string · minLength: 8 · maxLength: 2048 · required

Full address of the offending page.

reporterEmail
​null | string · minLength: 0 · maxLength: 320

Optional contact address. Deliberately not required: insisting on one costs more reports than it gains in follow-up.

ReportAbuseResponse

Response of `POST /abuse`.
reportId
​string · required

Reference for the report. Given back so a reporter following up has something to quote, and so a retried submission can be recognised as a duplicate by hand.

ReportProblemRequest

Request body of `POST /support/reports`.
message
​string · minLength: 3 · maxLength: 4000 · required

What happened, in the person's words.

​
email
​null | string · minLength: 0 · maxLength: 320

Where to answer. Read only without a session; a signed-in user's own address is used.

turnstileToken
​null | string · maxLength: 4096

The bot check's token. Required without a session, ignored with one.

ReportProblemResponse

Response of `POST /support/reports`.
reportId
​string · required

Reference for the report, for the person to quote if they write again.

ResendDeletionLinkRequest

Request body of `POST /auth/deletion/resend`.
email
​string · maxLength: 320 · required

The address the person signs in with.

ResendSiteViewerInvitationRequest

Request body of `POST /sites/{siteId}/viewers/resend`.
email
​string · required

The address on the list to mail again, in any case.

ResendSiteViewerInvitationResponse

Response of `POST /sites/{siteId}/viewers/resend`.
email
​string · required

The address mailed, as stored.

emailedAt
​string · date-time · required

When the mail was queued; another may be sent a day after this.

ResetPasswordRequest

Request body of `POST /auth/password/reset`.
password
​string · maxLength: 512 · required

The new password.

token
​string · maxLength: 128 · required

The token the mailed link carried.

RevokeTokenResponse

Response of `DELETE /api/tokens/{tokenId}`.
id
​string · required

ULID of the token that no longer works.

revokedAt
​string · date-time · required

When it stopped working, which is unchanged if it already had.

SaveOnboardingRequest

Request body of `PUT /me/onboarding`.
builds
​null | array · maxItems: 16 · required

What their sites are made with. One or several.

completed
​boolean · required

Whether this is the last step's send, so the questions are done.

role
​null | string · maxLength: 32 · required

What they do.

source
​null | string · maxLength: 32 · required

Where they heard about us.

sourceDetail
​null | string · maxLength: 200 · required

What they typed beside a source that offers a box; required for other.

useCase
​null | string · maxLength: 32 · required

What they will publish first.

SetAccountSecurityRequest

Body of `PATCH /account/security`.
requireTwoFactor
​boolean · required

Whether every member must sign in with two-factor.

SetProductEmailRequest

Request body of `PUT /me/product-email`.
subscribed
​boolean · required

True to receive product email, false to stop it.

SetSiteEnvVarRequest

Request of `PUT /sites/{siteId}/env/{name}`.
value
​null | string · required

The value, in plain text — sealed on arrival and never shown back.

SignUpRequest

Request body of `POST /auth/signup`.
email
​string · maxLength: 320 · required

The address to create the account with.

password
​string · maxLength: 512 · required

The password, checked against the rules in PasswordPolicy.

turnstileToken
​null | string · maxLength: 4096 · required

The token the page's Turnstile widget produced.

returnTo
​null | string · maxLength: 4096

Where to send the person once the address is confirmed: a path on the dashboard origin, checked by the same rule the sign-in pages apply. Anything that is not one is dropped, not refused.

SiteClaim

One site the caller is trying to claim.
claimToken
​string · required

The plaintext token issued when the site was created.

siteId
​string · required

ULID of the site.

SiteCommentBlockRow

One person blocked from commenting on a site.
blockedAt
​string · date-time · required

When they were blocked.

commentsRemoved
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many of their comments were deleted with the block.

email
​null | string · required

Their address, or null once the account is gone.

name
​string · required

The name their comments showed.

userId
​string · required

Who, for unblocking.

SiteCommentBlocksResponse

One page of the people blocked from commenting on a site.
page
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The page returned, from 0.

pageSize
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Rows per page.

​SiteCommentBlockRow[] · required

Most recent first.

total
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Everybody blocked on the site.

SiteDetail

Response of `GET /sites/{siteId}`.
analyticsDays
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many days of traffic this site's plan allows seeing, or zero when it includes none. Sent for the same reason as the flag above: the page can state what the plan covers instead of requesting the figures and rendering a refusal.

analyticsExportAvailable
​boolean · required

Whether this site's plan is sold with the traffic export. Read from the site's own plan rather than from the signed-in account's, because the two differ — an anonymous site is on the anonymous tier whoever is looking at it.

anonymous
​boolean · required

Whether the site has no account behind it.

Stated rather than inferred, and it replaces an inference the dashboard was making from ExpiresAt being set. That proxy held only while an expiry meant one thing: now that an owner can schedule a takedown on a site of their own, a paid site with a date on it would have read as anonymous and been told it gets deleted after a few days.

browserEditAvailable
​boolean · required

Whether this site's plan lets its owner edit a file in the browser. Sent so the file list can leave the Edit action out rather than offering one the server refuses.

commentAudience
​string · required

Who the owner chose may comment — Off, Invited or Anyone. The stored choice; it takes effect only where FeedbackAvailable is true and, for Invited, while the site is invite-only, which the Sharing tab says in words.

createdAt
​string · date-time · required

When the site was created.

customDomainAllowance
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many hostnames of the customer's own this site's plan allows across the account, or zero when it includes none.

Sent here rather than looked up from the public plans list, which is where the dashboard read it and where it is not always findable: GET /plans filters to public tiers, so a site on a plan cut for one account matched nothing and the section rendered as a heading with nothing underneath — exactly the account most likely to have been given an allowance. The same argument as PasswordProtectionAvailable, which is why it sits beside it.

​DeploySummary[] · required

The most recent deploys, newest first.

docsMode
​boolean · required

Whether the site is served through the documents viewer.

expiresAt
​null | string · date-time · required

When an unclaimed anonymous site is removed, or null once claimed.

expiryAction
​string · required

What the expiry does when it falls due, Pause or Delete. Meaningless while ExpiresAt is null, and sent anyway so the form has something to show when the owner sets a date.

feedbackAvailable
​boolean · required

Whether this site's plan includes comments. Sent for PasswordProtectionAvailable's reason: the control shows disabled with a reason rather than failing on submit.

folderId
​null | string · required

The folder it is filed in, or null when it sits at the root of the listing.

The same field SiteSummary carries. Sent here as well so the site's own page can put that folder in its trail and return to it — after a removal, too — instead of to the root of the listing, which is where somebody who opened the site from inside a folder did not come from.

​FormerSubdomain[] · required

The names the site used to answer on, newest first, each redirecting to it.

formsAvailable
​boolean · required

Whether the account's tier includes forms at all.

Reported beside the switch for the reason PasswordProtectionAvailable is: the dashboard has to tell "off" apart from "not yours to turn on", and a control that looks available and then refuses is worse than one that says why.

formsEnabled
​boolean · required

Whether the owner has switched form submissions on for this site.

invitedOnly
​boolean · required

Whether only the people on the site's list may see it. Never true together with PasswordProtected.

invitedViewersAvailable
​boolean · required

Whether this site's plan offers invite-only sites. Sent for PasswordProtectionAvailable's reason: the Sharing tab shows the third choice disabled with a reason rather than offering it and failing.

lastActiveAt
​string · date-time · required

When it last received a deploy.

liveDeployId
​null | string · required

The deploy being served, or null.

maxSiteViewers
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many people this site's plan lets the list hold, the owner included — and, per site, how many invitations it may mail in a day.

modeIsManual
​boolean · required

Whether the serving mode was chosen by the owner rather than detected from the files of the deploy that went live. What lets the dashboard say which of the two it is showing.

name
​null | string · required

What to call it, or null when it has none and the subdomain should be shown instead.

A label only. The site is reached by Subdomain whatever this says, which is why the dashboard shows the address underneath rather than replacing it: two sites are allowed the same name, and the name is not what anybody types into a browser.

openFeedback
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Threads open on the site, the number on the Feedback tab.

passwordProtected
​boolean · required

Whether visitors must enter a password. Only whether one is set is reported — the password itself is stored as a hash, so there is nothing to return.

passwordProtectionAvailable
​boolean · required

Whether this site's plan permits a password at all. Sent so the dashboard can show the control in a disabled state with a reason, rather than offering it and failing on submit.

planId
​string · required

Plan whose limits apply.

primaryUrl
​string · required

The URL to lead with: a hostname of the customer's own once one is serving, and Url otherwise.

Sent as its own field rather than by overwriting Url, because the two are not interchangeable and the subdomain does not stop mattering: it needs no DNS of anybody's and keeps working when a custom domain's records are changed or lapse, which makes it the address to fall back to when the other one is what is being diagnosed.

publicDocumentCounts
​boolean · required

Whether readers of this documents site see each document's views and downloads. Every plan may turn it on.

scheduledExpiryAvailable
​boolean · required

Whether this site's plan lets its owner schedule when it comes down. Sent so the dashboard can show the control disabled with a reason rather than offering it and failing on submit.

siteId
​string · required

ULID of the site.

spaMode
​boolean · required

Whether an unmatched path falls back to index.html.

status
​string · required

Whether the site is serving, and if not, who switched it off — the SiteStatus name.

What the pause control reads, and what tells the three off-states apart for the customer. They need different words and different offers: their own pause has a button that undoes it, a suspension has support to contact, and being held for quota has an upgrade. One boolean could not say which.

statusChangedAt
​null | string · date-time · required

When the state last changed, or null if it never has.

subdomain
​string · required

Its subdomain.

subdomainChangesLeft
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many more times the owner may change Subdomain, or null when the plan does not limit it. What the change-of-address control and its confirmation show.

trafficBreakdownAvailable
​boolean · required

Whether this site's plan includes top lists, the globe and filters on the traffic page. Sent so the page draws a locked card naming the tier instead of requesting a list and rendering a 403.

trafficDetailAvailable
​boolean · required

Whether this site's plan splits people from bots and AI and shows devices, browsers and campaigns.

url
​string · required

Its public URL on the platform's own content domain.

SiteDomainResponse

One custom domain of a site, and what the customer still has to do about it.
bareDomain
​null | string · required

The bare domain this www hostname sits directly on, or null when it is not a www hostname or sits on something else.

What the dashboard needs to offer "send example.com here too": a bare domain cannot point at this platform, so the customer redirects it to the www name at their DNS provider. Read from the zone the nameserver lookup found when the domain was added, which is what makes www.example.com.vn answer example.com.vn; a row added before that was recorded falls back to the two-label case.

certificateReady
​boolean · required

Whether the certificate has been issued, which is what says the DCV records are done rather than missing.

Sent because the provider stops returning those records the moment the certificate exists, including when it validated over HTTP without the customer adding anything. Without this the dashboard reads an empty list as "not issued yet" and the rows vanish from under somebody who is still copying them.

cnameTarget
​string · required

What the customer points their hostname at, once both validations pass. Served rather than hardcoded in the frontend for the reason every other piece of configuration is: a customer told the wrong target gets a hostname that validates and then never serves.

createdAt
​string · date-time · required

When the customer asked for the hostname.

dcvTxtName
​null | string · required

Name of the certificate validation TXT records, or null once none is needed.

dcvTxtValues
​string[] · required

Values of the certificate validation TXT records, or empty once none is needed.

Several under one name: the certificate is issued as a pack and each member is validated separately, so the customer has more than one record to add and adding one of them satisfies nothing.

dnsProvider
​string · required

Who serves DNS for the hostname, as the lowercase name of DnsProvider, and therefore which order the dashboard has to ask for the records in.

hostname
​string · required

The hostname, normalized.

id
​string · required

ULID of the domain row, used to remove or re-check it.

ownershipTxtName
​null | string · required

Name of the ownership TXT record, or null once it is no longer needed.

ownershipTxtValue
​null | string · required

Value of the ownership TXT record, or null for the same reason.

prevalidationUnavailable
​boolean · required

Whether the customer asked for the no-gap path and could not have it, because the certificate provider will not pre-validate a hostname whose zone it is already authoritative for — which is what DnsProvider reports when the customer's own DNS sits with the same provider.

Sent so the dashboard can say so. The override is right — the path they asked for cannot complete and the one they got does — but a customer who ticked the box to protect a live site and is told nothing will point their DNS here believing there is no gap, and learn otherwise from their own visitors.

status
​string · required

Where it is between being asked for and serving, as the lowercase name of SiteDomainStatus.

validation
​string · required

How the certificate is being proven, as the lowercase name of CertificateValidation, and therefore how many records to show.

"http" is one CNAME and nothing else. "txt" is the no-gap path a customer asked for because their hostname is already serving, and carries the record pairs above. Sent rather than inferred from those pairs being empty, which is what an "http" row and a finished "txt" row would otherwise look like alike.

verificationErrors
​string[] · required

Why the certificate provider has not activated the hostname, in its words, or empty when it has nothing to say.

verifiedAt
​null | string · date-time · required

When both validations first passed, or null while still pending.

SiteDomainsResponse

Response of `GET /sites/{siteId}/domains`.
​SiteDomainResponse[] · required

The site's custom domains, oldest first, excluding ones that were given up. Empty for a site with none, which is every site until somebody adds one.

SiteEnvResponse

Response of `GET /sites/{siteId}/env`.
allowed
​boolean · required

Whether the site may run functions now. False, the variables are kept but none reaches the edge, and none can be set.

maxTotalValueBytes
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Largest total of a site's values, in UTF-8 bytes.

maxValueBytes
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Largest value of one variable, in UTF-8 bytes.

maxVars
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Most variables a site may hold.

valueBytes
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The values' total size, in UTF-8 bytes.

​EnvVarView[] · required

The variables, by name.

SiteFeedbackAuthor

A comment's author: a name, never an address.
name
​string · required

The name the site shows.

owner
​boolean · required

Whether they own the site.

removed
​boolean · required

Whether they are no longer on the site's list, or their account is gone.

SiteFeedbackComment

One comment in a thread, as a tool reads it.
​SiteFeedbackAuthor · required

Who wrote it.

body
​string · required

The text, plain — the visitor's own words.

createdAt
​string · date-time · required

When it was written.

editedAt
​null | string · date-time · required

When its author last changed it, or null.

id
​string · required

Comment id.

source
​string · required

Page when written on the site, Api when sent through the API.

SiteFeedbackPage

Response of `GET /sites/{siteId}/feedback`.
available
​boolean · required

Whether the site's plan includes comments.

comments
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Comments the site holds, deleted ones not counted — what the plan's ceiling counts.

limit
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The plan's ceiling on comments per site.

open
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Threads open on the site.

page
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The page returned, from 0.

pageSize
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Rows per page.

paths
​string[] · required

Every page that has a thread, for the page filter.

resolved
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Threads resolved on the site.

​SiteFeedbackRow[] · required

The comments, newest first.

total
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Comments matching the filter.

SiteFeedbackPlace

Where on its page a thread sits.
kind
​string · required

text for selected words, point for a pin.

prefix
​null | string · required

A little of what comes before them, for text.

quote
​null | string · required

The selected words, for text.

selector
​null | string · required

The CSS selector of the element.

snippet
​null | string · required

Text near the pin, for point; may be empty.

suffix
​null | string · required

A little of what comes after them, for text.

SiteFeedbackRow

One comment in the Feedback tab.
authorEmail
​null | string · required

Their address, or null once their account is gone.

authorName
​string · required

Who wrote it.

commentId
​string · required

The comment.

createdAt
​string · date-time · required

When it was written.

excerpt
​string · required

The text, cut at 280 characters.

onLiveVersion
​boolean · required

Whether the thread was opened on the version the site serves now.

path
​string · required

The page it is on.

reply
​boolean · required

Whether it replies in a thread rather than opening one.

resolved
​boolean · required

Whether its thread is resolved.

threadId
​string · required

Its thread, which the View link opens.

SiteFeedbackThread

One thread, whole, as a tool reads it.
​SiteFeedbackComment[] · required

Its comments, oldest first; deleted ones left out.

createdAt
​string · date-time · required

When it was opened.

id
​string · required

Thread id, for replying and resolving.

outdated
​boolean · required

Whether it was opened on an earlier version than the one the site serves now — the words it points at may have changed since.

path
​string · required

The page it is on: a path on the site, or a document's path in a documents site.

​SiteFeedbackPlace · required

Where on the page.

resolvedAt
​null | string · date-time · required

When it was resolved, or null while open.

resolvedBy
​null | string · required

Who resolved it, by name, or null while open.

url
​string · required

The link that opens the page at the thread.

SiteFeedbackThreadsPage

Response of `GET /sites/{siteId}/feedback/threads`.
cursor
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The largest change value on the site at the moment of the read; send it as since to get only the threads that changed after.

more
​boolean · required

Whether another page follows.

page
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The page returned, from 0.

​SiteFeedbackThread[] · required

The threads, in the order they were opened.

SiteFolderNode

One folder in the tree.
createdAt
​string · date-time · required

When the folder was created.

folderId
​string · required

ULID of the folder.

name
​string · required

What the owner calls it.

parentId
​null | string · required

The folder it sits inside, or null when it sits at the root.

siteCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Sites filed directly in this folder, not counting those in folders inside it. Deleted sites are not counted — they are gone from the listing, so counting them would label an empty folder as holding something.

updatedAt
​string · date-time · required

When it was last renamed or moved.

SiteFolderResponse

Response of the endpoints that write a single folder.
​SiteFolderNode · required

The folder as it now stands.

SiteFoldersResponse

Response of `GET /site-folders`.
​SiteFolderNode[] · required

Every folder the account holds, by name.

maxDepth
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How deeply folders may nest. Sent for the same reason as MaxFolders: the drag target that would break this rule can be refused before the drop rather than after the request.

maxFolders
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many folders this account may hold in total.

Sent so the dashboard can grey out "New folder" before somebody names one and is refused. A client that had to discover the limit by hitting it would have to discard what they typed.

SiteFormSummary

One form on a site, as the tab lists it.
lastReceivedAt
​string · date-time · required

When the most recent one arrived.

name
​string · required

The name the form declared, from data-drop2run.

spam
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many of those are marked spam, by us or by the owner.

submissions
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many have arrived, spam included.

SiteFormsResponse

Response of `GET /api/sites/{siteId}/forms`.
enabled
​boolean · required

Whether this site's switch is on, so the tab can say why nothing is arriving.

​SiteFormSummary[] · required

One row per form name, most recently used first.

monthlyAllowance
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

What the account's tier allows a month. Zero means forms are not part of it.

usedThisMonth
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Submissions the account has taken this calendar month, across every site it owns. The figure the allowance is measured against, which is why it is not the site's own count.

SitePauseResponse

Response of `POST /sites/{siteId}/pause` and `/resume`.
ownerPaused
​boolean · required

Whether the owner has it switched off, whatever the status says.

siteId
​string · required

ULID of the site.

status
​string · required

Its lifecycle state, one of SiteStatus as text.

statusChangedAt
​null | string · date-time · required

When the state last changed, or null if it never has.

subdomain
​string · required

The subdomain it is addressed by, whether or not it is serving.

SiteProxyLogResponse

Response of `GET /sites/{siteId}/upstreams/log`.
asOf
​null | string · date-time · required

When the entries were read, or null when they were not.

available
​boolean · required

False when the log could not be read: no dataset configured, or Analytics Engine down.

​ProxyLogRow[] · required

Latest proxied requests, newest first.

SiteSettingsResponse

Response of `PATCH /sites/{siteId}`.
commentAudience
​string · required

Who the owner chose may comment — Off, Invited or Anyone. The stored choice, which takes effect only where the plan and the viewing mode allow it.

docsMode
​boolean · required

The setting as it now stands.

expiresAt
​null | string · date-time · required

When the site is now scheduled to come down, or null when it has no schedule. Echoed because the request sends a string and this is the instant it parsed to.

expiryAction
​string · required

What that schedule will do. Reported even when ExpiresAt is null, where it is the choice a future date would inherit.

folderId
​null | string · required

The folder the site is now filed in, or null when it sits at the root. Echoed so a client that sent "root" reads back the null it produced rather than the token it sent.

formsEnabled
​boolean · required

Whether this site accepts form submissions. The site's own switch, which the tier has to permit before the edge honours it — so a site on a tier without forms reports false here and cannot be set to true.

invitedOnly
​boolean · required

Whether only the people on the site's list may now see it. Never true together with PasswordProtected.

live
​boolean · required

Whether the hostname mapping was rewritten. False for a site that has never published, where the setting is stored and takes effect with its first deploy.

modeIsManual
​boolean · required

Whether the serving mode shown here was chosen by the owner rather than detected from the files.

Reported so the dashboard can say which it is. A control that renders a detected value identically to a chosen one tells the owner they picked something they never picked, and hides the one fact that explains why the mode changed after a deploy — or why it stopped changing.

name
​null | string · required

The name as it now stands, or null when the site has none and the dashboard should show its subdomain. Echoed back because cleaning can change what was sent.

passwordProtected
​boolean · required

Whether the site now requires a password. The password itself is never returned — only the hash is stored, so there is nothing to return even if it were wanted.

publicDocumentCounts
​boolean · required

Whether readers see each document's views and downloads.

siteId
​string · required

ULID of the site.

spaMode
​boolean · required

The setting as it now stands.

SiteSubdomainResponse

Response of `POST /sites/{siteId}/subdomain`: the site's addresses after the change.
​FormerSubdomain[] · required

The names it used to answer on, newest first, each redirecting here.

siteId
​string · required

ULID of the site.

subdomain
​string · required

The subdomain it answers on now.

subdomainChangesLeft
​null | integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many more changes its plan allows, or null when it allows any number.

url
​string · required

Its URL on the content domain.

SiteSummary

One site in a listing.
createdAt
​string · date-time · required

When the site was created.

docsMode
​boolean · required

Whether the site is served through the documents viewer. Here so a listing can label a folder of notes as one, rather than showing it as a static site that happens to answer oddly.

Unlike SiteDetail this listing does not carry whether the mode was chosen or detected: that belongs beside the control that changes it, and there is no such control in a listing.

fileCount
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Files in the live deploy.

folderId
​null | string · required

The folder it is filed in, or null when it sits at the root of the listing.

On every row rather than only when a folder is being listed, because a search crosses folders and its results are flat: without this, a site found by searching would be found without any way to say where it lives, which is half an answer.

lastActiveAt
​string · date-time · required

When it last received a deploy.

liveDeployId
​null | string · required

The deploy being served, or null when nothing has gone live yet.

name
​null | string · required

What to call it in a listing, or null to show the subdomain instead. What makes a list of sites readable: a generated subdomain says nothing about what a site holds.

primaryUrl
​string · required

The URL to show: a hostname of the customer's own once one is serving, and Url otherwise.

The same field SiteDetail carries, and here for the same reason: a customer who has put their own domain in front of a site does not think of it by the address this platform assigned, and a listing that shows them one is a listing they have to translate. Kept beside Url rather than replacing it, because the subdomain needs nobody's DNS and keeps answering when the custom domain is what has gone wrong.

siteId
​string · required

ULID of the site.

spaMode
​boolean · required

Whether an unmatched path falls back to index.html.

status
​string · required

Whether the site is serving, and if not, who switched it off — the SiteStatus name.

A listing has to carry it because a site that is off looks identical to one that is on from every other field here: it still has a live deploy, a size and a URL. Without this the dashboard would show a row that reads as healthy beside a hostname answering 404.

subdomain
​string · required

Its subdomain.

totalBytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Size of the live deploy.

url
​string · required

Its public URL on the platform's own content domain.

SiteTrafficDocument

One document's figures over the traffic window.
downloads
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Loads through the reader's Download button.

path
​string · required

The path with its leading slash, decoded. Recorded from requests and cut at 128 characters, so it is rendered as text rather than a link, like the top lists.

views
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Loads of the file without the download flag.

SiteTrafficList

One list of the traffic page.
asOf
​null | string · date-time · required

When it was read from Analytics Engine, or null.

available
​boolean · required

False when the list could not be read and nothing was kept.

breakdownDays
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Days the list covers.

dimension
​string · required

Which list: page, referrer, country or notfound.

from
​string · date-time · required

First instant the list covers — the breakdown window, not always the range.

​null | array · required

Values, busiest first, or null when the list could not be read.

range
​string · required

The range asked for.

sampled
​boolean · required

Whether any count is an estimate from sampled rows.

to
​string · date-time · required

End of the window, exclusive.

SiteTrafficListItem

One value of a traffic list.
count
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Page views, or requests for broken links, the HTTP version and the cache.

value
​string · required

The path, host or country.

group
​null | string

The agent's group on the bot list — search, ai-search, ai-assistant, ai-training or other — and null on every other list.

SiteTrafficOverview

The traffic page's overview for one range, audience and set of filters.
asOf
​null | string · date-time · required

When the Analytics Engine figures were read, or null when none were.

available
​boolean · required

False when Analytics Engine could not be read and nothing was kept.

breakdownDays
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Days the lists, globe and status split cover — the range, capped at what Analytics Engine keeps.

bucket
​string · required

Width of a chart point: hour, day or week.

days
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Its length in days.

​TrafficDocuments · required

The documents table, by UTC day.

from
​string · date-time · required

First instant of the range, UTC.

measuredSince
​null | string · date-time · required

First day anything was rolled up for this site, or null.

​required
range
​string · required

The range as the page spells it: 24h, 12m, or {N}d.

sampled
​boolean · required

Whether any figure is an estimate from sampled rows.

​null | array · required

The chart, or null when Analytics Engine could not be read.

seriesFrom
​string · date-time · required

Where the chart and tiles start: From, except on a filtered range longer than BreakdownDays, where only the breakdown window can be filtered.

​required
speedAvailable
​boolean · required

False when the speed figures were asked for and could not be read, so a null Speed means "couldn't load" rather than "nothing measured".

splitSince
​null | string · date-time · required

First whole day bots were counted apart from people and arrivals were recorded, or null when not yet. Before it, people include bots and visits are unknown; the page marks the day. Equal to MeasuredSince for a site that was split from its first day, which has no "before".

​required
to
​string · date-time · required

End of the range, exclusive: the top of the next hour.

​required

SiteUpstreamsResponse

Response of `GET /sites/{siteId}/upstreams`.
​ProxyAllowance · required

The account's proxied requests this month against its plan.

limit
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Most upstreams a site may declare.

proxyBlocked
​boolean · required

Whether the platform switched this site's proxy off (D17): every proxy route answers 404 until it is lifted, whatever the upstreams say.

​ProxyRouteView[] · required

The proxy routes the live version's _redirects declares; empty when it has none.

​UpstreamView[] · required

The site's upstreams, oldest first.

SiteViewerCounts

How many people on a site's list are in each status.
everyone
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Everybody listed.

notOpened
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Those who have not opened it yet.

opened
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Those who have opened the site.

SiteViewerRow

One person on a site's list.
email
​string · required

The address, as stored: trimmed and lower-cased.

firstOpenedAt
​null | string · date-time · required

When they first opened the site, or null if they have not.

invitedAt
​string · date-time · required

When the address was added.

lastEmailedAt
​null | string · date-time · required

When the invitation was last mailed, or null if it never was.

owner
​boolean · required

Whether this is the address added for whoever switched the site to invite-only. It cannot be removed.

role
​string · required

What they may do — only View is offered today.

status
​string · required

Opened or NotOpened.

you
​boolean · required

Whether the address belongs to the person asking.

SiteViewersPage

Response of `GET /sites/{siteId}/viewers`.
available
​boolean · required

Whether the plan offers invite-only sites at all. A list can outlive the plan that allowed it, and is still shown so it can be shortened; adding to it is refused.

​SiteViewerCounts · required

How many people are in each status, ignoring the search and filter.

invitedOnly
​boolean · required

Whether the site is currently open only to the people listed.

limit
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The most people this site's plan allows on the list, the owner included.

page
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

The zero-based page returned.

pageSize
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Rows per page.

total
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many rows match the search and filter, across every page.

​SiteViewerRow[] · required

The rows on this page: the owner's first, then the most recently added.

StartCliDeviceRequest

Request body of `POST /api/auth/cli/device`.
clientName
​string · minLength: 1 · maxLength: 64 · required

What the command line calls itself; becomes the token's name.

StartCliDeviceResponse

Response of `POST /api/auth/cli/device`.
deviceCode
​string · required

The command line's own secret. Returned once; it is what collects the token.

expiresAt
​string · date-time · required

When both codes stop working.

intervalSeconds
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How long to wait between polls.

userCode
​string · required

The short code a person types, grouped for reading.

verificationUri
​string · required

Where to go to approve, for somebody typing it by hand.

verificationUriComplete
​string · required

The same page with the code already filled in, for a clickable link.

StartEmailChangeRequest

Request body of `POST /me/email`.
email
​string · maxLength: 320 · required

The address to move the account to.

code
​null | string · maxLength: 16

A code from the authenticator app, which two-factor accounts may give instead.

currentPassword
​null | string · maxLength: 512

The account's password.

StartTwoFactorResponse

Response of `POST /me/2fa/start`.
otpauthUri
​string · required

The otpauth://totp/... URI to draw as a QR code.

secret
​string · required

The same key in Base32, for typing into an app on a device with no camera.

SubdomainAvailabilityResponse

Response of `GET /sites/subdomain-availability`.
available
​boolean · required

Whether this name could be used right now.

normalized
​null | string · required

The name as it would actually be stored, lowercase and trimmed. Null when the input failed format outright, in which case there was nothing to normalize.

reason
​null | string · required

Why not, using the same codes POST /sites would answer with. Null when Available is true.

SubscriptionResponse

Response of `GET /api/billing/subscription`.
​required
​required

SubscriptionRow

One subscription, as the billing page renders it.
cancelAtPeriodEnd
​boolean · required

Whether it stops at the end of the current period.

currentPeriodEnd
​null | string · date-time · required

When the paid period ends; null while paused.

graceUntil
​null | string · date-time · required

When the grace window on a failed payment runs out, or null.

interval
​string · required

The billing interval.

pausedAt
​null | string · date-time · required

When it was paused, or null.

pendingInterval
​null | string · required

The interval it switches to at the next renewal, or null.

pendingPlanId
​null | string · required

The plan it switches to at the next renewal, or null.

planId
​string · required

The plan currently paid for.

seats
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many seats are being paid for; one on every tier not sold by the seat.

status
​string · required

One of the SubscriptionStatus names.

SupportReportContext

What a client knew about the failure being reported. Every field is the client's claim; none is checked against the database.
clientVersion
​null | string · minLength: 0 · maxLength: 64

The client's own version.

code
​null | string · minLength: 0 · maxLength: 100

The error code the client was showing.

deployId
​null | string · pattern: ^[0-9A-HJKMNP-TV-Za-…

The deploy the client was working on.

siteId
​null | string · pattern: ^[0-9A-HJKMNP-TV-Za-…

The site the client was working on.

source
​null | string · minLength: 0 · maxLength: 16

Which client: web, cli, mcp or link. web when absent.

traceId
​null | string · minLength: 0 · maxLength: 128

The API trace id the client was showing.

url
​null | string · minLength: 0 · maxLength: 2048

The page the report was sent from.

TokenSummary

One token as its owner sees it. Never carries the plaintext, which was not kept.
createdAt
​string · date-time · required

When it was issued.

expiresAt
​null | string · date-time · required

When it stops working on its own, or null.

id
​string · required

ULID of the token.

lastUsedAt
​null | string · date-time · required

When a request last authenticated with it, or null if never.

name
​string · required

What its owner called it.

prefix
​string · required

Its first characters, which is all there is to tell two rows apart by.

revokedAt
​null | string · date-time · required

When it was revoked, or null while it stands.

source
​string · required

How it came to exist: Manual (this page), CommandLine (a sign-in on the person's machine) or RemoteMcp (a hosted chat's connector, where revoking it disconnects that connector).

TrafficDocuments

The documents table and the UTC days it covers.
from
​string · date-time · required

First day counted.

​SiteTrafficDocument[] · required

Documents, most viewed first.

to
​string · date-time · required

Last day counted.

TrafficSeriesPoint

One point of the traffic chart.
bytes
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Bytes sent, or null before measurement began.

pageviews
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Page views, or null before measurement began.

requests
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Requests, or null before measurement began.

start
​string · date-time · required

Start of the bucket, UTC.

visits
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Arrivals by people, or null before they were recorded.

TrafficSpeed

How fast the edge answered and how much its cache served.
cacheHitRate
​number | string · double · pattern: ^-?(?:0|[1-9]\d*)(?:… · required

Share of requests the edge cache answered, between 0 and 1.

medianMs
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Median wait at the edge before the response existed, in milliseconds.

p95Ms
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

95th percentile of the same wait.

TrafficStatusSplit

Requests by status class.
s2xx
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Successful.

s3xx
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Redirected or not modified.

s4xx
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Client errors, 404 included.

s5xx
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Server errors.

TrafficTotals

The figures on the traffic page's tiles.
bytes
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Bytes of body sent.

errorRate
​null | number | string · double · pattern: ^-?(?:0|[1-9]\d*)(?:… · required

Share of requests answered 4xx or 5xx, or null when it cannot be computed.

pageviews
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Page views.

requests
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Requests of every kind.

visits
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Page views by people who arrived from another site or typed the address — not unique people — or null when arrivals were not recorded for the period.

TrustedDeviceResponse

One trusted browser.
createdAt
​string · date-time · required

When it was trusted.

current
​boolean · required

Whether it is the browser asking.

expiresAt
​string · date-time · required

When it stops skipping one.

id
​string · required

Its id, which forgetting it names.

label
​string · required

"Chrome on macOS" — the raw User-Agent is not kept.

lastSeenAt
​string · date-time · required

When it last skipped a code.

TrustedDevicesResponse

Response of `GET /me/devices`.
​TrustedDeviceResponse[] · required

The browsers, most recently used first.

TwoFactorChallengeResponse

Body of a 202 from a sign-in route: the first factor was right, and a code is wanted.
challenge
​string · required

Always two_factor; the page goes to /auth/2fa.

TwoFactorStatusResponse

A person's two-factor sign-in, as the profile describes it.
enabledAt
​string · date-time · required

When a code first checked out and turned it on.

​EnforcingAccount[] · required

Accounts this person owns that require two-factor of their members. Non-empty means turning it off is refused, so the page disables the control and names the account to change first.

recoveryCodesLeft
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many of the ten recovery codes are unused.

UpdateNameRequest

Request body of `PATCH /me`.
name
​null | string · maxLength: 100 · required

The new display name, or null or blank to clear it.

UpdateSiteFolderRequest

Body of `PATCH /site-folders/{folderId}`.
name
​null | string

A new name, or null to leave it alone.

parentId
​null | string

Where to move it: a folder id, or "root" to move it to the top level. Null leaves it where it is — see string SiteFolderAccess.RootToken for why moving to the root needs a token of its own rather than a null.

UpdateSiteSettingsRequest

Request body of `PATCH /sites/{siteId}`.
commentAudience
​null | string

Who may comment on the site's pages: Off or Invited, in any case. Null leaves it alone.

Invited is refused on a plan without comments (string Errors.FeedbackUnavailable); Off never is. It is stored whatever the viewing mode, and only takes effect while the site is invite-only — switching the site to public keeps the choice for when it comes back. Anyone is not accepted yet (docs/IMPLEMENTATION-PLAN.md §16.7 S11).

docsMode
​null | boolean

Whether the site is served through the documents viewer instead of as a plain static site. Null leaves the setting alone.

Sending either this or SpaMode tells the server the owner has chosen, and detection stops deciding for this site from then on. The two cannot both be on, so a client switching between modes sends both fields rather than only the one it is enabling.

expiresAt
​null | string

When the site should come down, as an ISO 8601 instant — or an empty string to cancel a schedule it already has.

A string rather than a DateTimeOffset?, and the reason is the same one Name and Password give: null has to keep meaning "not sent", so there has to be some other value that means "clear it". An empty string is that value for all three.

expiryAction
​null | string

What the expiry does when it falls due — Pause or Delete, defaulting to Pause for a date an owner sets.

Only read when a date is being set. Sending it alone is refused rather than stored, because an action with no date is a decision about an event that will not happen, and storing it would answer 200 to a request that changed nothing observable.

folderId
​null | string

Which of the account's folders to file the site in, or "root" to take it back out of every folder. Null leaves it where it is.

A literal token for the root rather than a null, for the reason the other clearable fields here take an empty string: null has to keep meaning "not sent". Unlike them it is a word rather than an empty string, because the same token spells the root in the listing's query parameter and an empty query parameter already means "absent" — see string SiteFolderAccess.RootToken.

Nothing about serving depends on it, so unlike the settings around it this triggers no KV write.

formsEnabled
​null | boolean

Whether this site's hostnames accept form submissions. Null leaves the setting alone.

Turning it on is refused when the account's tier does not include forms (string Errors.FormsNotAvailable); turning it off is always allowed, so a site whose tier changed underneath it is never stranded switched on.

This switches the endpoint on for the site. Which forms exist and what they are called is not a setting at all — it comes from data-drop2run in the HTML (docs/IMPLEMENTATION-PLAN.md §16.2.1 F7).

invitedOnly
​null | boolean

Whether only the people on the site's list may see it, each signed in with their own account. Null leaves the setting alone.

Turning it on clears any password, since the two exclude each other, and adds the caller's own address to the list so they are not locked out; sending it together with a new password is refused. Turning it off is always allowed. The list is kept across both, and either change signs every invited visitor out — those still on the list are let back in without being asked anything.

name
​null | string

What to call the site in the dashboard, or an empty string to clear it and fall back to the subdomain. Null leaves it alone.

Cleaned by SiteNames rather than validated: a name is a label, so there is no shape to reject — only invisible characters to strip and a length to cap. A name that cleans away to nothing is stored as null, which is the same as having cleared it.

password
​null | string

A new access password for the site, or an empty string to remove the gate and make it public again. Null leaves the current setting alone.

The three states are deliberately carried by one nullable string rather than a string plus a boolean. With two fields a client could send a password and private: false together, and there would be no correct interpretation — the endpoint would have to guess or refuse a body that looks valid.

Never echoed back. The response reports only whether a gate is now in place.

publicDocumentCounts
​null | boolean

Whether readers of the site see each document's views and downloads in the reader's toolbar. Null leaves it alone. Allowed on every plan. The counts are of file loads, not of people, and appear within about an hour of switching on; switching off takes up to five minutes to reach every reader.

spaMode
​null | boolean

Whether an unmatched path should fall back to index.html, for a site whose routing happens in the browser. Null leaves the setting alone, and a body where every field is null is refused.

UpdateSiteUpstreamRequest

Request of `PATCH /sites/{siteId}/upstreams/{upstreamId}`.
methods
​null | array · required

The methods to allow from now on; unchanged when left out.

removeHeaders
​null | array · required

Names of headers to drop.

​null | array · required

Headers to add or replace, values in plain text — sealed on arrival.

UploadBatch

Several small files the client sends as one body, under one permit.
​BatchFile[] · required

The files, in the order their bytes must follow the layout.

token
​string · required

Bearer token authorising exactly these files.

UploadTarget

Where the client should PUT one file, and what the PUT must carry.
path
​string · required

Normalized path, which is also what the manifest records.

sha256
​string · required

Digest signed into Token, echoed back because the client needs it to name the file it is sending. It is the same value the client put in the manifest; returning it saves the client from keeping its own manifest indexed by path just to find it again.

token
​string · required

Bearer token authorising exactly this object. Signed by the control plane and verified by the upload Worker, which refuses a second write of the same key without touching R2.

UpstreamHeaderInput

One header as the owner sends it: a name and a plaintext value.
name
​null | string · required

Header name, any case.

value
​null | string · required

The value, sealed on arrival and never shown back.

UpstreamHeaderView

One header as the dashboard sees it.
last4
​string · required

The value's last four characters, or empty for a short value.

name
​string · required

Header name, lowercase.

UpstreamView

One upstream as the dashboard sees it.
blocked
​boolean · required

Whether the platform blocked this origin for every site (D17): calls to it answer 502 until the block is lifted.

createdAt
​string · date-time · required

When it was declared.

​UpstreamHeaderView[] · required

Header names and the last four characters of each value.

id
​string · required

Upstream id.

methods
​string[] · required

Methods visitors may send, GET implying HEAD.

origin
​string · required

https://host.

updatedAt
​string · date-time · required

When it last changed.

UsageResponse

How much of a plan's quota a user is currently using.
bytes
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

What the account is holding on storage — every deploy of every site whose files have not been removed, not just the version currently serving. The same total prepare weighs against long? PlanResponse.MaxAccountBytes, so the page can say how much room is left and be right.

countedSites
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

How many of those the site allowance is measured against: the ones the account holds, which is Active plus Paused. CreateSite and ClaimSites refuse against exactly this set. A site an administrator suspended or the quota job cut is excluded from both.

Sent beside Sites rather than replacing it because a page needs both: the total explains why the list can be longer than the allowance, and this one says whether anything is refused. A dashboard given only the total told an account holding sites the platform had switched off that it was at a limit it was not at.

extraAllowanceUsed
​boolean · required

Whether this account has already been let past its monthly budget once this month.

filesResetAt
​string · date-time · required

When the monthly figure returns to zero. Sent so the page can name a date rather than say "next month", which is a different day depending on when it is read.

filesThisMonth
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Files published this calendar month, counted the way the budget counts them: one per piece of content that was new, plus one per deploy.

filesThisMonthLimit
​null | integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

What the tier allows in a month, or null when the tier is not bounded by month.

formSubmissionsThisMonth
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Form submissions the account has taken this calendar month, across every site it owns, read from the counter the ingest path adds to. Measured against int PlanResponse.MaxFormSubmissionsPerMonth and reset on FilesResetAt, which is the same calendar month boundary.

​required
membersOverSeats
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

People on the account past the seats it pays for — zero on every account in good standing. Non-zero means a team stopped paying, and that many people are removed, the most recently added first, when DateTimeOffset? MeResponse.OverLimitUntil passes. Sent as a count rather than as the member total so the page does not have to know where the seat ceiling sits.

proxyRequestsThisMonth
​integer | string · int64 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Requests the account's sites sent through the API proxy this calendar month, read from the counter the monthly hold is decided on, so up to about an hour and a half behind. Measured against int PlanResponse.MaxProxyRequestsPerMonth; zero where the deployment does not serve the proxy.

proxySuspended
​boolean · required

Whether this month's proxy allowance is spent and every proxy route of the account answers 429.

sites
​integer | string · int32 · pattern: ^-?(?:0|[1-9]\d*)$ · required

Number of non-deleted sites the user owns, whatever state they are in. This is how many rows the site list shows, and it is not the figure the plan's site allowance bounds — read countedSites for that.

VerifyEmailRequest

Request body of `POST /auth/verify`.
token
​string · maxLength: 128 · required

The token the mailed link carried.

VerifyEmailResponse

What redeeming a change-of-address link did, when it started no session.
outcome
​string · required

email-changed once the account moved to the new address — sign in again with it.

VerifyTwoFactorRequest

Body of `POST /auth/2fa/verify`.
code
​null | string · required

Six digits from the app; spaces are ignored.

trustBrowser
​boolean · required

Whether to skip the code in this browser for thirty days.