Skip to content

Node API Reference (OpenAPI)

This page is the node API as a machine-readable OpenAPI 3.1 document, rendered: every route of router in crates/node/src/api.rs (and the area routers it merges, api/<area>.rs) outside /internal/, with its credential, parameters, request body, answer and error codes. Node API is the same API as an operator’s overview with the meroctl command for each route.

The document is docs/public/openapi.json, served beside this page as openapi.json. It is generated from the registry next to the router, crates/node/src/api/openapi.rs, and that registry’s tests hold it to the code on every CI run:

  • every route router serves (outside /internal/) has exactly one entry, and no entry names a route the router lacks;
  • each entry’s request body and query are the ones its handler extracts (Json<T>, Option<Json<T>>, Query<T> or raw bytes), with the same field names as T; a sample of the shape deserializes into T, and a field is optional in the document exactly when T accepts the body without it;
  • additionalProperties: false marks a body whose type refuses unknown fields;
  • every error code a handler raises with a literal code is listed for it;
  • each error code that carries details names that value’s schema, on every error response that lists the code (x-calimero-details) and at the document’s root (x-calimero-error-details), and the schema is held to the constructor that builds the error: each value it builds is one of the schema, and each property is built, always when it is required and not always when it is optional;
  • a response schema the node answers by serializing a Rust type (an app record, an API key, a package release reference, an organization and its teams, an upgrade, Access, Deployer, an attestation and its KMS evidence, an account proof, a registered node, the quotas) names that type, and is held to it the same way: the same field names, a sample read into the type writes back as a value of the schema, and a field is optional exactly when the type may leave it out; one the type only serializes (a Raft group’s status, the rollback counter) is held to real values of the type;
  • the committed openapi.json is what the registry builds now.

The other response schemas, those a handler builds with json!, are written in the registry from the handlers’ answers and are not checked against them. A value left free-form ({} in the schema) is one whose shape is not the API’s: an app’s metadata, initArgs, a method’s result, an event’s data, an app’s error value, the WebAuthn options a ceremony hands to the browser, an app’s ABI and its own OpenAPI document. Each says so in its description. To change the API, change the handler and its entry, then regenerate:

Terminal window
UPDATE_OPENAPI=1 cargo test -p calimero-node --lib openapi
cargo run -p calimero-client-gen

The second command regenerates the Rust client’s route layer from the document (crates/client/src/generated/, by tools/client-gen): one method per operation on its x-calimero-group’s accessor (client.orgs().invite_create(..), client.apps().call(..)), named as the other SDKs name it. Its test fails while the checked-in code differs from what the document generates, so a route change regenerates both in the same pull request.

Every error answers the one Error schema, so a client decodes any error, including a code a route does not list, the same way; it reads details by the error code with the schema the code names. The sealed channel’s own refusal (busy, outside the envelope) is not an Error: its schema is the one x-calimero-sealed-refusal names at the root.

The SDKs (mero-js, calimero-client-py, swift-sdk and kotlin-sdk, the openapi repositories in .github/fleet.json) each vendor this document and generate their client from it. When a push to master changes it, openapi-sync.yml sends each of them a core-openapi event with the commit. Each SDK’s own openapi-sync.yml calls core’s reusable sdk-openapi-sync.yml (pinned by commit), which re-vendors the document at that commit, regenerates, and opens or refreshes one pull request (chore/core-openapi), so that SDK’s CI judges the change before anything is released. Run the workflow by hand (dry run by default) to resend the event.

The pull request’s title sets the SDK’s next version. scripts/openapi-classify.py diffs the document the SDK vendors now against the new one, using a pinned oasdiff and a set of rules for the x-calimero-* extensions:

Change Title SDK release
Something callers of the generated client rely on is removed or changed: a route, a response field, an operationId, a narrowed enum, a new required request field. The same holds for an operation that now needs a step-up, an operator signature or the sealed channel, stops being retry-safe, or moves to another x-calimero-group. feat(api)!: with a BREAKING-CHANGE: footer major
Something is added and nothing is broken feat(api): minor
Descriptions, new x-calimero-codes entries, and anything else no generated signature sees chore(api): patch

A pull request here that changes the document gets the same verdict in the summary of its OpenAPI impact run, so its author sees what each SDK will release before merging.

Calimero node API, OpenAPI 3.1.0: openapi.json(164 paths). Shared schemas are listed at the end.

Public

In the clear (/health, /attestation) or sealed without a credential.

GET /attestation

The node's attestation. In the clear.

In the clear. A TDX quote binding the node's transport key (or, with purpose=receipts, its receipt key and the governance; with purpose=kms, what it verified of its KMS; with purpose=orchestrator, the cluster identity this replica holds) to nonce; app/appHash bind an app's bundle hash. A client checks it before it seals anything to the key. Who: anyone.

ParameterInType
noncequerystring
app?querystring
appHash?querystring
purpose?query"receipts" | "kms" | "orchestrator"

Answer (application/json)

AttestationDoc
StatusCodes
400BAD_HASH; BAD_NONCE
404NOT_FOUND: no such object, or one the caller may not see

GET /health

Node health. In the clear.

In the clear. The node's id, the system group's leader (null: none known), its merod release, the newest cluster version it supports (clusterVersion) and the cluster's rollback epoch (null on a node without a rollback counter). Who: anyone.

Answer (application/json)

{
  ok: boolean,
  node: integer,
  systemLeader: integer | null,
  release: string,
  clusterVersion: string,
  rollbackEpoch: integer | null
}

GET /publishers/{signer}

Whether a signing key is bound. Sealed.

Whether a package signing key (did:key) is bound to an organization on this cluster (bound, never which), and its binding generation (0: never bound). Who: signed in (a session or an API key).

ParameterInType
signerpathstring

Answer (application/json)

{
  signerId: string,
  cluster: string,
  generation: integer,
  bound: boolean
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /recover/holder

Bring an organization's or account's apps back from its recovery files. Sealed.

Sent by the holder's own device, over the sealed channel: its newest holder file (slice), each app's file and the code files, in the receiving node's --recovery-dir (or --recover-from) under org-<id>/ or account-<id>/, each with the data key the holder opened from it with its backup key (hex). The cluster admits it with the operator's signature over cluster / __recover_holder / { holder, slice, apps: [{ app, file, sha256 }] } (428 first, naming it). Where owners upgrade apps, and only for an organization, account, apps and passkeys the cluster does not hold; the receiving node seeds each app, which answers 409 APP_RESTORING until its replicas hold it. People sign in again with the passkeys they had. Who: anyone. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  holder: string,
  slice: {
    file: string,
    key: string
  },
  apps?: {
    file: string,
    key: string
  }[],
  code?: {
    file: string,
    key: string
  }[],
  operatorProof?: OperatorProof
}

Answer (application/json)

{
  apps: any
}
StatusCodes
400BAD_RECOVERY_FILE; BAD_RECOVERY_KEY; BAD_REQUEST: the request is malformed; NOT_A_REPLICA_NODE; TOO_MANY_FILES; UNATTESTED_RECOVERY_FILE
403BAD_OPERATOR_SIGNATURE
409FEATURE_NOT_ACTIVE; NO_BACKUP_DIR; RECOVERY_SEGMENTS_MISSING. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /releases

The cluster's releases. Sealed.

The cluster's governance and the deadlines set on mero-tee releases, oldest release first: after after (RFC 3339; afterSecs Unix seconds) a scope that has not approved that release (or a newer one) starts no new work. Who: anyone.

Answer (application/json)

{
  governance: Governance,
  deadlines: {
    version: string,
    after: string,
    afterSecs: integer
  }[]
}

Accounts

Sign-up, sign-in, passkeys, sessions, API keys and the account's own approvals.

POST /auth/account-proof

Prove the account to another party. Sealed.

A statement signed with this node's receipt key that the caller's passkey session asked to bind nonce for audience. Who: a passkey session (an API key is refused).

Body (application/json)

{
  nonce: string,
  audience: string
}

Answer (application/json)

AccountProof
StatusCodes
400BAD_AUDIENCE; BAD_NONCE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /auth/activity

What the account's passkeys did. Sealed.

Newest first, the last 100: sign-ins (app, origin) and approvals (method, subject); after keeps the entries after that Unix second. Who: an account holder (a passkey session not bound to an app's frontend).

ParameterInType
after?queryinteger

Answer (application/json)

{
  activity: {
    at: integer,
    passkey: string,
    kind: "signIn" | "approval",
    app?: string | null,
    origin?: string | null,
    method?: string,
    subject?: string
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /auth/aliases

The account's aliases. Sealed.

Who: signed in (a session or an API key).

Answer (application/json)

{
  aliases: {
    [key: string]: string
  }
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /auth/aliases/{alias}

Resolve an alias. Sealed.

Who: signed in (a session or an API key).

ParameterInType
aliaspathstring

Answer (application/json)

{
  alias: string,
  appId: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

PUT /auth/aliases/{alias}

Set an alias. Sealed.

Who: signed in (a session or an API key).

ParameterInType
aliaspathstring

Body (application/json)

{
  app: string
}

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /auth/aliases/{alias}

Remove an alias. Sealed.

Who: signed in (a session or an API key).

ParameterInType
aliaspathstring

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /auth/apikeys

The account's API keys. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend).

Answer (application/json)

{
  keys: ApiKey[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/apikeys

Make an API key. Sealed.

Scoped to apps and methods, read-only or not, for ttlSecs; upgrades makes an upgrade key, which signs upgrades of one app in place of a passkey. 412 first. The key is shown once. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  label?: string,
  apps?: string[],
  methods?: string[],
  readOnly?: boolean,
  allowConfirm?: boolean,
  ttlSecs?: integer,
  upgrades?: {
    app: string,
    package?: string
  },
  confirm?: Confirm
}

Answer (application/json)

{
  keyId: string,
  key: string
}
StatusCodes
400BAD_UPGRADE_KEY; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; WRONG_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429QUOTA_EXCEEDED

DELETE /auth/apikeys/{key}

Revoke an API key. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
keypathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /auth/apps

The account's own apps. Sealed.

The apps the account owns, in any organization (a package-bound session: its package's), with its personal organization's approvedReleases: each app's release, the newer releases it may upgrade to, its last upgrade, its replicas' releases and lastWriteAt. Who: signed in (a session or an API key).

ParameterInType
after?querystring
limit?queryinteger

Answer (application/json)

{
  scope: AppScope,
  governance: Governance,
  approvedReleases: string[] | null,
  clusterReleases: ClusterRelease[],
  apps: ReportApp[],
  next: string | null
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /auth/backup-key

The account's backup key. Sealed.

The X25519 public key the recovery-disk backups of the account's personal apps are sealed to (key, null while none is set). Who: an account holder (a passkey session not bound to an app's frontend).

Answer (application/json)

BackupKeyAnswer
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/backup-key

Set the account's backup key. Sealed.

publicKey: 64 lowercase hex, an X25519 public key whose private half the account holder keeps (never a node), for its personal apps, where owners upgrade apps. 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  publicKey: string,
  confirm?: Confirm
}

Answer (application/json)

BackupKeyAnswer
StatusCodes
400BAD_BACKUP_KEY; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/logout

End this session. Sealed.

Who: a passkey session (an API key is refused).

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/logout-all

End every session of the account. Sealed.

revoked: how many sessions ended. Who: an account holder (a passkey session not bound to an app's frontend).

Answer (application/json)

{
  revoked: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /auth/me

The caller's account. Sealed.

The account, its passkeys (with addedAt and lastSignInAt), organizations (personal: the one made at sign-up, where its instances go unless they name another; its approvals are that organization's), recovery state, and how the caller came (via). Who: signed in (a session or an API key).

Answer (application/json)

{
  accountId: string,
  name: string,
  passkeys: {
    id: string,
    signCount: integer,
    label: string | null,
    addedAt?: integer | null,
    lastSignInAt?: integer | null
  }[],
  orgs: {
    orgId: string,
    name: string,
    role: OrgRole,
    personal?: boolean
  }[],
  via: "session" | "apiKey",
  passkeyId: string | null,
  app?: string | null,
  origin?: string | null,
  recoveryCode?: boolean,
  recoveryPending?: {
    accountId: string,
    credentialId: string,
    startedAt: integer,
    readyAt: integer
  } | null
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/passkey/login/begin

Start a sign-in. Sealed.

A WebAuthn challenge for any passkey of the cluster. origin is an app frontend's registered origin, whose rp-id the ceremony then uses. options are the WebAuthn options to hand to the browser as they are: free-form here, their shape is WebAuthn's. Who: anyone.

Body (application/json, optional): May be absent.

{
  origin?: string
}

Answer (application/json)

{
  challengeId: string,
  options: any
}
StatusCodes
429RATE_LIMITED: a node's limit on open streams or ceremonies

POST /auth/passkey/login/finish

Finish a sign-in. Sealed.

Who: anyone.

Body (application/json)

{
  challengeId: string,
  assertion: Assertion
}

Answer (application/json)

Session
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; WRONG_CHALLENGE
401PASSKEY_UNKNOWN_HERE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/passkey/register/begin

Start a sign-up. Sealed.

Creation options for a new passkey. invite is an organization or cluster sign-up invite token, which the policy may require; 403 SIGN_UP_REFUSED when the policy would refuse the sign-up. options are the WebAuthn options to hand to the browser as they are: free-form here, their shape is WebAuthn's. Who: anyone.

Body (application/json)

{
  name?: string,
  origin?: string,
  invite?: string
}

Answer (application/json)

{
  challengeId: string,
  options: any
}
StatusCodes
403SIGN_UP_REFUSED
429RATE_LIMITED: a node's limit on open streams or ceremonies

POST /auth/passkey/register/finish

Finish a sign-up. Sealed.

The new passkey's registration. Answers 412 CONFIRM_REQUIRED first: the new passkey signs the account it creates; the retry with confirm (and the same invite) opens a session, and redeems invite for the new account. Who: anyone. Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  challengeId: string,
  registration: Registration,
  invite?: string,
  confirm?: Confirm
}

Answer (application/json)

Session
StatusCodes
400BAD_REGISTRATION; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; WRONG_CHALLENGE
401PASSKEY_UNKNOWN_HERE
403SIGN_UP_REFUSED
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/passkeys/add/begin

Start adding a passkey. Sealed.

Creation options for another passkey (a device) on the caller's account. options are the WebAuthn options to hand to the browser as they are: free-form here, their shape is WebAuthn's. Who: an account holder (a passkey session not bound to an app's frontend).

Answer (application/json)

{
  challengeId: string,
  options: any
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/passkeys/add/finish

Finish adding a passkey. Sealed.

Answers 412 first; sent again with confirm signed by a passkey the account already has. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  challengeId: string,
  registration: Registration,
  confirm?: Confirm
}

Answer (application/json)

{
  credentialId: string
}
StatusCodes
400BAD_REGISTRATION; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; WRONG_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/passkeys/{cred}

Name a passkey. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend).

ParameterInType
credpathstring

Body (application/json)

{
  label: string
}

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /auth/passkeys/{cred}

Remove a passkey. Sealed.

Its sessions end. 412 first; the retry's JSON body is { confirm }. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
credpathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/recovery

Make a recovery code. Sealed.

Shown once, replacing any; 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{
  code: string
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; WRONG_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /auth/recovery

Remove the recovery code. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/recovery/begin

Start an account recovery. Sealed.

Signed out, with the recovery code: creation options for the passkey that will replace the lost ones. options are the WebAuthn options to hand to the browser as they are: free-form here, their shape is WebAuthn's. Who: anyone.

Body (application/json)

{
  code: string
}

Answer (application/json)

{
  challengeId: string,
  options: any
}
StatusCodes
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429RATE_LIMITED: a node's limit on open streams or ceremonies

POST /auth/recovery/cancel

Cancel an account recovery. Sealed.

With a passkey the account has; 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/recovery/finish

Finish an account recovery. Sealed.

Approved by the new passkey once readyAt passed (412 first): adds it and ends every session of the account. Who: anyone. Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  accountId?: string,
  confirm?: Confirm
}

Answer (application/json)

Session
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; WRONG_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
409RECOVERY_NOT_READY. details of RECOVERY_NOT_READY: a RecoveryNotReady.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /auth/recovery/start

Spend the recovery code. Sealed.

Logs the new passkey as pending; it may finish the recovery once readyAt passed (72 h). 401 for a wrong or spent code. Who: anyone.

Body (application/json)

{
  challengeId: string,
  code: string,
  registration: Registration
}

Answer (application/json)

{
  accountId: string,
  credentialId: string,
  startedAt: integer,
  readyAt: integer
}
StatusCodes
400BAD_REGISTRATION; WRONG_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
409RECOVERY_PENDING

POST /auth/refresh

Refresh a session. Sealed.

A new session and the refresh token to use next (the same one until it is an hour old). A reused, superseded token ends the sessions it opened. Who: anyone.

Body (application/json)

{
  refreshToken: string
}

Answer (application/json)

Session
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
503UNAVAILABLE: the cluster cannot answer now

GET /auth/sessions

The account's live sessions. Sealed.

Latest active first, at most 256. openedAt (Unix seconds) is null for a session opened before the node kept it. Who: an account holder (a passkey session not bound to an app's frontend).

Answer (application/json)

{
  sessions: {
    session: string,
    passkey: string | null,
    app: string | null,
    origin: string | null,
    openedAt: integer | null,
    lastActiveAt: integer,
    current: boolean
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /auth/sessions/{session}

End one session. Sealed.

404 for a session the account does not hold live. Who: an account holder (a passkey session not bound to an app's frontend).

ParameterInType
sessionpathstring

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /auth/usage

The account's usage against its quotas. Sealed.

The apps the account owns, its bundle bytes (a decimal string), API keys and owned organizations; the file bytes held by each payer it belongs to (each organization it is in, and account:<id> for its own apps); the cluster's quotas; and what today's runs of the apps the account develops used (decimal strings). Who: signed in (a session or an API key).

Answer (application/json)

{
  apps: integer,
  bundleBytes: string /* decimal */,
  apiKeys: integer,
  orgsOwned: integer,
  fileBytes: {
    [key: string]: integer
  },
  quotas: Quotas,
  developerFuelToday: string /* decimal */,
  developerWritesToday: string /* decimal */
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

Packages

Signed releases (.mpk), raw bundles and frontend origins.

POST /bundles

Upload a raw component. Sealed.

A calimero:app component, 16 MiB at most; only on a node started with --allow-unsigned-bundles or --dev. A WASM core module (SDK 0.12) is refused 400 UNSUPPORTED_BUNDLE. Who: an installer (an account holder, or an unscoped API key that is not read-only).

Body (application/wasm): the component

Answer (application/json)

{
  hash: string
}
StatusCodes
400BAD_BUNDLE; UNSUPPORTED_BUNDLE. details of BAD_BUNDLE: a ServiceRefused, UNSUPPORTED_BUNDLE: a ServiceRefused.
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
413TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429QUOTA_EXCEEDED

GET /package-origins/{package}

A package's frontend origins. Sealed.

The custom origins (and rp-ids) the package's manager registered for its frontend. Who: signed in (a session or an API key).

ParameterInType
packagepathstring

Answer (application/json)

{
  package: string,
  origins: PackageOrigin[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /package-origins/{package}

Register a frontend origin. Sealed.

By whoever manages the package, with a passkey step-up over the change. Answers the origin as registered (the one already there, when the same origin is registered again). Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
packagepathstring

Body (application/json)

{
  origin: string,
  rpId?: string,
  served?: boolean,
  confirm?: Confirm
}

Answer (application/json)

PackageOrigin
StatusCodes
400BAD_RP_ID; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429QUOTA_EXCEEDED

DELETE /package-origins/{package}

Remove a frontend origin. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
packagepathstring

Body (application/json)

{
  origin: string,
  confirm?: Confirm
}

Answer (application/json)

{
  package: string,
  origin: string,
  removed: boolean
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /packages

Installed packages. Sealed.

Only the releases the caller may see. Who: signed in (a session or an API key).

Answer (application/json)

{
  packages: Package[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /packages

Upload a signed release. Sealed.

A signed .mpk, checked as an install from the registry is (signature, artifact digests, minRuntimeVersion, the package's pinned signer, every service compiles). Only with --dev; otherwise 403 UPLOADS_DISABLED. Who: an installer (an account holder, or an unscoped API key that is not read-only).

Body (application/octet-stream): the .mpk

Answer (application/json)

{
  package: string,
  version: string,
  signerId: string,
  services: {
    [key: string]: string
  }
}
StatusCodes
400BAD_BUNDLE; BAD_PACKAGE; COMPUTE_ABI_MISMATCH; UNSUPPORTED_BUNDLE. details of BAD_BUNDLE: a ServiceRefused, COMPUTE_ABI_MISMATCH: a ServiceRefused, UNSUPPORTED_BUNDLE: a ServiceRefused.
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403DEPLOY_NOT_GRANTED; FORBIDDEN: the credential may not do this (scope, role, governance, read-only); UPLOADS_DISABLED
413TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /packages/install

Install a release from the registry. Sealed.

Who: an installer (an account holder, or an unscoped API key that is not read-only).

Body (application/json)

{
  package: string,
  version: string
}

Answer (application/json)

{
  package: string,
  version: string,
  signerId: string,
  services: {
    [key: string]: string
  }
}
StatusCodes
400BAD_BUNDLE; BAD_PACKAGE; COMPUTE_ABI_MISMATCH; NO_REGISTRY; UNSUPPORTED_BUNDLE. details of BAD_BUNDLE: a ServiceRefused, COMPUTE_ABI_MISMATCH: a ServiceRefused, UNSUPPORTED_BUNDLE: a ServiceRefused.
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403DEPLOY_NOT_GRANTED; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /packages/{package}

One package. Sealed.

The versions the caller may see; 404 when none. Who: signed in (a session or an API key).

ParameterInType
packagepathstring

Answer (application/json)

Package
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /packages/{package}

Uninstall a package. Sealed.

Every version; refused while an app runs one. Who: an account holder (a passkey session not bound to an app's frontend).

ParameterInType
packagepathstring

Answer (application/json)

Uninstalled
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /packages/{package}/{version}

Uninstall one version. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend).

ParameterInType
packagepathstring
versionpathstring

Answer (application/json)

Uninstalled
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /packages/{package}/{version}/pipelines

A release's pipelines. Sealed.

The pipelines the release registers, by name: hash, worstCaseFuel (a decimal string), the modules they pin and the canonical pipeline. 404 for a release the caller may not see. Who: signed in (a session or an API key).

ParameterInType
packagepathstring
versionpathstring

Answer (application/json)

{
  [key: string]: {
    hash: string,
    worstCaseFuel: any,
    modules: any,
    pipeline: any
  }
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

Apps

App instances (contexts): calls, views, events, upgrades, blobs and sealed files.

GET /apps

Apps the caller reaches. Sealed.

Anyone may list public apps. Who: signed in (a session or an API key).

ParameterInType
package?querystring
bundle?querystring

Answer (application/json)

{
  apps: AppEntry[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps

Create an app instance. Sealed.

From a release (package, version, service), a deployment's offer (deployment), or an uploaded bundle; in an organization (org), or, naming none, the caller's personal organization. Every app is in an organization. initArgs go to the app's init and metadata is kept as given (both free-form JSON). Answers once init committed; compute says whether the app has a compute component. Who: an installer (an account holder, or an unscoped API key that is not read-only).

Body (application/json)

{
  name?: string,
  bundle?: string,
  package?: string,
  version?: string,
  service?: string,
  org?: string,
  access?: Access,
  initArgs?: any,
  metadata?: any,
  deployment?: string
}

Answer (application/json)

{
  appId: string,
  contextId: string,
  group: integer,
  replicas: integer[],
  compute: boolean
}
StatusCodes
400AMBIGUOUS_COMPUTE; BAD_REQUEST: the request is malformed; NOT_OFFERED; NO_SUCH_SERVICE; VERSION_REQUIRED
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409RELEASE_DEADLINE; RUNTIME_TOO_OLD. details of RELEASE_DEADLINE: a ReleaseDeadline, RUNTIME_TOO_OLD: a RuntimeTooOld.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
422INIT_FAILED. details of INIT_FAILED: a InitFailed.
429QUOTA_EXCEEDED
503UNAVAILABLE: the cluster cannot answer now

GET /apps/{app}

One app. Sealed.

{app} is an app id or its context id (hex(SHA-256(app_id))), here and on every /apps/{app} route. Who: signed in (a session or an API key).

ParameterInType
apppathstring

Answer (application/json)

App
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /apps/{app}

Delete an app. Sealed.

The owner or an organization admin. Who: a passkey session (an API key is refused).

ParameterInType
apppathstring

Answer (application/json)

{
  appId: string,
  deleted: boolean
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/abi

An app's ABI. Sealed.

The ABI its bundle embeds: methods, events, errors and state. abi is the bundle's own document, free-form here: its format is the ABI's, not this API's. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring

Answer (application/json)

{
  bundle: string,
  abi: any
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/access

Set who may reach an app. Sealed.

A package-bound session: only its own package's app, from one of its package's teams to another. Who: a passkey session (an API key is refused).

ParameterInType
apppathstring

Body (application/json)

{
  access: Access
}

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/attestation

Every replica's receipt-key attestation. Sealed.

Each replica's /attestation?purpose=receipts for nonce (32 bytes, hex), or why it could not be had (error), and cluster, the cluster id each quote binds (with the replica's node): the documents are fetched in the clear, so their own cluster and node fields count for nothing. Any other query parameter is ignored. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
noncequerystring

Answer (application/json)

{
  appId: string,
  cluster: string,
  replicas: {
    node: integer,
    attestation: AttestationDoc
  } | {
    node: integer,
    error: string
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/blobs

List an app's blobs. Sealed.

Plain blobs only. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring

Answer (application/json)

{
  blobs: {
    blobId: string,
    id: string,
    size: integer
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/blobs

Upload a blob. Sealed.

A plain blob, stored with the request's Content-Type, which a component app's download answers with: any media type (printable ASCII, 127 bytes at most; another is 400 BAD_REQUEST), application/octet-stream when the request names none. Send the blob's own type, not */*, which would be stored as its type. Any sealed parameter, true or false, is refused 400 USE_FILES_API: sealed files go through /files. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
sealed?queryboolean

Body (application/octet-stream): the blob; its Content-Type is the type it is stored and served with

Answer (application/json)

{
  blobId: string,
  id: string,
  size: integer,
  index: integer
}
StatusCodes
400USE_FILES_API
401UNAUTHENTICATED: no, unknown, expired or revoked credential
413TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429QUOTA_EXCEEDED

GET /apps/{app}/blobs/{id}

Download a blob. Sealed.

{id} is base58 or hex; grant is a link the app made (BlobRef::grant). Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
idpathstring
grant?querystring

Answer (*/*): OK: the blob: a component app's under the MIME type it was stored with, otherwise application/octet-stream.

StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
503UNAVAILABLE: the cluster cannot answer now

DELETE /apps/{app}/blobs/{id}

Forget a blob. Sealed.

The owner or an organization admin. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
idpathstring

Answer (application/json)

{
  index: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/blobs/{id}/info

A blob's size. Sealed.

Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
idpathstring

Answer (application/json)

{
  blobId: string,
  id: string,
  size: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
409NOT_SUPPORTED
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/blobs/{id}/revoke

Invalidate a blob's grants. Sealed.

The grants made so far for a published blob; the owner or an organization admin. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
idpathstring

Answer (application/json)

{
  index: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/events

An app's events as server-sent events. Sealed.

Committed events from index from, then live ones, each to its audience. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
from?queryinteger

Answer (text/event-stream): Server-sent events: each committed event the caller is in the audience of.

StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429RATE_LIMITED: a node's limit on open streams or ceremonies
503UNAVAILABLE: the cluster cannot answer now

GET /apps/{app}/files

List an app's sealed files. Sealed.

Who: signed in (a session or an API key).

ParameterInType
apppathstring

Answer (application/json)

{
  files: {
    blobId: string,
    id: string,
    size: integer,
    sha256: string
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/files

Upload a sealed file. Sealed.

Up to 16 MiB in one request; the owner and the organization's members. Who: signed in (a session or an API key).

ParameterInType
apppathstring

Body (application/octet-stream): the file

Answer (application/json)

{
  blobId: string,
  id: string,
  size: integer,
  sha256: string,
  index: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
413TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429QUOTA_EXCEEDED

POST /apps/{app}/files/uploads

Begin a file upload. Sealed.

A session for a file of size bytes, sent in parts of partBytes. Who: signed in (a session or an API key).

ParameterInType
apppathstring

Body (application/json)

{
  size: integer
}

Answer (application/json)

{
  uploadId: string,
  partBytes: integer,
  parts: integer,
  expiresAt: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
413TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429QUOTA_EXCEEDED

GET /apps/{app}/files/uploads/{upload}

Where an upload is. Sealed.

Who: signed in (a session or an API key).

ParameterInType
apppathstring
uploadpathstring

Answer (application/json)

{
  uploadId: string,
  partBytes: integer,
  parts: integer,
  expiresAt: integer,
  size: integer,
  next: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /apps/{app}/files/uploads/{upload}

Abort an upload. Sealed.

Who: signed in (a session or an API key).

ParameterInType
apppathstring
uploadpathstring

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/files/uploads/{upload}/complete

Commit an upload. Sealed.

Charges and commits the file; a retry answers the same file. 409 UPLOAD_INCOMPLETE names the part still missing. Who: signed in (a session or an API key).

ParameterInType
apppathstring
uploadpathstring

Answer (application/json)

{
  blobId: string,
  id: string,
  size: integer,
  sha256: string,
  index: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
409UPLOAD_INCOMPLETE. details of UPLOAD_INCOMPLETE: a UploadPosition.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

PUT /apps/{app}/files/uploads/{upload}/parts/{k}

Send one part. Sealed.

Part k (from 0), raw bytes; a part out of order (409 PART_OUT_OF_ORDER), or one that differs from the part sent before as k (409 PART_CONFLICT), answers the next one expected in details.next. Who: signed in (a session or an API key).

ParameterInType
apppathstring
uploadpathstring
kpathstring

Body (application/octet-stream): the part

Answer (application/json)

{
  next: integer
}
StatusCodes
400BAD_PART; BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
409PART_CONFLICT; PART_OUT_OF_ORDER. details of PART_CONFLICT: a UploadPosition, PART_OUT_OF_ORDER: a UploadPosition.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
503FILES_UNAVAILABLE. details of FILES_UNAVAILABLE: a RetryAfter.

GET /apps/{app}/files/{id}

One sealed file. Sealed.

Its plaintext size and SHA-256, never its key. Who: signed in (a session or an API key).

ParameterInType
apppathstring
idpathstring

Answer (application/json)

{
  blobId: string,
  id: string,
  size: integer,
  sha256: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/files/{id}/export

Export a sealed file's key. Sealed.

The owner and the organization's members. recipient is an X25519 public key (64 hex characters); the file's data key comes back wrapped to it, with the file's segments (each one's hash, hex) and ephemeral public key. The node never answers plaintext or a key in the clear. 30 a minute per account. Who: signed in (a session or an API key).

ParameterInType
apppathstring
idpathstring

Body (application/json)

{
  recipient: string
}

Answer (application/json)

{
  app: string,
  id: string,
  size: integer,
  sha256: string,
  segments: string[],
  ephemeral: string,
  wrapped: string
}
StatusCodes
400BAD_RECIPIENT; BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429TOO_MANY_EXPORTS

GET /apps/{app}/files/{id}/segments/{k}

One segment of a sealed file. Sealed.

Segment k (from 0) of the file's ciphertext, raw; the owner and the organization's members. Who: signed in (a session or an API key).

ParameterInType
apppathstring
idpathstring
kpathstring

Answer (*/*): OK: the segment's ciphertext, application/octet-stream.

StatusCodes
400BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see; NO_SUCH_SEGMENT
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/intents

Call a method. Sealed.

A logged call: the result, the events of the call the caller receives, and the answering node's receipt. A confirm method answers 412 first. An app error is 422 APP_ERROR with details { index, code, fields }; a trap 422 TRAP. args, result and each event's data are the app's own JSON, free-form here: the app's ABI (GET /apps/{app}/abi, or its OpenAPI document) types them. Who: whoever the app's access admits (a public app: anyone). Step-up: when the method is a confirm method of the app's ABI, answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
apppathstring

Body (application/json)

{
  method: string,
  args?: any,
  idempotencyKey?: string,
  confirm?: Confirm
}

Answer (application/json)

{
  index: integer,
  result: any,
  events: {
    kind: string,
    data: any
  }[],
  receipt: Receipt
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
409RELEASE_DEADLINE. details of RELEASE_DEADLINE: a ReleaseDeadline.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
413ARGS_TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
422APP_ERROR; TRAP. details of APP_ERROR: a AppError, TRAP: a Trap.
429QUOTA_EXCEEDED
503TIMEOUT; UNAVAILABLE: the cluster cannot answer now. details of TIMEOUT: a RetryAfter.

POST /apps/{app}/metadata

Set an app's metadata. Sealed.

The owner or an organization admin; 16 KiB at most. metadata is the caller's own JSON, free-form, kept as given. Who: signed in (a session or an API key).

ParameterInType
apppathstring

Body (application/json)

{
  metadata: any
}

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
413TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/methods/{method}

Call a method by its path. Sealed.

The body of /intents or /views without method, which the path names, as the app's OpenAPI document lists it: a view the running bundle's ABI declares (without confirm) is answered as /views, anything else as /intents, with that route's gate, step-up and limits. Retry-safe as a view always, as a call with idempotencyKey. args, result and each event's data are the app's own JSON, free-form here: the app's ABI (GET /apps/{app}/abi, or its OpenAPI document) types them. Who: whoever the app's access admits (a public app: anyone). Step-up: when the method is a confirm method of the app's ABI, answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
apppathstring
methodpathstring

Body (application/json)

{
  args?: any,
  idempotencyKey?: string,
  confirm?: Confirm,
  consistency?: "strong" | "stale",
  minIndex?: integer
}

Answer (application/json)

{
  index: integer,
  result: any,
  events?: {
    kind: string,
    data: any
  }[],
  receipt: Receipt
}
StatusCodes
400EXPIRED_CHALLENGE; RESERVED_METHOD; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
409RELEASE_DEADLINE. details of RELEASE_DEADLINE: a ReleaseDeadline.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
413ARGS_TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
422APP_ERROR; TRAP. details of APP_ERROR: a AppError, TRAP: a Trap.
429QUOTA_EXCEEDED
503NOT_CAUGHT_UP; TIMEOUT; UNAVAILABLE: the cluster cannot answer now. details of TIMEOUT: a RetryAfter.

POST /apps/{app}/move

Move an app to another organization. Sealed.

Its data where it is; its files, runs and quotas go to the target, org or app-team access becomes the target's app team of its package. bringMembers adds the source's members who reach it, capped at member. from is the organization it left, null for an app of the caller's own; added the accounts brought; revokedInvites how many invites to its old team were withdrawn. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
apppathstring

Body (application/json)

{
  toOrg: string,
  bringMembers?: boolean,
  confirm?: Confirm
}

Answer (application/json)

{
  appId: string,
  from: string | null,
  org: string,
  access: Access,
  created: boolean,
  added: string[],
  revokedInvites: integer
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/openapi.json

An app's OpenAPI document. Sealed.

Generated from the ABI of the bundle the app runs, under the access /abi has: one POST /apps/{app}/methods/{method} per method, with its arguments, result and errors. Free-form here: it is a document of its own, which a client reads as OpenAPI. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring

Answer (application/json)

{
  [key: string]: any
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
410UNSUPPORTED_ENGINE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
422BAD_ABI

GET /apps/{app}/pipeline-runs

An app's pipeline runs. Sealed.

The recent runs, newest first, as { runs }; limit 1 to 100. Sizes, hashes and results only for callers who may list the app's files. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
limit?querystring

Answer (application/json)

{
  [key: string]: any
}
StatusCodes
400BAD_LIMIT
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/pipeline-runs/{run}

One pipeline run. Sealed.

Its record: state, version, hash, computeBundle, inputs, params, per-step status, runs, outputs, result, reason and cost (cost and costSoFar for a run with a cap). Sizes, hashes and results only for callers who may list the app's files. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
runpathstring

Answer (application/json)

{
  [key: string]: any
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/pipeline-runs/{run}/cancel

Cancel a pipeline run. Sealed.

The owner and the organization's members. Its pending steps end cancelled and its running steps' runs stop. Who: signed in (a session or an API key).

ParameterInType
apppathstring
runpathstring

Answer (application/json)

{
  run: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/pipeline-runs/{run}/events

A pipeline run as server-sent events. Sealed.

Whoever may read the run. Metadata only; at most 64 streams per app per node, and one lasts an hour. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
runpathstring

Answer (text/event-stream): Server-sent events: a snapshot, then run and step per change, then end, and the stream closes.

StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429TOO_MANY_SUBSCRIBERS

GET /apps/{app}/pipeline-runs/{run}/receipt

A pipeline run's receipt. Sealed.

The owner and the organization's members. For an ended run: the receipt, the answering node and its signature over it, by the node's receipt key. Who: signed in (a session or an API key).

ParameterInType
apppathstring
runpathstring

Answer (application/json)

{
  receipt: any,
  node: string,
  signature: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
409RUN_NOT_ENDED
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/pipeline-runs/{run}/retry

Retry a pipeline run. Sealed.

The owner and the organization's members. A new run of an ended run's pipeline at the same release, hash and compute component, with the same inputs and params, the limits applied and retryOf set. 202. Who: signed in (a session or an API key).

ParameterInType
apppathstring
runpathstring

Body (application/json)

{
  limits?: {
    [key: string]: {
      fuel?: integer,
      memoryMib?: integer,
      wallSecs?: integer
    }
  },
  maxCost?: string
}

Answer (application/json)

{
  run: string,
  retryOf: string,
  worstCase?: string
}
StatusCodes
400BAD_LIMITS; BAD_MAX_COST; LIMIT_EXCEEDS_CAP
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
409CLUSTER_NOT_UPGRADED; NO_PRICE_TABLE; STILL_RUNNING
410OUTPUT_EXPIRED
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429TOO_MANY_PIPELINE_RUNS

POST /apps/{app}/pipelines/{name}/estimate

Estimate a pipeline run. Sealed.

The owner and the organization's members. Runs, fuel and cost of a run of a pipeline the app's release registers, for inputs (file ids, only counted) or counts, not both; numbers as decimal strings. Who: signed in (a session or an API key).

ParameterInType
apppathstring
namepathstring

Body (application/json)

{
  inputs?: {
    [key: string]: string[]
  },
  counts?: {
    [key: string]: integer
  },
  params?: {
    [key: string]: any
  }
}

Answer (application/json)

{
  steps: {
    [key: string]: {
      runs: string,
      fuel: string,
      cost?: string
    }
  },
  fuel: string,
  cost?: string,
  priceVersion?: integer
}
StatusCodes
400BAD_INPUTS; BAD_PARAMS
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see; NO_SUCH_PIPELINE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/pipelines/{name}/runs

Start a pipeline run. Sealed.

The owner and the organization's members. Starts a run of a pipeline the app's release registers. maxCost (micro-units, a decimal string) caps the run, and worstCase answers it. 202. Who: signed in (a session or an API key).

ParameterInType
apppathstring
namepathstring

Body (application/json)

{
  inputs?: {
    [key: string]: string[]
  },
  params?: {
    [key: string]: any
  },
  maxCost?: string
}

Answer (application/json)

{
  run: string,
  worstCase?: string
}
StatusCodes
400BAD_INPUTS; BAD_MAX_COST; BAD_PARAMS
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see; NO_SUCH_PIPELINE
409CLUSTER_NOT_UPGRADED; NO_PRICE_TABLE
410OUTPUT_EXPIRED
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
422PIPELINES_NEED_ONE_SERVICE
429TOO_MANY_PIPELINE_RUNS

GET /apps/{app}/presence

Who is present. Sealed.

One entry per present device (a session's passkey, or an API key): its account, device and state (hex). Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring

Answer (application/json)

{
  present: {
    account: string,
    device: string,
    state: string | null
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/presence

Publish presence. Sealed.

The caller's presence state (hex), in sequence; not logged. A null (or absent) state retracts it. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring

Body (application/json)

{
  seq: integer,
  state?: string | null
}

Answer (application/json)

{}
StatusCodes
400BAD_STATE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
413TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/presence/stream

Presence as server-sent events. Sealed.

Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring

Answer (text/event-stream): Server-sent events: a snapshot, then presence diffs.

StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/runs

An app's compute runs. Sealed.

Newest first, limit (1 to 100, default 20) at a time; next is the before of the next page, null on the last. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
limit?querystring
before?querystring

Answer (application/json)

{
  runs: Run[],
  next: string | null
}
StatusCodes
400BAD_CURSOR; BAD_LIMIT
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/runs/{run}

One compute run. Sealed.

Its record without arguments or keys: method, state, cancelRequested, startTsMs, attempts, input and output ids (sizes and SHA-256 only for callers who may list the app's files), usage, and progress as the leader last polled it. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring
runpathstring

Answer (application/json)

Run
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/runs/{run}/logs

A compute run's attempt logs. Sealed.

Each attempt's module log, as a sealed file of the app: { attempt, id, size, sha256 }. Only for those who may handle the app's files; the bytes are a files export. Who: signed in (a session or an API key).

ParameterInType
apppathstring
runpathstring

Answer (application/json)

{
  logs: {
    attempt: integer,
    id: string,
    size: integer,
    sha256: string
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /apps/{app}/storage

What an app stores. Sealed.

Keys, bytes and blobs held, and lastWriteAt (Unix seconds of its last committed write, null before one). Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring

Answer (application/json)

{
  keys: integer,
  bytes: integer,
  blobs: integer,
  blobBytes: integer,
  lastWriteAt?: integer | null
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/transfer

Hand an app to another account. Sealed.

The owner (for an organization's app, while a member and in the app's team), or an organization admin; an organization's app only to a member. Answers null. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
apppathstring

Body (application/json)

{
  to: string,
  confirm?: Confirm
}

Answer (application/json)

null
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/upgrade

Upgrade an app instance. Sealed.

To a release (version, of the app's own package unless package names another) or a bundle, code only: the state stays and is read by the new code. Whoever the package's manifest names (upgrades: the owner, or its publisher's MANAGE_APPLICATION holders), with a step-up over { bundle, migrate, manifest }; an upgrade key signs in place of it. A refused or failed upgrade leaves the app on its release and answers 422 UPGRADE_FAILED with the app log's error in details (MigrationsNotSupported when migrate is named: there are no migrations in this version). error is the app log's error value (null when it ran), free-form: the app's own. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
apppathstring

Body (application/json)

{
  bundle?: string,
  package?: string,
  version?: string,
  service?: string,
  confirm?: Confirm,
  migrate?: string
}

Answer (application/json)

{
  index: integer,
  status: string,
  error: any,
  compute: boolean
}
StatusCodes
400AMBIGUOUS_COMPUTE; BAD_BUNDLE; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; VERSION_REQUIRED. details of BAD_BUNDLE: a ServiceRefused.
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409CONFLICT: the state does not allow it now; RELEASE_DEADLINE; RUNTIME_TOO_OLD. details of RELEASE_DEADLINE: a ReleaseDeadline, RUNTIME_TOO_OLD: a RuntimeTooOld.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
422UPGRADE_FAILED. details of UPGRADE_FAILED: a Applied.

GET /apps/{app}/usage

An app's runs per day. Sealed.

The owner or an organization admin: today and the 30 days before it, figures as decimal strings; wallMs is information only. Who: signed in (a session or an API key).

ParameterInType
apppathstring

Answer (application/json)

{
  today: UsageDay,
  days: UsageDay[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /apps/{app}/views

Read with a view method. Sealed.

Read linearizably (consistency: "strong", the default; any value but "stale" reads as it): the replica answering waits until it applied the index the app's leader names once it confirmed it leads, and sends the view to the leader if it cannot catch up; or ("stale") on the replica answering, as it stands; minIndex waits until the replica applied it (503 NOT_CAUGHT_UP). args, result and each event's data are the app's own JSON, free-form here: the app's ABI (GET /apps/{app}/abi, or its OpenAPI document) types them. Who: whoever the app's access admits (a public app: anyone).

ParameterInType
apppathstring

Body (application/json)

{
  method: string,
  args?: any,
  consistency?: "strong" | "stale",
  minIndex?: integer
}

Answer (application/json)

{
  index: integer,
  result: any,
  receipt: Receipt
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
422APP_ERROR; TRAP. details of APP_ERROR: a AppError, TRAP: a Trap.
503NOT_CAUGHT_UP; TIMEOUT. details of TIMEOUT: a RetryAfter.

GET /apps/{app}/xcalls

An app's cross-app calls. Sealed.

The owner or an organization admin: how many calls wait in its outbox for delivery (pending, a count), and its dead letters, oldest first (atMs: the entry time it was dead-lettered at, Unix milliseconds). Who: signed in (a session or an API key).

ParameterInType
apppathstring

Answer (application/json)

{
  pending: integer,
  deadLetters: DeadLetter[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
503UNAVAILABLE: the cluster cannot answer now

POST /pipelines/validate

Validate a pipeline. Sealed.

Every problem of source; with package and version (both, a release the caller sees) also against that release's methods, modules and the cluster's pools. Writes nothing. Who: signed in (a session or an API key).

Body (application/json)

{
  source: string,
  package?: string,
  version?: string
}

Answer (application/json)

{
  ok: boolean,
  errors: {
    path: string,
    code: string,
    message: string
  }[],
  pipeline?: any,
  worstCaseFuel?: string,
  worstCaseCost?: string
}
StatusCodes
400BAD_RELEASE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

Organizations

Organizations, members, teams, invites, approvals and upgrade runs.

POST /invites/{token}/redeem

Join with an invite. Sealed.

No passkey prompt: the node signs the redemption with the token's key. Answers the organization joined. Who: a passkey session (an API key is refused).

ParameterInType
tokenpathstring

Answer (application/json)

{
  org: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs

Create an organization. Sealed.

recoveryKey is the public half of an organization recovery key. Every account also has a personal organization from sign-up (personal in /auth/me), which this does not make. Who: a passkey session (an API key is refused).

Body (application/json)

{
  name: string,
  recoveryKey?: string
}

Answer (application/json)

{
  orgId: string
}
StatusCodes
400BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
429QUOTA_EXCEEDED

GET /orgs/{org}

One organization. Sealed.

As the directory records it, with only the teams the caller reaches or manages and the people they see; and its mode (from its app teams), the accounts that may approve its releases (releaseApprovers), the keys it publishes under (publishes), and newWorkStopped: the release whose passed deadline stops new work in it (after, RFC 3339), null when none does. Those four are absent from a node older than they are (1.0.0-rc.1 sends none of them). Who: signed in (a session or an API key).

ParameterInType
orgpathstring

Answer (application/json)

Org
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /orgs/{org}

Delete an organization. Sealed.

With its teams, invites and apps; the owner. apps: the apps deleted with it. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{
  apps: string[]
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/all-apps

Give a member every app added later. Sealed.

Or stop it (allApps: false); apps already there are not touched. The owner or an admin; 412 first. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  account: string,
  allApps: boolean,
  confirm?: Confirm
}

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /orgs/{org}/app-teams

The organization's app teams. Sealed.

A member: each app team's package, id, name, join, member count, default capabilities, and whether the caller is in it or manages it (a guest: only their own). Who: signed in (a session or an API key).

ParameterInType
orgpathstring

Answer (application/json)

{
  mode: "legacy" | "standalone" | "shared",
  appTeams: {
    package: string,
    teamId: string,
    name: string,
    join: TeamJoin,
    memberCount: integer,
    defaultCapabilities: integer | null,
    member: boolean,
    manages: boolean
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/app-teams

Give apps app teams, or open or close one. Sealed.

The owner or an admin; keep names who stays when a team closes; childTeams says whether the app team's members make restricted teams below it (private channels), adding or removing CREATE_CHILD_TEAM (absent: as they are). Naming join or childTeams on any package leaves shared unset to mean no other team. 412 first. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  apps?: {
    package: string,
    name?: string,
    instances?: string[],
    join?: TeamJoin,
    keep?: string[],
    childTeams?: boolean
  }[],
  shared?: boolean,
  confirm?: Confirm
}

Answer (application/json)

{
  mode: "legacy" | "standalone" | "shared",
  teams: {
    package: string,
    teamId: string,
    created: boolean,
    apps: string[],
    added: integer,
    join: TeamJoin | null,
    dropped: integer
  }[]
}
StatusCodes
400EXPIRED_CHALLENGE; TOO_MANY_PACKAGES; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /orgs/{org}/apps

The organization's apps. Sealed.

As GET /auth/apps, for the apps the caller reaches or manages; 404 to a non-member. Who: signed in (a session or an API key).

ParameterInType
orgpathstring
after?querystring
limit?queryinteger

Answer (application/json)

{
  scope: AppScope,
  governance: Governance,
  approvedReleases: string[] | null,
  clusterReleases: ClusterRelease[],
  apps: ReportApp[],
  next: string | null
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /orgs/{org}/backup-key

The organization's backup key. Sealed.

The X25519 public key its apps' recovery-disk backups are sealed to (key, null while none is set), and how many apps that covers. Any member; 404 outside the organization. Who: an account holder (a passkey session not bound to an app's frontend).

ParameterInType
orgpathstring

Answer (application/json)

BackupKeyAnswer
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/backup-key

Set the organization's backup key. Sealed.

publicKey: 64 lowercase hex, an X25519 public key whose private half its holder keeps (never a node). Those who upgrade all the organization's apps (org-wide MANAGE_APPLICATION), where owners upgrade apps; replaces the key before. 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  publicKey: string,
  confirm?: Confirm
}

Answer (application/json)

BackupKeyAnswer
StatusCodes
400BAD_BACKUP_KEY; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/capabilities

Set capabilities. Sealed.

A member's (account), in a team (team), or a team's default; the capability bits. 412 first. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  account?: string,
  team?: string,
  capabilities: integer,
  confirm?: Confirm
}

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /orgs/{org}/invites

The organization's invites. Sealed.

Their keys and terms, never a token: expiresAt Unix seconds; createdBy and createdAt are null on an invite from before they were kept. Who: a passkey session (an API key is refused).

ParameterInType
orgpathstring

Answer (application/json)

{
  invites: {
    inviteKey: string,
    role: OrgRole,
    teams: string[],
    usesLeft: integer,
    expiresAt: integer,
    expired: boolean,
    createdBy: string | null,
    createdAt: integer | null,
    allApps: boolean
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/invites

Make an invite. Sealed.

A token for role and teams, uses times within ttlSecs; allApps (an admin's) also gives every app added later. 412 first. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  role: OrgRole,
  teams?: string[],
  ttlSecs?: integer,
  uses?: integer,
  allApps?: boolean,
  confirm?: Confirm
}

Answer (application/json)

{
  token: string
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; WRONG_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /orgs/{org}/invites/{key}

Revoke an invite. Sealed.

Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring
keypathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /orgs/{org}/members

Members' lockout risk. Sealed.

detail=security (the only listing: without it, or with another value, 400 BAD_REQUEST), the owner or an admin: each member's passkeys (1, 2 or "3+"), recovery code, last active UTC day and sessions. 403 below admin, 404 outside the organization. Who: an account holder (a passkey session not bound to an app's frontend).

ParameterInType
orgpathstring
detail?query"security"

Answer (application/json)

{
  orgId: string,
  members: {
    account: string,
    name: string | null,
    role: OrgRole,
    teams: string[],
    passkeys: integer | "3+",
    recoveryCode: boolean,
    lastActiveDay: string | null,
    sessions: integer
  }[]
}
StatusCodes
400BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/members

Set a member's role. Sealed.

owner moves ownership. 412 first. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  account: string,
  role: OrgRole,
  confirm?: Confirm
}

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /orgs/{org}/members/{account}

Remove a member, or leave. Sealed.

412 first; the retry's JSON body is { confirm }. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring
accountpathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/members/{account}/metadata

Set a member's metadata. Sealed.

metadata is the caller's own JSON, free-form, kept as given. Who: signed in (a session or an API key).

ParameterInType
orgpathstring
accountpathstring

Body (application/json)

{
  metadata: any
}

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/members/{account}/teams

Set a member's rows in several teams. Sealed.

Each team judged as POST /orgs/{org}/teams/{team}/members would judge it, and none set unless every one may be (a row's absent role is member; absent capabilities, a new row takes the defaults and an existing row keeps its own). 1 to 64 distinct teams; one passkey, 412 first. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring
accountpathstring

Body (application/json)

{
  teams: {
    team: string,
    role?: TeamRole,
    capabilities?: integer
  }[],
  confirm?: Confirm
}

Answer (application/json)

{}
StatusCodes
400BAD_TEAMS; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /orgs/{org}/members/{account}/teams

Remove a member from several teams, or leave them. Sealed.

Each judged as DELETE /orgs/{org}/teams/{team}/members/{account} would judge it, and none taken unless every one may be. 1 to 64 distinct teams; one passkey, 412 first. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring
accountpathstring

Body (application/json)

{
  teams: string[],
  confirm?: Confirm
}

Answer (application/json)

{}
StatusCodes
400BAD_TEAMS; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/metadata

Set an organization's metadata. Sealed.

metadata is the caller's own JSON, free-form, kept as given. Who: signed in (a session or an API key).

ParameterInType
orgpathstring

Body (application/json)

{
  metadata: any
}

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/name

Rename an organization. Sealed.

The owner or an admin, to a name that fits as a new organization's would; 412 first. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  name: string,
  confirm?: Confirm
}

Answer (application/json)

{
  orgId: string,
  name: string
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/outbound

Approve outbound prefixes for the organization's apps. Sealed.

The owner; 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  package: string,
  prefixes?: OutboundSelection,
  replace?: boolean,
  confirm?: Confirm
}

Answer (application/json)

OutboundApproved
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/packages/{package}/upgrade

Upgrade every instance of a publisher's package. Sealed.

An upgrade run over every app on the cluster that runs the package, by its publisher's MANAGE_APPLICATION holders. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring
packagepathstring

Body (application/json)

{
  version: string,
  migrate?: string,
  confirm?: Confirm
}

Answer (application/json)

UpgradeRun
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/publishers

Bind a package signing key. Sealed.

The key's signature over the binding proves the organization holds it; then its MANAGE_APPLICATION holders upgrade the apps of packages that name publisher. Answers the key's binding generation now. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  signerId: string,
  publicKey: string,
  signature: string,
  confirm?: Confirm
}

Answer (application/json)

{
  generation: integer
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/recovery

Set the organization's recovery key. Sealed.

Set or rotate it (publicKey: base64url Ed25519 public key), or remove it (publicKey: null; an absent publicKey removes it too); the owner; cancels a recovery under way. 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  publicKey?: string | null,
  confirm?: Confirm
}

Answer (application/json)

{}
StatusCodes
400BAD_RECOVERY_KEY; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/recovery/cancel

Cancel an organization recovery. Sealed.

The owner; 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/recovery/finish

Finish an organization recovery. Sealed.

The account that started it, once readyAt passed; 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{
  org: string,
  previousOwners: string[]
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
409RECOVERY_NOT_READY. details of RECOVERY_NOT_READY: a RecoveryNotReady.
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/recovery/start

Start an organization recovery. Sealed.

The recovery seed's signature handing the organization to the caller. Who: an account holder (a passkey session not bound to an app's frontend).

ParameterInType
orgpathstring

Body (application/json)

{
  nonce: string,
  signature: string
}

Answer (application/json)

{
  startedAt: integer,
  readyAt: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only); WRONG_RECOVERY_KEY
409RECOVERY_PENDING
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/releases

Approve a mero-tee release for the organization's apps. Sealed.

The owner; 412 first. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  version: string,
  approved?: boolean,
  confirm?: Confirm
}

Answer (application/json)

ApprovedReleases
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/teams

Create a team. Sealed.

An admin, a lead of parent, a member with CREATE_TEAM at the top, or a member who holds CREATE_CHILD_TEAM under parent (a restricted team only). A package-bound session: only its own package's teams (its app team and the teams below it): parent one of them. Who: a passkey session (an API key is refused).

ParameterInType
orgpathstring

Body (application/json)

{
  name: string,
  parent?: string,
  join: TeamJoin
}

Answer (application/json)

{
  teamId: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /orgs/{org}/teams/{team}

One team. Sealed.

Who: signed in (a session or an API key).

ParameterInType
orgpathstring
teampathstring

Answer (application/json)

TeamView
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/teams/{team}

Update a team. Sealed.

Rename, open or restrict, move under another parent, or set its metadata (the caller's own JSON, free-form, kept as given). parent absent leaves the team where it is; parent: null (an explicit null) moves it to the top; a team id moves it under that team. A package-bound session: only its own package's teams (its app team and the teams below it): a team below its app team, moved only within. Who: a passkey session (an API key is refused).

ParameterInType
orgpathstring
teampathstring

Body (application/json)

{
  name?: string,
  join?: TeamJoin,
  parent?: string | null,
  metadata?: any
}

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /orgs/{org}/teams/{team}

Delete a team. Sealed.

With the teams and apps below it. A package-bound session: only its own package's teams (its app team and the teams below it): a team below its app team whose apps are all its package's. Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring
teampathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{
  teams: string[],
  apps: string[]
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/teams/{team}/members

Add or change a team member. Sealed.

A package-bound session: only its own package's teams (its app team and the teams below it). Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring
teampathstring

Body (application/json)

{
  account: string,
  lead?: boolean,
  role?: TeamRole,
  capabilities?: integer,
  confirm?: Confirm
}

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /orgs/{org}/teams/{team}/members/{account}

Remove a team member, or leave. Sealed.

A package-bound session: only its own package's teams (its app team and the teams below it). Who: a passkey session (an API key is refused). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring
teampathstring
accountpathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/upgrade

Start an upgrade run. Sealed.

Upgrade every app of the organization (or of team, with cascade its subtree) that runs package to version, with one passkey assertion over the whole run; whoever holds MANAGE_APPLICATION there. Each app is upgraded as POST /apps/{app}/upgrade would; GET /orgs/{org}/upgrades/{run} follows it. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
orgpathstring

Body (application/json)

{
  package: string,
  version: string,
  team?: string,
  cascade?: boolean,
  migrate?: string,
  confirm?: Confirm,
  operatorProof?: OperatorProof
}

Answer (application/json)

UpgradeRun
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /orgs/{org}/upgrades/{run}

An upgrade run's progress. Sealed.

A member of the organization. Who: signed in (a session or an API key).

ParameterInType
orgpathstring
runpathstring

Answer (application/json)

UpgradeRun
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /orgs/{org}/upgrades/{run}/retry

Retry an upgrade run's failed apps. Sealed.

As a new run under the same terms: a passkey step-up for a member's run, the operator's signature for an operator's run (with the ops token). Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
orgpathstring
runpathstring

Body (application/json, optional): May be absent.

{
  confirm?: Confirm,
  operatorProof?: OperatorProof
}

Answer (application/json)

UpgradeRun
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /orgs/{org}/usage

An organization's usage. Sealed.

An admin: how many apps the organization develops, what their runs used today (decimal strings) and the cluster's quotas; a member gets 403. Who: signed in (a session or an API key).

ParameterInType
orgpathstring

Answer (application/json)

{
  apps: integer,
  developerFuelToday: string /* decimal */,
  developerWritesToday: string /* decimal */,
  quotas: Quotas
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

Approvals an app's frontend asks for on the node's own consent page.

Ask the account's owner to approve. Sealed.

From an app's frontend: a release approval, an upgrade of its instance, outbound prefixes, a new organization, a new invite or joining with one, leaving an organization, a member's removal, role, teams or capabilities, an invite's revocation, an organization's name, its deletion, defaults or all-apps grants, approved on the node's own consent page (url), which takes the passkey. What the approval made (orgId, an invite's token, the org joined, a rename's { orgId, name }, a deletion's apps) is in /consent/{request}/result's outcome. 64 KiB at most. Who: a passkey session (an API key is refused).

Body (application/json)

{
  kind: "release",
  scope: "account" | {
    org: string
  },
  subject: {
    version: string,
    withdraw?: boolean
  },
  returnTo: string
} | {
  kind: "upgrade",
  subject: {
    app: string,
    toVersion: string
  },
  returnTo: string
} | {
  kind: "outbound",
  scope: "account" | {
    org: string
  },
  subject: {
    package?: string,
    prefixes?: string[]
  },
  returnTo: string
} | {
  kind: "createOrg",
  subject: {
    name: string
  },
  returnTo: string
} | {
  kind: "createInvite",
  subject: {
    org: string,
    role: "guest" | "member" | "admin",
    teams?: string[],
    ttlSecs?: integer,
    uses?: integer,
    allApps?: boolean
  },
  returnTo: string
} | {
  kind: "acceptInvite",
  subject: {
    token: string
  },
  returnTo: string
} | {
  kind: "leaveOrg",
  subject: {
    org: string
  },
  returnTo: string
} | {
  kind: "removeMember",
  subject: {
    org: string,
    account: string
  },
  returnTo: string
} | {
  kind: "setMemberRole",
  subject: {
    org: string,
    account: string,
    role: "guest" | "member" | "admin" | "owner"
  },
  returnTo: string
} | {
  kind: "setMemberTeams",
  subject: {
    org: string,
    account: string,
    teams: {
      team: string,
      role?: "lead" | "member" | "readOnly",
      capabilities?: integer
    }[]
  },
  returnTo: string
} | {
  kind: "removeMemberTeams",
  subject: {
    org: string,
    account: string,
    teams: string[]
  },
  returnTo: string
} | {
  kind: "revokeInvite",
  subject: {
    org: string,
    inviteKey: string
  },
  returnTo: string
} | {
  kind: "renameOrg",
  subject: {
    org: string,
    name: string
  },
  returnTo: string
} | {
  kind: "deleteOrg",
  subject: {
    org: string
  },
  returnTo: string
} | {
  kind: "setCapabilities",
  subject: {
    org: string,
    account?: string,
    team?: string,
    capabilities: integer
  },
  returnTo: string
} | {
  kind: "setAllApps",
  subject: {
    org: string,
    account: string,
    allApps: boolean
  },
  returnTo: string
}

Answer (application/json)

{
  requestId: string,
  url: string,
  code: string,
  expiresAt: integer
}
StatusCodes
400BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
413TOO_LARGE
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

What became of a consent request. Sealed.

decidedAt (Unix seconds) is null while it is pending. outcome, once approved, is what the approval made: { orgId } for createOrg (with teamId, the asking app's own team the organization starts with, when an app's frontend asked on a cluster that makes it), { token } for createInvite, { org } for acceptInvite, { orgId, name } for renameOrg, { apps } (the apps deleted) for deleteOrg; absent for the other kinds. Who: a passkey session (an API key is refused).

ParameterInType
requestpathstring

Answer (application/json)

{
  requestId: string,
  kind: "release" | "upgrade" | "outbound" | "createOrg" | "createInvite" | "acceptInvite" | "leaveOrg" | "removeMember" | "setMemberRole" | "setMemberTeams" | "removeMemberTeams" | "revokeInvite" | "renameOrg" | "deleteOrg" | "setCapabilities" | "setAllApps",
  status: "pending" | "approved" | "declined",
  decidedAt: integer | null,
  outcome?: {
    orgId?: string,
    teamId?: string,
    token?: string,
    org?: string,
    name?: string,
    apps?: string[]
  }
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)
503UNAVAILABLE: the cluster cannot answer now

Sign-up and deployments

The cluster's owner: the sign-up policy, deployers and deployments.

GET /deployers

The deployers. Sealed.

The operator, or the cluster's owner: the deployments and deployers governance, the owner (null until named), and every grant (until RFC 3339 and untilSecs, null for none; grantedAt RFC 3339; deployer null for a key it cannot read). Who: an account holder (a passkey session not bound to an app's frontend).

Answer (application/json)

{
  deployments: "open" | "granted",
  deployers: "operator" | "owner",
  owner: Deployer | null,
  grants: {
    key: string,
    deployer: Deployer | null,
    until: string | null,
    untilSecs: integer | null,
    grantedAt: string,
    grantedBy: string
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /deployers

Grant a deployer. Sealed.

The cluster's owner, with a passkey. Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  deployer: Deployer,
  until?: string,
  operatorProof?: OperatorProof,
  confirm?: Confirm
}

Answer (application/json)

{
  key: string,
  deployer: Deployer,
  grant: DeployerGrant
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /deployers/{key}

Revoke a deployer. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
keypathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{
  key: string
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /deployments

Deployments. Sealed.

The deployments the caller manages. Who: signed in (a session or an API key).

Answer (application/json)

{
  deployments: Deployment[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /deployments

Create a deployment. Sealed.

A named set of releases an owner (an account or organization) offers for others to instantiate. Answers its id, the record as made (no apps yet) and its frontend host (null on a node with no apps domain). Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  name: string,
  owner: Deployer,
  confirm?: Confirm
}

Answer (application/json)

{
  id: string,
  deployment: DeploymentRecord,
  host: string | null
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /deployments/{id}

One deployment. Sealed.

As anyone may read it: its name, its owner's kind and name (null when unknown), and the releases it offers; never its managers or customers. Who: signed in (a session or an API key).

ParameterInType
idpathstring

Answer (application/json)

{
  id: string,
  host: string | null,
  name: string,
  owner: {
    kind: "account" | "org",
    name: string | null
  },
  apps: {
    app: string,
    package: string,
    version: string
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
404NOT_FOUND: no such object, or one the caller may not see
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /deployments/{id}

Delete a deployment. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
idpathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{
  deployment: string
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /deployments/{id}/apps

Offer a release in a deployment. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
idpathstring

Body (application/json)

{
  app: string,
  package: string,
  version: string,
  confirm?: Confirm
}

Answer (application/json)

{
  deployment: string,
  app: string
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /deployments/{id}/apps/{app}

Withdraw an offer. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
idpathstring
apppathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

{
  deployment: string,
  app: string
}
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /deployments/{id}/orgs

The organizations a deployment serves. Sealed.

For its managers: each organization with instances from it, its name (null when unknown), member counts (activeMembers30d: active in the last 30 days), its instances and the releases they run, and when its first was created (RFC 3339); instances outside an organization, or in a personal organization, are only counted (outsideOrgs). Never who the members are. Who: signed in (a session or an API key).

ParameterInType
idpathstring

Answer (application/json)

{
  deployment: string,
  orgs: {
    orgId: string,
    name: string | null,
    memberCount: integer,
    activeMembers30d: integer,
    instances: integer,
    apps: {
      app: string,
      version: string
    }[],
    firstCreatedAt: string
  }[],
  outsideOrgs: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /sign-up

The sign-up policy. Sealed.

Who may create an account here, the cluster's name and the tag a sign-in uses to pick the person's passkey for it. Who: anyone.

Answer (application/json)

{
  policy: SignUp,
  orgInvites: boolean,
  signUpInvites: boolean,
  inviteRequired: boolean,
  cluster: string,
  passkeyTag: string
}

POST /sign-up

Set the sign-up policy. Sealed.

The cluster's owner, once named, with a passkey (412 first). Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  policy: SignUp,
  operatorProof?: OperatorProof,
  confirm?: Confirm
}

Answer (application/json)

SignUpSet
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

GET /sign-up/invites

Cluster sign-up invites. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend).

Answer (application/json)

{
  signUp: {
    policy: SignUp,
    orgInvites: boolean,
    signUpInvites: boolean,
    inviteRequired: boolean
  },
  runBy: "owner" | "operator",
  invites: SignUpInvite[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

POST /sign-up/invites

Issue a cluster sign-up invite. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

Body (application/json)

{
  uses?: integer,
  ttlSecs?: integer,
  confirm?: Confirm
}

Answer (application/json)

{
  token: string,
  inviteKey: string,
  uses: integer,
  expiresAt: string,
  expiresAtSecs: integer,
  createdBy: string,
  createdAt: string
}
StatusCodes
400BAD_REQUEST: the request is malformed; EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE; WRONG_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

DELETE /sign-up/invites/{key}

Withdraw a cluster sign-up invite. Sealed.

Who: an account holder (a passkey session not bound to an app's frontend). Step-up: answers 412 CONFIRM_REQUIRED first; send the same request again with confirm, a passkey assertion over details.challenge.

ParameterInType
keypathstring

Body (application/json, optional): May be absent.

ConfirmOnly

Answer (application/json)

InviteKey
StatusCodes
400EXPIRED_CHALLENGE; UNKNOWN_CHALLENGE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
412CONFIRM_REQUIRED: a passkey assertion is needed; details carries the challenge. details of CONFIRM_REQUIRED: a ConfirmRequired.
421WRONG_NODE: this node runs a release the account's owners have not approved, so it neither issues nor takes the account's sessions; send it to another node of the cluster (no details; nothing was spent)

Ops

The operator's routes: every one needs the ops token; decisions are signed with the operator key.

GET /ops/apps

What each app runs. Sealed.

Each app's bundle, package, publisher, who holds its upgrades and release approvals, its last upgrade, approved releases, replicas' releases and lastWriteAt. Who: the ops token.

ParameterInType
after?querystring
limit?queryinteger

Answer (application/json)

{
  fresh: boolean,
  governance: Governance,
  apps: ReportApp[],
  next: string | null
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/apps/{app}/replicas

Move an app's replicas. Sealed.

Signed over <app> / __set_replicas / { replicas } (sorted); at least min(3, nodes) registered nodes, each on a release the app's owner approved. The set it already has answers unchanged: true. status is the app group's Raft status when the move finished (as the leader saw it). Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
apppathstring

Body (application/json)

{
  replicas: integer[],
  operatorProof?: OperatorProof
}

Answer (application/json)

{
  status: {
    group: integer,
    leader: integer | null,
    is_leader: boolean,
    term: integer,
    last_log: integer | null,
    applied: integer,
    voters: integer[],
    learners: integer[]
  },
  unchanged: boolean
}
StatusCodes
400DUPLICATE_REPLICA; JOB_NODE; TOO_FEW; UNKNOWN_NODE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409MOVE_IN_PROGRESS; RUNTIME_TOO_OLD. details of RUNTIME_TOO_OLD: a RuntimeTooOld.
421NOT_LEADER: send it to the leader named in details.leaderUrl. details of NOT_LEADER: a NotLeader.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/apps/{app}/restore

Restore an app from its sealed backup. Sealed.

Signed over <app> / __restore_app / { backup, sha256 }. The receiving node holds the backup (backup, else the newest, in {backup-dir}/{app}/) and seeds the restore; answers once every replica holds the restored state: the rows restored, the backup (format 0, with merod and release null, for one written before manifests) and the app group's Raft status. recovery restores from a recovery-disk file instead (in the app's holder's directory under --recover-from, else --recovery-dir), opened with the data key its holder opened from it (hex); backup is then the file's name and sha256 its body's. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
apppathstring

Body (application/json)

{
  backup?: string,
  recovery?: {
    file: string,
    key: string
  },
  operatorProof?: OperatorProof
}

Answer (application/json)

{
  app: string,
  group: integer,
  rows: integer,
  backup: {
    name: string,
    index: integer,
    format: integer,
    merod: string | null,
    release: string | null
  },
  status: GroupStatus
}
StatusCodes
400BAD_BACKUP; BAD_RECOVERY_FILE; BAD_RECOVERY_KEY; BAD_REQUEST: the request is malformed; NOT_A_REPLICA_NODE; UNATTESTED_RECOVERY_FILE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404BACKUP_NOT_FOUND
409BACKUP_FROM_NEWER_RELEASE; BUNDLE_GONE; MOVE_IN_PROGRESS; NO_BACKUP_DIR; RECOVERY_SEGMENTS_MISSING; UNKNOWN_BACKUP_FORMAT; UPGRADE_PENDING. details of UPGRADE_PENDING: a UpgradePending.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/apps/{app}/upgrade

Upgrade an app as the operator. Sealed.

To a release the operator installed, where the operator holds app upgrades. error is the app log's error value (null when it ran), free-form: the app's own. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
apppathstring

Body (application/json)

{
  bundle?: string,
  package?: string,
  version?: string,
  service?: string,
  migrate?: string,
  operatorProof?: OperatorProof
}

Answer (application/json)

{
  index: integer,
  status: string,
  error: any,
  compute: boolean
}
StatusCodes
400AMBIGUOUS_COMPUTE; BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409NOT_INSTALLED; RELEASE_DEADLINE; RUNTIME_TOO_OLD. details of RELEASE_DEADLINE: a ReleaseDeadline, RUNTIME_TOO_OLD: a RuntimeTooOld.
422UPGRADE_FAILED. details of UPGRADE_FAILED: a Applied.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/backup

Snapshot the apps this node leads. Sealed.

Into --backup-dir. With all=true, every group this node holds, leader or not: what a node of a cluster that lost a majority still has, to found the cluster again from (merod --bootstrap --restore-from). written: how many snapshots it wrote. Who: the ops token.

ParameterInType
all?queryboolean

Answer (application/json)

{
  written: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

GET /ops/backup-key

The operator's backup key. Sealed.

The X25519 public key every app's recovery-disk backups are sealed to where the operator upgrades apps (key, null while none is set). Who: the ops token.

Answer (application/json)

BackupKeyAnswer
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/backup-key

Set the operator's backup key. Sealed.

Signed over operator / __set_backup_key / { publicKey }, where the operator upgrades apps (else 403). publicKey: 64 lowercase hex, an X25519 public key whose private half the operator keeps (never a node). Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  publicKey: string,
  operatorProof?: OperatorProof
}

Answer (application/json)

BackupKeyAnswer
StatusCodes
400BAD_BACKUP_KEY
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409FEATURE_NOT_ACTIVE. details of FEATURE_NOT_ACTIVE: a FeatureNotActive.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/cluster

The cluster's identity. Sealed.

The cluster's name and the identity this replica holds (hex). Who: the ops token.

Answer (application/json)

{
  cluster: string,
  identity: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/cluster-owner

Name the cluster's owner. Sealed.

The account or organization that then runs sign-up and deployers with passkeys; once. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  owner: Deployer,
  operatorProof?: OperatorProof
}

Answer (application/json)

{
  owner: Deployer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409CONFLICT: the state does not allow it now
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/deployers

Grant a deployer. Sealed.

An account or organization that may install where deployments are granted, until an RFC 3339 time. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  deployer: Deployer,
  until?: string,
  operatorProof?: OperatorProof,
  confirm?: Confirm
}

Answer (application/json)

{
  key: string,
  deployer: Deployer,
  grant: DeployerGrant
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

DELETE /ops/deployers/{key}

Revoke a deployer. Sealed.

Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
keypathstring

Body (application/json, optional): May be absent.

ProofOnly

Answer (application/json)

{
  key: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/deployers/{key}/revoke

Revoke a deployer (POST). Sealed.

The same as the DELETE, for an HTTP client whose DELETE carries no body. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
keypathstring

Body (application/json, optional): May be absent.

ProofOnly

Answer (application/json)

{
  key: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/deployments/granted

Require deployer grants. Sealed.

From now on only granted deployers install; once. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json, optional): May be absent.

ProofOnly

Answer (application/json)

{
  governance: Governance
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409CONFLICT: the state does not allow it now
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/job-nodes/{id}/attestation

Whether the cluster accepts a job node. Sealed.

Runs the check the leader makes before it sends a job node work: a quote that passes the release policy, this cluster and node, this cluster's identity, a release not retired (not the per-app release approval). admitted carries the attested release; refused (final), with the reason: a 400 or 404 from the node, a 2xx that is oversized or does not decode, a failed verification, or a 400 or 404 from the collateral source on the PCK certificate or TCB info request; unreachable (transient), with the reason: anything else, including no answer, any other status from the node and any other collateral failure. 503 when this node's directory is stale. A verified answer is reused for up to a minute. Who: the ops token.

ParameterInType
idpathstring

Answer (application/json)

{
  state: "admitted",
  node: integer,
  release: string
} | {
  state: "refused" | "unreachable",
  node: integer,
  reason: string
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
503UNAVAILABLE: the cluster cannot answer now

GET /ops/metrics

Prometheus metrics. Sealed.

Including per-app usage for billing. --metrics-listen ADDR also serves it as plain GET /metrics there. Who: the ops token.

Answer (text/plain): OK: the Prometheus text format.

StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/nodes

Register a node. Sealed.

Signed with the operator key over cluster / __register_node / { id, addr, zone }. The system leader adds it as a learner and promotes caught-up learners while fewer than 3 voters are left; role: job registers a compute node (in pool). Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  id: integer,
  addr: string,
  zone?: string,
  operatorProof?: OperatorProof,
  role?: "replica" | "job",
  pool?: string
}

Answer (application/json)

{}
StatusCodes
400BAD_ADDRESS; BAD_POOL; NODE_HOLDS_CLUSTER; POOL_FOR_JOB_NODES
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409ADDRESS_TAKEN
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

DELETE /ops/nodes/{id}

Remove a node. Sealed.

One no app keeps a replica on; the system leader (elsewhere 421 NOT_LEADER); signed over __remove_node / { id }. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
idpathstring

Body (application/json, optional): May be absent.

ProofOnly

Answer (application/json)

{
  status: {
    group: integer,
    leader: integer | null,
    is_leader: boolean,
    term: integer,
    last_log: integer | null,
    applied: integer,
    voters: integer[],
    learners: integer[]
  }
}
StatusCodes
400LAST_NODE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
421NOT_LEADER: send it to the leader named in details.leaderUrl. details of NOT_LEADER: a NotLeader.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/nodes/{id}/receipt-key

A node's receipt key. Sealed.

Who: the ops token.

ParameterInType
idpathstring

Answer (application/json)

{
  node: integer,
  key: string,
  release: string,
  attestedAt: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see

GET /ops/orgs

Each organization's approved releases. Sealed.

Who: the ops token.

ParameterInType
after?querystring
limit?queryinteger

Answer (application/json)

{
  fresh: boolean,
  governance: Governance,
  orgs: {
    org: string,
    approvedReleases: string[] | null
  }[],
  next: string | null
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/orgs/{org}/upgrade

An operator's upgrade run. Sealed.

Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
orgpathstring

Body (application/json)

{
  package: string,
  version: string,
  team?: string,
  cascade?: boolean,
  migrate?: string,
  confirm?: Confirm,
  operatorProof?: OperatorProof
}

Answer (application/json)

UpgradeRun
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
404NOT_FOUND: no such object, or one the caller may not see
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/outbound

Approve outbound prefixes. Sealed.

Where the operator holds outbound approvals. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  package: string,
  prefixes?: OutboundSelection,
  replace?: boolean,
  operatorProof?: OperatorProof
}

Answer (application/json)

OutboundApproved
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/packages

The releases the operator installed. Sealed.

Who: the ops token.

Answer (application/json)

{
  packages: Package[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/packages

Install an uploaded release as the operator. Sealed.

Who: the ops token.

Body (application/octet-stream): the .mpk

Answer (application/json)

{
  package: string,
  version: string,
  signerId: string,
  services: {
    [key: string]: string
  }
}
StatusCodes
400BAD_BUNDLE; BAD_PACKAGE; COMPUTE_ABI_MISMATCH; UNSUPPORTED_BUNDLE. details of BAD_BUNDLE: a ServiceRefused, COMPUTE_ABI_MISMATCH: a ServiceRefused, UNSUPPORTED_BUNDLE: a ServiceRefused.
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/packages/install

Install a release from the registry as the operator. Sealed.

Who: the ops token.

Body (application/json)

{
  package: string,
  version: string
}

Answer (application/json)

{
  package: string,
  version: string,
  signerId: string,
  services: {
    [key: string]: string
  }
}
StatusCodes
400BAD_BUNDLE; COMPUTE_ABI_MISMATCH; UNSUPPORTED_BUNDLE. details of BAD_BUNDLE: a ServiceRefused, COMPUTE_ABI_MISMATCH: a ServiceRefused, UNSUPPORTED_BUNDLE: a ServiceRefused.
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

DELETE /ops/packages/{package}

Uninstall what the operator installed. Sealed.

Who: the ops token.

ParameterInType
packagepathstring

Answer (application/json)

Uninstalled
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

DELETE /ops/packages/{package}/{version}

Uninstall one operator-installed version. Sealed.

Who: the ops token.

ParameterInType
packagepathstring
versionpathstring

Answer (application/json)

Uninstalled
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

GET /ops/placement

Where every app's replicas are. Sealed.

Ids and counts only, read after a read index (fresh: this node caught up with the system leader); release is a node's attested release; clusterVersion is the logged cluster version (null until the system leader logs one). Who: the ops token.

Answer (application/json)

{
  fresh: boolean,
  apps: {
    app: string,
    group: integer,
    replicas: integer[]
  }[],
  nodes: {
    id: integer,
    zone: string,
    role: NodeRole,
    release: string | null,
    apps: integer
  }[],
  clusterVersion: string | null
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

GET /ops/pools

Compute pools. Sealed.

The pools by name (absent: none set, one legacy pool), and each pool's capacity: how many runs its job nodes take at once. Who: the ops token.

Answer (application/json)

{
  pools: {
    [key: string]: {
      runsPerNode: integer,
      maxMemoryMib: integer
    }
  },
  capacity: {
    [key: string]: integer
  }
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/pools

Set the compute pools. Sealed.

Signed over cluster / __set_pools / { pools }; POOL_IN_USE when a pool to remove still has job nodes or runs. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  pools: {
    [key: string]: {
      runsPerNode: integer,
      maxMemoryMib: integer
    }
  },
  operatorProof?: OperatorProof
}

Answer (application/json)

{}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409POOL_IN_USE; UPGRADE_PENDING. details of UPGRADE_PENDING: a UpgradePending.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/prices

The price table. Sealed.

In micro-units of the billing currency; {} until one is set. Who: the ops token.

Answer (application/json)

{
  version?: integer,
  fuelPerVcpuSecond?: integer,
  vcpuSecond?: integer,
  gibSecond?: integer,
  connectorGib?: integer,
  storageGibMonth?: integer,
  egressGib?: integer
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/prices

Set the price table. Sealed.

Signed over cluster / __set_price_table / { table }; PRICE_VERSION unless version is the current one plus one (1 for the first), BAD_PRICES for a zero fuelPerVcpuSecond. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  table: {
    version: integer,
    fuelPerVcpuSecond: integer,
    vcpuSecond: integer,
    gibSecond: integer,
    connectorGib: integer,
    storageGibMonth: integer,
    egressGib: integer
  },
  operatorProof?: OperatorProof
}

Answer (application/json)

{}
StatusCodes
400BAD_PRICES
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409PRICE_VERSION; UPGRADE_PENDING. details of UPGRADE_PENDING: a UpgradePending.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/quotas

The quotas. Sealed.

The per-account quotas, and the per-payer overrides under orgs. Who: the ops token.

Answer (application/json)

QuotaSettings
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/quotas

Change quotas. Sealed.

Changes the limits the body names, the others keep their value; signed over cluster / __set_quotas / { quotas } with every limit after the change. Without org, the cluster's limits (GET /ops/quotas names them); orgs, which that answer carries, is ignored, so its answer may be sent back changed. With org: one payer's maxConcurrentRuns, computeFuel (decimal string) and maxFileBytes (null clears one, back to the cluster's), and no other limit. A property that is no limit (of the cluster's, or with org of a payer's) is refused 400 UNKNOWN_QUOTA. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

QuotaChanges

Answer (application/json)

{}
StatusCodes
400BAD_REQUEST: the request is malformed; UNKNOWN_QUOTA
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409UPGRADE_PENDING. details of UPGRADE_PENDING: a UpgradePending.
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/recover

Found the cluster again from its recovery disk. Sealed.

On the founder started with --bootstrap --recover-from DIR, its system state empty: the newest system file in DIR/operator/ and the apps' code files, each with the data key the operator opened from it (hex). Checked as founding from backups is (governance, operator key, no node of the old cluster answering), then the system group is seeded; each app waits for POST /ops/apps/{app}/restore { recovery }. Who: the ops token.

Body (application/json)

{
  system: {
    file: string,
    key: string
  },
  code?: {
    file: string,
    key: string
  }[]
}

Answer (application/json)

{
  apps: integer,
  accounts: integer,
  index: integer
}
StatusCodes
400BAD_RECOVERY_FILE; BAD_RECOVERY_KEY; TOO_MANY_FILES; UNATTESTED_RECOVERY_FILE
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409NOT_RECOVERING; OLD_CLUSTER_ANSWERS; OTHER_DEPLOYMENT

GET /ops/recovery-files

The recovery files a node reads. Sealed.

In --recover-from, else --recovery-dir, of holder (operator, the default; org:<id>; account:<id>): each file's name, its header as signed (JSON text) and the node's Ed25519 signature over calimero.recovery-backup.v1\0 and those bytes (hex), for the holder's device to check before it opens a key with its own. Who: the ops token.

ParameterInType
holder?querystring

Answer (application/json)

{
  holder: any,
  files: {
    name: string,
    header: string,
    signature: string
  }[]
}
StatusCodes
400BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
409NO_BACKUP_DIR

POST /ops/releases

Approve a mero-tee release for every app. Sealed.

Where the operator holds release approvals. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  version: string,
  approved?: boolean,
  operatorProof?: OperatorProof
}

Answer (application/json)

ApprovedReleases
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/releases/{version}/deadline

Set a release deadline. Sealed.

After after (RFC 3339), apps whose approver has not moved past the release may start no new work. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
versionpathstring

Body (application/json)

{
  after?: string,
  operatorProof?: OperatorProof
}

Answer (application/json)

Deadlines
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

DELETE /ops/releases/{version}/deadline

Lift a release deadline. Sealed.

Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
versionpathstring

Body (application/json, optional): May be absent.

ProofOnly

Answer (application/json)

Deadlines
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/served-origins

Custom domains to serve. Sealed.

Every served origin a package's manager registered, by the package's label, never its name; addedAt is RFC 3339. Who: the ops token.

Answer (application/json)

{
  fresh: boolean,
  origins: {
    origin: string,
    host: string,
    label: string,
    addedAt: string
  }[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/sign-up

Set the sign-up policy. Sealed.

Refused once the cluster's owner runs sign-up. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  policy: SignUp,
  operatorProof?: OperatorProof,
  confirm?: Confirm
}

Answer (application/json)

SignUpSet
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/sign-up/invites

Cluster sign-up invites. Sealed.

Who: the ops token.

Answer (application/json)

{
  signUp: {
    policy: SignUp,
    orgInvites: boolean,
    signUpInvites: boolean,
    inviteRequired: boolean
  },
  runBy: "owner" | "operator",
  invites: SignUpInvite[]
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

POST /ops/sign-up/invites

Issue a cluster sign-up invite. Sealed.

Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

Body (application/json)

{
  token: string,
  uses?: integer,
  expiresAt: string,
  operatorProof?: OperatorProof
}

Answer (application/json)

SignUpInvite
StatusCodes
400BAD_REQUEST: the request is malformed
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

DELETE /ops/sign-up/invites/{key}

Withdraw a cluster sign-up invite. Sealed.

Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
keypathstring

Body (application/json, optional): May be absent.

ProofOnly

Answer (application/json)

InviteKey
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

POST /ops/sign-up/invites/{key}/revoke

Withdraw a cluster sign-up invite (POST). Sealed.

For an HTTP client whose DELETE carries no body. Who: the ops token. Operator signature: answers 428 OPERATOR_SIGNATURE_REQUIRED first; send it again with operatorProof, the operator key's signature over details.message and its nonce.

ParameterInType
keypathstring

Body (application/json, optional): May be absent.

ProofOnly

Answer (application/json)

InviteKey
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403BAD_OPERATOR_SIGNATURE; FORBIDDEN: the credential may not do this (scope, role, governance, read-only)
428OPERATOR_SIGNATURE_REQUIRED: the operator key must sign the decision; details names the statement. details of OPERATOR_SIGNATURE_REQUIRED: a OperatorSignatureRequired.

GET /ops/status

The node and the cluster. Sealed.

Counts, Raft status and governance; never app state, names or credentials. groups: the app groups this node hosts; apps and accounts are counts; rollback is this node's rollback counter, null on a node without one. Who: the ops token.

Answer (application/json)

{
  node: integer,
  system: GroupStatus,
  governance: Governance,
  groups: {
    app: string,
    status: GroupStatus
  }[],
  nodes: NodeRecord[],
  apps: integer,
  accounts: integer,
  rollback: RollbackStatus | null
}
StatusCodes
401UNAUTHENTICATED: no, unknown, expired or revoked credential
403FORBIDDEN: the credential may not do this (scope, role, governance, read-only)

Schemas

Error

An error answer: error is the code. details, absent for most codes, has the schema x-calimero-details names for the code on the operation's response (every code's: x-calimero-error-details at the document's root); a code it names no schema for carries none, or a value clients need not read.

{
  status: integer,
  error: string,
  message: string,
  details?: any
}

Confirm

A passkey assertion over the challenge a 412 CONFIRM_REQUIRED named: the same request sent again with it approves exactly that request.

{
  challengeId: string,
  assertion: Assertion
}

ConfirmRequired

details of a 412 CONFIRM_REQUIRED: the WebAuthn challenge to sign under rpId with one of the passkeys allowCredentials names (credential ids; empty: any of the account's), and the challengeId the retry's confirm names. apps: deleting a team that holds apps, the apps that go with it.

{
  challengeId: string,
  challenge: string,
  rpId: string,
  allowCredentials: string[],
  apps?: string[]
}

OperatorProof

The operator key's Ed25519 signature (hex) over the statement a 428 OPERATOR_SIGNATURE_REQUIRED named, with that statement's nonce.

{
  nonce: string,
  signature: string
}

OperatorSignatureRequired

details of a 428 OPERATOR_SIGNATURE_REQUIRED: the statement to sign (args is the JSON text of its arguments, as signed) and the exact bytes to sign (message, standard base64).

{
  subject: string,
  method: string,
  args: string,
  nonce: string,
  cluster: string,
  message: string
}

Assertion

The browser's answer to navigator.credentials.get, each field base64url.

{
  credentialId: string,
  authenticatorData: string,
  clientDataJson: string,
  signature: string
}

Registration

The browser's answer to navigator.credentials.create, each field base64url.

{
  attestationObject: string,
  clientDataJson: string
}

Session

A session: its token (15 minutes, by the issuing node) and the refresh token for /auth/refresh.

{
  accountId: string,
  sessionToken: string,
  expiresAt: integer,
  refreshToken: string
}

BackupKeyAnswer

A holder's backup key: who holds it ({ kind: "operator" }, { kind: "org", id } or { kind: "account", id }), the X25519 public key the recovery disk seals their apps' backups to (null while none is set), and how many apps that covers.

{
  holder: {
    kind: "operator" | "org" | "account",
    id?: string
  },
  key: {
    publicKey: string,
    setAt: integer,
    setBy: string
  } | null,
  apps: integer
}

Applied

An entry an app's log applied: its index, how it ended and the app's error (null when it ended ok; the app's own error value otherwise, free-form). details of a 422 UPGRADE_FAILED.

{
  index: integer,
  status: "ok" | "appError" | "trap",
  error: any
}

NotLeader

details of a 421 NOT_LEADER: the leader's URL to send the same request to, and its node id where known.

{
  leaderUrl: string,
  leader?: integer
}

FeatureNotActive

details of a 409 FEATURE_NOT_ACTIVE: the feature the request needs, the cluster version it ships in (needs) and the version active now (null: none logged, and the nodes could not say).

{
  feature: string,
  needs: string,
  active: string | null
}

RuntimeTooOld

details of a 409 RUNTIME_TOO_OLD: the runtime the release needs and the replicas known to fall short of it, each with what it runs (a version, or { before }: a release older than that one).

{
  minRuntimeVersion: string,
  nodes: {
    node: integer,
    runtime: string | {
      before: string
    }
  }[]
}

ReleaseDeadline

details of a 409 RELEASE_DEADLINE: the mero-tee release whose deadline passed, and the deadline (after RFC 3339, afterSecs Unix seconds). Approving that release (or a newer one) lifts it.

{
  release: string,
  after: string,
  afterSecs: integer
}

UpgradePending

details of a 409 UPGRADE_PENDING: the release every node must run first, and the nodes that run an older one (release null: one this node could not attest).

{
  release: string,
  nodes: {
    node: integer,
    release: string | null
  }[]
}

AppError

details of a 422 APP_ERROR: the app's error code, its fields (the app's own value, free-form: the object its ABI declares for the error, or the app's message as a string when that is not JSON), and the log index of the call (absent when the node refused it before it ran: UnknownMethod, WrongKind, Forbidden, ConfirmNotAView, NotAView, ConfirmRequired).

{
  index?: integer,
  code: string,
  fields: any
}

Trap

details of a 422 TRAP: the log index of the run, how it trapped, and the engine's account of it.

{
  index: integer,
  kind: "OutOfFuel" | "Timeout" | "Cancelled" | "Unavailable" | "OutOfMemory" | "StackOverflow" | "Fault" | "HostDenied",
  detail: string
}

InitFailed

details of a 422 INIT_FAILED: the app made, and the error its init ended with (the app log's, free-form).

{
  appId: string,
  error: any
}

RecoveryNotReady

details of a 409 RECOVERY_NOT_READY: when the recovery may finish (Unix seconds).

{
  readyAt: integer
}

UploadPosition

details of a 409 PART_CONFLICT, 409 PART_OUT_OF_ORDER or 409 UPLOAD_INCOMPLETE: the part the upload expects next.

{
  next: integer
}

RetryAfter

details of a 503 TIMEOUT or 503 FILES_UNAVAILABLE: the seconds to wait before sending the same request (with the same idempotency key) again.

{
  retryAfter: integer
}

ServiceRefused

details of a 400 UNSUPPORTED_BUNDLE, 400 BAD_BUNDLE or 400 COMPUTE_ABI_MISMATCH refusing one service of a release: the service, and compute: true when it was that service's compute component. Absent when the refusal is of a raw bundle.

{
  service: string,
  compute?: boolean
}

SealedRefusal

The sealed channel's own refusal, outside the envelope and in the clear: not an Error. busy (503, with Retry-After: 1): too many sealed requests or sessions at once, send it again; the other codes (400, malformed and the like) say the envelope could not be opened.

{
  error: {
    code: string,
    message: string
  }
}

Receipt

The answering node's signature (receipt key, hex) over (app, index, SHA-256(JCS(result)), node).

{
  app: string,
  index: integer,
  resultHash: string,
  node: integer,
  key: string,
  signature: string
}

Access

Who may reach an app at all.

{
  kind: "owner"
} | {
  kind: "org"
} | {
  kind: "public"
} | {
  kind: "accounts",
  accounts: string[]
} | {
  kind: "team",
  team: string
}

OrgRole

A member's role in an organization.

"guest" | "member" | "admin" | "owner"

TeamRole

A member's standing in one team.

"lead" | "member" | "readOnly"

TeamJoin

Open (everyone who reaches the parent) or restricted (invite) membership.

"everyone" | "invite"

OutboundSelection

manifest (every prefix the release declares) or these prefixes.

"manifest" | string[]

Deployer

An account or an organization.

{
  account: string
} | {
  org: string
}

SignUp

The cluster's sign-up policy.

"open" | "invite" | "closed"

Page

A page of a list: next is the after of the next page, null on the last.

{
  next: string | null
}

Release

A mero-tee release.

{
  version: string,
  profile: string
}

AttestationDoc

A node's attestation: the TDX quote (base64), the key it binds (hex) and what it was asked for. receiptKey and governance with purpose=receipts, kms with purpose=kms on a node with a KMS record, clusterIdentity with purpose=orchestrator; jobKey only from a job node, never from this API.

{
  quote: string,
  transportKey: string,
  appHash: string,
  nonce: string,
  release: Release,
  cluster: string,
  node: integer,
  mock: boolean,
  receiptKey?: string,
  governance?: Governance,
  kms?: KmsKeys,
  jobKey?: string,
  clusterIdentity?: string
}

KmsKeys

What a node verified of the mero-kms replicas it took its keys from: the storage key merod fetched, and the data disk's key the boot script fetched; each absent without a record.

{
  storage?: KmsEvidence,
  disk?: KmsEvidence
}

KmsEvidence

The KMS quote a node accepted a key under: the KMS host, the mero-kms release (and image profile) whose signed policy it matched, the quote's registers (hex), its TCB status, SHA-256 and when it was verified (Unix seconds); mock (absent: false) in development builds only.

{
  kmsHost: string,
  release: string,
  profile?: string,
  mrtd: string,
  rtmr0: string,
  rtmr1: string,
  rtmr2: string,
  rtmr3: string,
  tcbStatus?: string,
  quoteSha256: string,
  verifiedAt: integer,
  mock?: boolean
}

GroupStatus

A Raft group's status as one node sees it: the leader (null: none known), whether this node is it, the term, the last log index (null: an empty log), the applied index, and the voters and learners.

{
  group: integer,
  leader: integer | null,
  is_leader: boolean,
  term: integer,
  last_log: integer | null,
  applied: integer,
  voters: integer[],
  learners: integer[]
}

RollbackStatus

A node's rollback counter: the cluster's epoch (rollbacks forced so far), its generation and mark, whether this start was forced (--accept-rollback), and the seconds since mero-kms last acknowledged a checkpoint.

{
  epoch: integer,
  generation: integer,
  mark: integer,
  forced: boolean,
  sinceCheckpointSecs: integer
}

NodeRole

What a node does: hold app replicas, or run compute jobs.

"replica" | "job"

NodeRecord

A registered node: its id, address, zone, role and (a job node's) compute pool, absent for none.

{
  id: integer,
  addr: string,
  zone: string,
  role: NodeRole,
  pool?: string
}

Quotas

The per-account limits, and the compute and file limits of each organization (or personal account) that has no override. maxFuelPerDeveloperPerDay (0: no limit) is a decimal string; the others are JSON numbers.

{
  maxAppsPerAccount: integer,
  maxBundleBytesPerAccount: integer,
  maxApiKeysPerAccount: integer,
  maxOrgsPerAccount: integer,
  maxAccounts: integer,
  maxFileBytesPerOrg: integer,
  maxConcurrentRunsPerOrg: integer,
  computeFuelPerOrg: integer,
  maxFuelPerDeveloperPerDay: string /* decimal */
}

OrgQuotas

One payer's limits in place of the cluster's; a limit left out is the cluster's.

{
  maxConcurrentRuns?: integer,
  computeFuel?: string /* decimal */,
  maxFileBytes?: integer
}

QuotaSettings

GET /ops/quotas: the cluster's limits and, under orgs, each payer's overrides by payer id.

{
  maxAppsPerAccount: integer,
  maxBundleBytesPerAccount: integer,
  maxApiKeysPerAccount: integer,
  maxOrgsPerAccount: integer,
  maxAccounts: integer,
  maxFileBytesPerOrg: integer,
  maxConcurrentRunsPerOrg: integer,
  computeFuelPerOrg: integer,
  maxFuelPerDeveloperPerDay: string /* decimal */,
  orgs: {
    [key: string]: OrgQuotas
  }
}

UsageDay

What an app's runs used on one UTC day (date, YYYY-MM-DD), each figure a decimal string; wallMs is information only.

{
  date: string,
  runs: string /* decimal */,
  fuel: string /* decimal */,
  wallMs: string /* decimal */,
  writes: string /* decimal */,
  bytesWritten: string /* decimal */,
  events: string /* decimal */
}

RunFile

A file a run reads or wrote: its id, and its plaintext size and SHA-256 (hex) only for a caller who may list the app's files.

{
  id: string,
  size?: integer,
  sha256?: string
}

Run

A compute run's record, without its arguments or keys: its method, state, caps (fuel a JSON number here), inputs, attempts (tsMs Unix milliseconds) and final outcome (null while it runs; message the failure text, null unless the caller may list the app's files). progress is the leader's last poll (null elsewhere, when it is not active, or to a caller who may not list files); queue where the run waits for a job node, to a caller who may list files only.

{
  run: string,
  method: string,
  state: "queued" | "running" | "done" | "failed" | "cancelled",
  cancelRequested: boolean,
  startTsMs: integer,
  caps: {
    fuel: integer,
    memoryMib: integer,
    wallSecs: integer
  },
  inputs: RunFile[],
  attempts: {
    attempt: integer,
    node: integer,
    tsMs: integer
  }[],
  final: {
    attempt: integer,
    outcome: {
      kind: "done"
    } | {
      kind: "failed",
      reason: "fuel" | "memory" | "trap" | "app-error" | "integrity" | "cancelled" | "lost" | "refused" | "timeout" | "quota" | "not-granted" | "too-large"
    } | {
      kind: "cancelled"
    },
    outputs: RunFile[],
    usage: {
      cpuMicros: integer,
      gibMicros: integer,
      fuel: integer
    },
    tsMs: integer,
    message: string | null
  } | null,
  progress: {
    percent: integer,
    step: string
  } | null,
  queue?: {
    state: "unplaced" | "waiting" | "granted",
    capacity: integer,
    pool: string,
    reason?: "NO_CAPACITY" | "POOL_FULL" | "PAYER_AT_RUN_QUOTA" | "PAYER_AT_FUEL_QUOTA"
  }
}

AccountProof

A statement, signed with the answering node's receipt key (hex, Ed25519 over the statement's canonical JSON after its domain), that the account asked to bind nonce for audience, valid from issuedAt to expiresAt (Unix seconds).

{
  statement: AccountStatement,
  key: string,
  signature: string
}

AccountStatement

What an account proof states: the cluster and node, the account, the nonce and audience it binds, and when it was issued and expires (Unix seconds).

{
  cluster: string,
  node: integer,
  account: string,
  nonce: string,
  audience: string,
  issuedAt: integer,
  expiresAt: integer
}

PackageOrigin

A custom frontend origin of a package: the rp-id its passkeys use, who registered it and when (RFC 3339), and whether the cluster serves the package's frontend there.

{
  package: string,
  origin: string,
  rpId: string,
  addedBy: string,
  addedAt: string,
  served: boolean
}

SignUpState

The sign-up policy and what it implies: whether organization invites and cluster sign-up invites admit a new account, and whether one is required.

{
  policy: SignUp,
  orgInvites: boolean,
  signUpInvites: boolean,
  inviteRequired: boolean
}

ApprovedReleases

The mero-tee releases the scope approves now, after the change.

{
  approvedReleases: string[]
}

OutboundApproved

The outbound approval the scope holds now for the package's publisher (signer), after the change.

{
  signer: string,
  approval: OutboundApproval
}

Uninstalled

The versions an uninstall removed.

{
  removed: string[]
}

Deadlines

Every release deadline after the change, oldest release first (after RFC 3339, afterSecs Unix seconds).

{
  deadlines: {
    version: string,
    after: string,
    afterSecs: integer
  }[]
}

SignUpSet

The cluster's governance and sign-up policy after the change.

{
  governance: Governance,
  signUp: SignUpState
}

InviteKey

The key of the cluster sign-up invite withdrawn.

{
  inviteKey: string
}

UpgradeRun

An organization-wide upgrade run: the apps it targets, those done, and why each failed one failed.

{
  runId: string,
  package: string,
  version: string,
  team?: string,
  cascade: boolean,
  by: string,
  startedAt: integer,
  apps: string[],
  done: string[],
  failed: {
    [key: string]: any
  },
  finished: boolean
}

App

An app instance (a context) as the directory records it. executor is absent for an SDK 0.12 app (wasmer), which this node lists but does not run; release is the package release it runs, absent for a record from before or a raw upload; restore is a restore from a backup under way.

{
  appId: string,
  name: string,
  group: integer,
  bundle: string,
  owner: string,
  org: string | null,
  access: Access,
  confirmMethods: string[],
  executor?: "component" | "wasmer",
  replicas: integer[],
  createdAt: integer,
  initArgs: any,
  computeBundle?: string,
  components?: "computeOnly",
  metadata: any,
  lastUpgrade?: Upgrade,
  deployment?: string,
  release?: PackageRef,
  restore?: {
    seed?: integer,
    source?: {
      name: string,
      sha256: string,
      index: integer
    }
  }
}

AppEntry

An app as GET /apps lists it: package and version name the release its bundle came from (null for a raw upload), deployment the deployment it was created from (null for none; absent from an older node, as 1.0.0-rc.1).

{
  appId: string,
  name: string,
  owner: string,
  org: string | null,
  bundle: string,
  package: string | null,
  version: string | null,
  deployment?: string | null
}

PackageRef

One service of one package release: service is absent for a single-service bundle, compute (absent: false) marks the service's compute component.

{
  package: string,
  version: string,
  service?: string,
  compute?: boolean
}

Upgrade

The last upgrade tried on an app, done or failed: from and to are bundle hashes, by the account (or operator), run the organization-wide run it was part of, apiKey the upgrade key that made it.

{
  from: string,
  to: string,
  at: integer,
  by: string,
  ok: boolean,
  error?: any,
  run?: string,
  apiKey?: string,
  fromRelease?: PackageRef,
  toRelease?: PackageRef
}

Package

A package and the releases of it the caller may see, oldest first; latest is the newest of those.

{
  package: string,
  signerId: string,
  owner: string,
  latest: string,
  versions: {
    version: string,
    mpk: string,
    size: integer,
    source: "registry" | "upload",
    services: {
      [key: string]: string
    },
    metadata: any,
    outbound: string[],
    installedBy: string,
    installedAt: integer
  }[]
}

ApiKey

An API key as the account's list shows it (never its secret): apps and methods are null for every one; upgrades makes it an upgrade key.

{
  keyId: string,
  account: string,
  label: string,
  apps: string[] | null,
  methods: string[] | null,
  readOnly: boolean,
  allowConfirm: boolean,
  expiresAt: integer,
  upgrades?: {
    app: string,
    package: string,
    signer: string,
    proofKey: string
  }
}

Org

An organization as GET /orgs/{org} answers it. members maps each account to its role, capabilities and defaultCapabilities are capability bits, outboundApprovals is keyed by package signer, upgradeRuns by run id; recovery is absent when the organization set no recovery key, allApps when no member gets every app added later, personal unless it is its owner's personal organization (where instances created without naming an organization go).

{
  orgId: string,
  name: string,
  members: {
    [key: string]: OrgRole
  },
  teams: {
    [key: string]: Team
  },
  defaultCapabilities: integer,
  capabilities: {
    [key: string]: integer
  },
  approvedReleases: string[],
  outboundApprovals: {
    [key: string]: OutboundApproval
  },
  metadata: any,
  memberMetadata: {
    [key: string]: any
  },
  upgradeRuns: {
    [key: string]: UpgradeRun
  },
  recovery?: {
    publicKey: string,
    setAt: integer,
    pending: {
      account: string,
      startedAt: integer,
      readyAt: integer
    } | null
  },
  allApps?: string[],
  personal?: boolean,
  mode?: "legacy" | "standalone" | "shared",
  releaseApprovers?: string[],
  publishes?: string[],
  newWorkStopped?: {
    release: string,
    after: string
  } | null
}

Team

A team as its organization records it: members maps each direct row to whether it is a lead; capabilities are capability bits per row; defaultCapabilities is absent when unset.

{
  teamId: string,
  name: string,
  parent: string | null,
  join: TeamJoin,
  members: {
    [key: string]: boolean
  },
  readOnly: string[],
  capabilities: {
    [key: string]: integer
  },
  metadata: any,
  removed: string[],
  defaultCapabilities?: integer
}

TeamView

A team as GET /orgs/{org}/teams/{team} answers it: each member's row, the child teams the caller sees, its apps, and the caller's own row (myRole, null for none) and membership (member). package names the package of an app team; it and defaultCapabilities are absent from an older node (1.0.0-rc.1 sends neither).

{
  teamId: string,
  name: string,
  parent: string | null,
  join: TeamJoin,
  metadata: any,
  package?: string | null,
  defaultCapabilities?: integer | null,
  members: {
    account: string,
    role: TeamRole,
    capabilities: integer
  }[],
  children: string[],
  apps: {
    appId: string,
    name: string,
    contextId: string
  }[],
  myRole: TeamRole | null,
  member: boolean
}

Deployment

A deployment as its managers list it. host is its frontend host, null on a node with no apps domain; times are RFC 3339.

{
  id: string,
  host: string | null,
  name: string,
  owner: Deployer,
  apps: {
    app: string,
    package: string,
    version: string,
    addedBy: string,
    addedAt: string
  }[],
  createdBy: string,
  createdAt: string
}

DeadLetter

A cross-app call that was never delivered: its sequence number, the target app and method, why, and when (atMs, Unix milliseconds).

{
  seq: integer,
  app: string,
  method: string,
  reason: string,
  atMs: integer
}

Governance

Who decides what on this cluster: release approvals, app upgrades and outbound approvals (owner: each app's owner; operator: the operator), and, left out at their defaults, deployments (open), deployers (operator) and signUp (open).

{
  releases: "owner" | "operator",
  appUpgrades: "owner" | "operator",
  outbound: "owner" | "operator",
  deployments?: "granted" | "open",
  deployers?: "owner" | "operator",
  signUp?: "invite" | "closed" | "open"
}

OutboundApproval

What an owner approved for one publisher's apps to call out to: the approved URL prefixes, and every prefix it was shown.

{
  prefixes: string[],
  reviewed: string[]
}

AppScope

The scope whose approvals cover an app: its organization (personal: true when it is its owner's personal organization). account is only GET /auth/apps' own scope: the apps the account owns, wherever they are.

{
  kind: "org",
  org: string,
  personal?: boolean
} | {
  kind: "account"
}

ClusterRelease

A mero-tee release the cluster's nodes run: how many run it, and whether the scope approved it (true where nothing was ever recorded).

{
  release: string,
  nodes: integer,
  approved: boolean
}

BundleRelease

A bundle by its digest, with the release it came from where the reader may see it.

{
  bundle: string,
  package?: string,
  version?: string
}

ReportUpgrade

An app's last upgrade as a report shows it. actor, error, run and apiKey are shown to the app's people, never to the operator.

{
  from: BundleRelease,
  to: BundleRelease,
  at: integer,
  ok: boolean,
  actorKind: "owner" | "member" | "operator",
  actor?: string,
  error?: any,
  run?: string,
  apiKey?: string
}

ReportApp

One app in a release report (GET /auth/apps, GET /orgs/{org}/apps, GET /ops/apps): its bundle and release (package, null where the reader may not see it), the publisher's key and bound organization, who holds its upgrades and release approvals, its last upgrade, the releases approved to hold it (null: unrestricted), each replica's release, and lastWriteAt (Unix seconds, null when unknown). name, team, availableVersions (newer releases, oldest first), latestReachable and latestBlocked (the newest release and why an upgrade would not take it) are for the app's people, never the operator.

{
  app: string,
  group: integer,
  scope: AppScope,
  bundle: string,
  package: {
    package: string,
    version: string,
    service?: string | null
  } | null,
  publisher: {
    signer: string,
    org: string | null
  } | null,
  upgradesHeldBy: "operator" | "owner" | "publisher",
  releasesApprovedBy: "operator" | "publisher" | "owner",
  lastUpgrade: ReportUpgrade | null,
  approvedReleases: string[] | null,
  replicas: {
    node: integer,
    release: string | null,
    approved: boolean
  }[],
  lastWriteAt: integer | null,
  name?: string,
  team?: string,
  availableVersions?: string[],
  latestReachable?: string | null,
  latestBlocked?: {
    version: string,
    reason: "authority" | "runtime",
    message: string,
    minRuntimeVersion?: string,
    nodes?: {
      node: integer,
      runtime: string | {
        before: string
      } | null
    }[]
  }
}

DeploymentRecord

A deployment as the directory records it: the release it offers by app name (addedAt Unix seconds), who created it and when (Unix seconds).

{
  id: string,
  name: string,
  owner: Deployer,
  apps: {
    [key: string]: {
      package: string,
      version: string,
      addedBy: string,
      addedAt: integer
    }
  },
  createdBy: string,
  createdAt: integer
}

DeployerGrant

A grant to install where deployments are granted: until when (Unix seconds; absent: it does not end), when and by whom it was granted.

{
  until?: integer,
  grantedAt: integer,
  grantedBy: string
}

SignUpInvite

A cluster sign-up invite, never its token: uses left, when it expires (expiresAt RFC 3339, expiresAtSecs Unix seconds), who made it and when (RFC 3339).

{
  inviteKey: string,
  uses: integer,
  expiresAt: string,
  expiresAtSecs: integer,
  createdBy: string,
  createdAt: string
}

ProofOnly

What an operator decision that names nothing in its body may carry: none at first, the operator's proof after the 428.

{
  operatorProof?: OperatorProof
}

ConfirmOnly

The body of a step-up that names nothing else: none (or {}) at first, the passkey assertion after the 412.

{
  confirm?: Confirm
}

QuotaChanges

The limits POST /ops/quotas changes, each optional: without org, the cluster's (those GET /ops/quotas answers, maxFuelPerDeveloperPerDay a decimal string); with org, one payer's (maxConcurrentRuns, computeFuel a decimal string, maxFileBytes; null clears one). orgs is ignored. Any other property is refused 400 UNKNOWN_QUOTA.

{
  org?: string,
  operatorProof?: OperatorProof,
  orgs?: any,
  maxAppsPerAccount?: integer,
  maxBundleBytesPerAccount?: integer,
  maxApiKeysPerAccount?: integer,
  maxOrgsPerAccount?: integer,
  maxAccounts?: integer,
  maxFileBytesPerOrg?: integer,
  maxConcurrentRunsPerOrg?: integer,
  computeFuelPerOrg?: integer,
  maxFuelPerDeveloperPerDay?: string /* decimal */,
  maxConcurrentRuns?: integer | null,
  computeFuel?: string /* decimal */ | null,
  maxFileBytes?: integer | null
}