> For the complete documentation index, see [llms.txt](https://docs.kinesis.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kinesis.network/api/apps.md).

# Apps

Deploy, configure and operate container applications.

Serverless placement is CPU-only. A GPU app must name at least one config.grids.ids entry; otherwise create/update can return serverless\_gpu\_unavailable. Log and export endpoints return raw application output and may include sensitive data.

Apps follow their project’s organization and visibility. Resource paths identify the organization; GET /apps can filter by org. Developers operate apps they can edit. Admins or the app’s creator delete or move it; moves stay within an organization. Grid quotas count against the app’s creator, and serverless settings still apply.

## Check which servers could run an app that does not exist yet, from the placement-relevant parts of its configuration, before create\_app. Nothing is created.

> Requires \`apps:read\` (View apps, their configuration and status).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"Placement":{"type":"object","properties":{"placeable":{"type":"boolean","description":"A server can take the app now, a hibernated one would fit once woken, or one can be provisioned"},"serversWithCapacity":{"type":"integer","description":"Servers that match and have room now"},"serversWithoutCapacity":{"type":"integer","description":"Servers that match but are full"},"wakeable":{"type":"integer","description":"Hibernated servers that would match once woken (power_servers wake, or the automatic wake-up on start)"},"wakeableAwaitingStock":{"type":"integer","description":"Of wakeable, servers whose provider has no stock right now, so a wake would not land yet"},"provisionable":{"type":"boolean","description":"The platform can provision a matching cloud machine on demand for a serverless app"},"rejections":{"type":"array","items":{"type":"object","properties":{"server":{"type":"string","description":"Server address"},"reason":{"type":"string"}},"required":["server","reason"],"additionalProperties":false},"description":"Why sampled servers cannot take the app; each distinct reason appears first, then repeats"}},"required":["placeable","serversWithCapacity","serversWithoutCapacity","wakeable","wakeableAwaitingStock","provisionable","rejections"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/placement":{"post":{"operationId":"projects.placement","summary":"Check which servers could run an app that does not exist yet, from the placement-relevant parts of its configuration, before create_app. Nothing is created.","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project the app would be created in","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"config":{"type":"object","properties":{"instances":{"description":"Instance count range","type":"object","properties":{"min":{"type":"integer","minimum":0,"description":"Instances to keep running"},"max":{"type":"integer","minimum":0,"description":"Upper bound for scaling"}},"required":["min","max"],"additionalProperties":false},"stateful":{"description":"Keep each instance pinned to its server and disk","type":"boolean"},"hardware":{"description":"Hardware requirements per instance","type":"object","properties":{"gpuCount":{"description":"GPUs per instance; 0 for CPU-only. Above 0 needs grids.ids: serverless placement is CPU-only","type":"integer","minimum":0,"maximum":16},"gpuModels":{"description":"Acceptable GPU models, e.g. H100; empty means any","maxItems":16,"type":"array","items":{"type":"string","minLength":1}},"gpuManufacturer":{"description":"GPU vendor; null means any","anyOf":[{"type":"string","enum":["amd","apple","intel","nvidia","xilinx"]},{"type":"null"}]},"gpuVramBytes":{"description":"Minimum VRAM per GPU, in bytes","type":"integer","minimum":0},"ramBytes":{"description":"RAM per instance, in bytes","type":"integer","exclusiveMinimum":0},"storageBytes":{"description":"Disk per instance, in bytes","type":"integer","exclusiveMinimum":0},"shmemBytes":{"description":"Shared memory (/dev/shm) size, in bytes","type":"integer","minimum":0}},"additionalProperties":false},"placement":{"description":"Where the app may run and who may reach it","type":"object","properties":{"regions":{"description":"Kinesis regions to run in; empty means any","type":"array","items":{"type":"string","enum":["us-west","us-east","us-central","ca-west","ca-east","ca-central","eu-west","eu-north","eu-east","eu-south","eu-central","eu-south-east","ap-east","ap-south-east","ap-north-east","ap-south"]}},"providers":{"description":"Restrict placement to specific providers and regions","type":"array","items":{"type":"object","properties":{"csp":{"type":"string","enum":["aws","azure","gcp","kinesis"],"description":"Cloud provider"},"regions":{"type":"array","items":{"type":"object","properties":{"region":{"type":"string","minLength":1,"description":"Provider region"},"zones":{"type":"array","items":{"type":"string"},"description":"Zones within the region; empty means any"}},"required":["region","zones"],"additionalProperties":false},"description":"Regions of the provider to allow"}},"required":["csp","regions"],"additionalProperties":false}},"allowedIps":{"description":"Source IPs or CIDR ranges allowed to reach the app; empty means everyone","maxItems":100,"type":"array","items":{"type":"string"}}},"additionalProperties":false},"grids":{"description":"Run on grids instead of serverless capacity (members only, on grids they may deploy to)","type":"object","properties":{"ids":{"description":"Grids to run on; empty means serverless (CPU-only), so a GPU app names at least one","maxItems":20,"type":"array","items":{"type":"string","minLength":1}},"priorities":{"description":"Priority per grid id, -100 to 100","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","minimum":-100,"maximum":100}}},"additionalProperties":false},"volumes":{"description":"Persistent volumes","maxItems":4,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.-]{1,63}$","description":"Volume name, unique within the app"},"target":{"type":"string","pattern":"^\\/.+","description":"Absolute mount path inside the container"},"declaredSizeBytes":{"description":"Expected size, used for placement; 0 or omitted means unspecified","type":"integer","minimum":0,"maximum":17592186044416}},"required":["name","target"],"additionalProperties":false}}},"additionalProperties":false,"description":"The placement-relevant parts of an app configuration: instances, stateful, hardware, placement, grids, volumes"}},"required":["config"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Placement"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## List the apps the caller can see, oldest first. Across every project, or within one

> Requires \`apps:read\` (View apps, their configuration and status).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"App":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"projectId":{"type":"string"},"name":{"type":"string"},"guid":{"type":"string","description":"Runtime identifier of the app"},"source":{"description":"Where the image comes from: Docker Hub, a registry link, GitHub or an upload","type":["string","null"]},"image":{"type":["string","null"]},"domain":{"description":"Hostname the app answers on: the default custom domain, else the Kinesis-issued one","type":["string","null"]},"buildState":{"description":"Build pipeline state for GitHub-sourced apps","type":["string","null"]},"access":{"$ref":"#/components/schemas/Access"},"createdBy":{"anyOf":[{"$ref":"#/components/schemas/Person"},{"type":"null"}],"description":"Who created it. Null when nobody is on record, for another organization's, and for a credential without members:read"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"}},"required":["id","projectId","name","guid","source","image","domain","buildState","access","createdBy","createdAt"],"additionalProperties":false},"Access":{"type":"object","properties":{"role":{"type":"string","enum":["admin","developer","viewer"],"description":"The caller's role on it"},"outside":{"type":"boolean","description":"Shared with the caller from another organization"},"isCreator":{"type":"boolean","description":"The caller created it"}},"required":["role","outside","isCreator"],"additionalProperties":false},"Person":{"type":"object","properties":{"userId":{"type":"string","description":"User id, as members.list and the sharing calls use it"},"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["userId","name","email"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/apps":{"get":{"operationId":"apps.list","summary":"List the apps the caller can see, oldest first. Across every project, or within one","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Apps"],"parameters":[{"name":"org","in":"query","required":false,"description":"Slug of an organization (see orgs.list) to list only what is in it or shared into it","schema":{"type":"string","minLength":3,"maxLength":39}},{"name":"projectId","in":"query","required":false,"description":"Limit the list to one project","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"limit","in":"query","required":false,"description":"Items per page, 1 to 200 (default 50)","schema":{"type":"integer","minimum":1,"maximum":200}},{"name":"cursor","in":"query","required":false,"description":"nextCursor from the previous page; omit for the first page","schema":{"type":"string","minLength":1,"maxLength":512}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"nextCursor":{"description":"Pass as cursor to fetch the next page; null on the last page","type":["string","null"]}},"required":["apps","nextCursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## List the apps in a project

> Requires \`apps:read\` (View apps, their configuration and status).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"App":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"projectId":{"type":"string"},"name":{"type":"string"},"guid":{"type":"string","description":"Runtime identifier of the app"},"source":{"description":"Where the image comes from: Docker Hub, a registry link, GitHub or an upload","type":["string","null"]},"image":{"type":["string","null"]},"domain":{"description":"Hostname the app answers on: the default custom domain, else the Kinesis-issued one","type":["string","null"]},"buildState":{"description":"Build pipeline state for GitHub-sourced apps","type":["string","null"]},"access":{"$ref":"#/components/schemas/Access"},"createdBy":{"anyOf":[{"$ref":"#/components/schemas/Person"},{"type":"null"}],"description":"Who created it. Null when nobody is on record, for another organization's, and for a credential without members:read"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"}},"required":["id","projectId","name","guid","source","image","domain","buildState","access","createdBy","createdAt"],"additionalProperties":false},"Access":{"type":"object","properties":{"role":{"type":"string","enum":["admin","developer","viewer"],"description":"The caller's role on it"},"outside":{"type":"boolean","description":"Shared with the caller from another organization"},"isCreator":{"type":"boolean","description":"The caller created it"}},"required":["role","outside","isCreator"],"additionalProperties":false},"Person":{"type":"object","properties":{"userId":{"type":"string","description":"User id, as members.list and the sharing calls use it"},"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["userId","name","email"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps":{"get":{"operationId":"projects.apps","summary":"List the apps in a project","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Limit the list to one project","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"org","in":"query","required":false,"description":"Slug of an organization (see orgs.list) to list only what is in it or shared into it","schema":{"type":"string","minLength":3,"maxLength":39}},{"name":"limit","in":"query","required":false,"description":"Items per page, 1 to 200 (default 50)","schema":{"type":"integer","minimum":1,"maximum":200}},{"name":"cursor","in":"query","required":false,"description":"nextCursor from the previous page; omit for the first page","schema":{"type":"string","minLength":1,"maxLength":512}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"apps":{"type":"array","items":{"$ref":"#/components/schemas/App"}},"nextCursor":{"description":"Pass as cursor to fetch the next page; null on the last page","type":["string","null"]}},"required":["apps","nextCursor"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Create an app from a container image, or from a GitHub repository with source, and start it. With envFrom the new app takes another app's environment variables, secret values included, copied on the server. Omitted config fields take the dashboard defaults (1 GiB RAM, 1 GB disk, 1 to 3 instances, no GPU).

> Requires \`apps:write\` (Create, update, start, stop, restart and rebuild apps), \`compute:spend\` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances).\
> \
> Errors specific to this operation:\
> \- 402 \`balance\_over\_limit\`: The organization's balance is below the allowed negative limit; add credits and retry\
> \- 429 \`app\_creation\_quota\_exceeded\`: The organization's app creation quota is used up; add a payment method or wait for the window\
> \- 400 \`no\_suitable\_machines\`: No machine can run this configuration; lower the hardware requirements or ask for provisioning\
> \- 400 \`serverless\_gpu\_unavailable\`: The app asks for a GPU and targets no grid; serverless placement is CPU-only, so pass grids.ids\
> \- 429 \`grid\_quota\_exceeded\`: The grids the app targets have no room for it under their per-person app and instance quotas\
> \- 403 \`serverless\_disabled\`: The app would run on Kinesis serverless capacity, which the organization keeps to its admins; target a grid\
> \- 503 \`github\_not\_configured\`: GitHub deployments are not enabled on this server\
> \- 404 \`github\_installation\_not\_found\`: The caller has no connected GitHub account with this installation id; connect it in the dashboard\
> \- 404 \`github\_repo\_not\_found\`: The installation cannot see the repository; grant the GitHub App access to it\
> \- 502 \`upstream\_github\`: GitHub did not answer; retry shortly\
> \- 404 \`github\_branch\_not\_found\`: The repository has no such branch\
> \- 409 \`app\_config\_unavailable\`: The envFrom app has no configuration to copy from

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"IdempotentReplayed":{"description":"true when the response was replayed for a reused Idempotency-Key rather than produced anew","schema":{"type":"boolean"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"AppCreateResult":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"projectId":{"type":"string"},"name":{"type":"string"},"guid":{"type":"string","description":"Runtime identifier of the app"},"source":{"description":"Where the image comes from: Docker Hub, a registry link, GitHub or an upload","type":["string","null"]},"image":{"type":["string","null"]},"domain":{"description":"Hostname the app answers on: the default custom domain, else the Kinesis-issued one","type":["string","null"]},"buildState":{"description":"Build pipeline state for GitHub-sourced apps","type":["string","null"]},"access":{"$ref":"#/components/schemas/Access"},"createdBy":{"anyOf":[{"$ref":"#/components/schemas/Person"},{"type":"null"}],"description":"Who created it. Null when nobody is on record, for another organization's, and for a credential without members:read"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"status":{"description":"Status as last cached; use the status endpoint for a live read","$ref":"#/components/schemas/AppStatus"},"config":{"anyOf":[{"$ref":"#/components/schemas/AppConfig"},{"type":"null"}]},"github":{"anyOf":[{"$ref":"#/components/schemas/AppGitHubSource"},{"type":"null"}],"description":"Repository settings of a GitHub-sourced app"},"defaultDomain":{"description":"Custom domain shown as the app's address in the dashboard; null for the Kinesis-issued one","type":["string","null"]},"start":{"description":"How the automatic start after creation went","$ref":"#/components/schemas/AppStartOutcome"},"buildId":{"description":"First build of a GitHub-sourced app; null for image apps","type":["string","null"]}},"required":["id","projectId","name","guid","source","image","domain","buildState","access","createdBy","createdAt","status","config","github","defaultDomain","start","buildId"],"additionalProperties":false},"Access":{"type":"object","properties":{"role":{"type":"string","enum":["admin","developer","viewer"],"description":"The caller's role on it"},"outside":{"type":"boolean","description":"Shared with the caller from another organization"},"isCreator":{"type":"boolean","description":"The caller created it"}},"required":["role","outside","isCreator"],"additionalProperties":false},"Person":{"type":"object","properties":{"userId":{"type":"string","description":"User id, as members.list and the sharing calls use it"},"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["userId","name","email"],"additionalProperties":false},"AppStatus":{"type":"object","properties":{"state":{"type":"string","enum":["unknown","running","stopped","starting","stopping","scaling","updating","downloading","provisioning","start_blocked","error","building","build_failed"],"description":"Aggregate state; build states win while there is no runnable image"},"targetState":{"type":"string","enum":["running","stopped","unknown"],"description":"What the runtime was last asked for; unknown until it has been asked, as for a repository app before its first build succeeds"},"nodes":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"state":{"type":"string"},"reportedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the server last reported this state; not a start time"}},"required":["address","state","reportedAt"],"additionalProperties":false},"description":"Servers the app is placed on and the container state on each"},"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/AppEndpoint"},"description":"Where each configured port answers; a load-balanced port gets its address a minute or two after the first start"},"errors":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"message":{"type":"string"},"at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"details":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}],"description":"Extra data the runtime attached, such as the grid or server involved"}},"required":["type","message","at","details"],"additionalProperties":false},"description":"Recent runtime errors, newest first"},"workOrders":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"What the runtime asked the server to do"},"server":{"type":"string","description":"Server address"},"status":{"type":"string"},"createdAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"startedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"completedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["type","server","status","createdAt","startedAt","completedAt"],"additionalProperties":false},"description":"The runtime's latest instructions to servers, newest first; an order that never completes is the stall"},"grid":{"anyOf":[{"type":"object","properties":{"fill":{"anyOf":[{"type":"object","properties":{"target":{"type":"integer","description":"Members the grid is composed to have"},"online":{"type":"integer","description":"Members the app runs on"},"pending":{"type":"integer"},"converging":{"type":"boolean","description":"The grid is still acquiring members or placing the app"}},"required":["target","online","pending","converging"],"additionalProperties":false},{"type":"null"}],"description":"How far the grid has filled for this app"},"idleReclaim":{"type":"array","items":{"type":"object","properties":{"gridId":{"type":"string"},"warnedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"evictAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the app becomes evictable; null when the grid only warns"},"evictedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"cooldownEndsAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the grid takes the app again after an eviction"},"evidence":{"type":"string","description":"Why the grid considers the app idle"}},"required":["gridId","warnedAt","evictAt","evictedAt","cooldownEndsAt","evidence"],"additionalProperties":false},"description":"Grids whose idle policy has warned or evicted the app"},"queue":{"type":"array","items":{"type":"object","properties":{"gridId":{"type":"string"},"position":{"type":"integer","description":"1-based place in the grid's fair-share queue"},"queueLength":{"type":"integer"},"enqueuedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"held":{"type":"boolean","description":"The scheduler keeps the app off the grid until its turn comes"}},"required":["gridId","position","queueLength","enqueuedAt","held"],"additionalProperties":false},"description":"Full grids the app is queued on"}},"required":["fill","idleReclaim","queue"],"additionalProperties":false},{"type":"null"}],"description":"Grid placement details; null for a serverless app"},"pollAfterSec":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Seconds to wait before reading the status again while it is changing; null in a settled state"}},"required":["state","targetState","nodes","endpoints","errors","workOrders","grid","pollAfterSec"],"additionalProperties":false},"AppEndpoint":{"type":"object","properties":{"port":{"type":"integer","description":"Container port, as in config.ports"},"protocol":{"type":"string","description":"Protocol of that port, as in config.ports"},"address":{"description":"An http(s) URL for the HTTP protocols, host:port for the others; null until the endpoint is wired","type":["string","null"]},"server":{"description":"Server address of a direct tcp or udp endpoint; null when load-balanced","type":["string","null"]}},"required":["port","protocol","address","server"],"additionalProperties":false},"AppConfig":{"type":"object","properties":{"image":{"type":"string","description":"Container image reference"},"imageTag":{"description":"Tag, kept separately for Docker Hub images","type":["string","null"]},"registryUsername":{"description":"Registry login; the password is write-only","type":["string","null"]},"ports":{"type":"array","items":{"type":"object","properties":{"port":{"type":"integer"},"protocol":{"type":"string"}},"required":["port","protocol"],"additionalProperties":false}},"env":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":["string","null"]},"secret":{"type":"boolean"}},"required":["key","value","secret"],"additionalProperties":false},"description":"Environment variables; value is null for secrets, and on a connection that takes no credentials for values that look like one (null keeps a value on update)"},"command":{"type":"array","items":{"type":"string"}},"entrypoint":{"type":"array","items":{"type":"string"}},"startupCommand":{"anyOf":[{"type":"object","properties":{"args":{"type":"array","items":{"type":"string"}},"user":{"type":"string"},"timeoutSec":{"type":"number"},"startPeriodSec":{"type":"number"}},"required":["args","user","timeoutSec","startPeriodSec"],"additionalProperties":false},{"type":"null"}]},"healthcheck":{"anyOf":[{"type":"object","properties":{"test":{"type":"array","items":{"type":"string"}},"intervalSec":{"type":"number"}},"required":["test","intervalSec"],"additionalProperties":false},{"type":"null"}]},"restartPolicy":{"anyOf":[{"type":"object","properties":{"mode":{"type":"string"},"startTimeoutSec":{"type":"number"},"maxRetriesPerNode":{"type":"number"},"maxErrorTolerance":{"type":"number"},"numTasks":{"type":"number"}},"required":["mode","startTimeoutSec","maxRetriesPerNode","maxErrorTolerance","numTasks"],"additionalProperties":false},{"type":"null"}]},"instances":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"}},"required":["min","max"],"additionalProperties":false},"stateful":{"type":"boolean"},"hardware":{"type":"object","properties":{"gpuCount":{"type":"integer"},"gpuModels":{"type":"array","items":{"type":"string"}},"gpuManufacturer":{"type":["string","null"]},"gpuVramBytes":{"type":"number"},"ramBytes":{"type":"number"},"storageBytes":{"type":"number"},"shmemBytes":{"type":"number"}},"required":["gpuCount","gpuModels","gpuManufacturer","gpuVramBytes","ramBytes","storageBytes","shmemBytes"],"additionalProperties":false},"placement":{"type":"object","properties":{"regions":{"type":"array","items":{"type":"string"},"description":"Kinesis regions, e.g. us-west"},"providers":{"type":"array","items":{"type":"object","properties":{"csp":{"type":"string"},"regions":{"type":"array","items":{"type":"object","properties":{"region":{"type":"string"},"zones":{"type":"array","items":{"type":"string"}}},"required":["region","zones"],"additionalProperties":false}}},"required":["csp","regions"],"additionalProperties":false}},"allowedIps":{"type":"array","items":{"type":"string"},"description":"Source IPs or CIDR ranges allowed to reach the app"}},"required":["regions","providers","allowedIps"],"additionalProperties":false},"grids":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}},"priorities":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"},"description":"Priority per grid id"}},"required":["ids","priorities"],"additionalProperties":false},"volumes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"target":{"type":"string"},"declaredSizeBytes":{"type":"number"}},"required":["name","target","declaredSizeBytes"],"additionalProperties":false}},"domains":{"type":"array","items":{"type":"string"},"description":"Custom domains attached to the app (see the domain operations)"}},"required":["image","imageTag","registryUsername","ports","env","command","entrypoint","startupCommand","healthcheck","restartPolicy","instances","stateful","hardware","placement","grids","volumes","domains"],"additionalProperties":false},"AppGitHubSource":{"type":"object","properties":{"installationId":{"type":"integer","description":"GitHub App installation the repository is read through"},"repo":{"type":"string","description":"owner/name"},"url":{"type":"string"},"branch":{"type":"string","description":"Branch that is built and, with autoDeploy, followed"},"contextDir":{"type":"string"},"dockerfilePath":{"description":"Dockerfile path relative to contextDir; not used while dockerfileContent is set","type":["string","null"]},"dockerfileOverride":{"type":"boolean","description":"An inline Dockerfile (dockerfileContent) is built instead of dockerfilePath"},"dockerfileContent":{"description":"The inline Dockerfile that is built; null when the repository's own file is used","type":["string","null"]},"autoDeploy":{"type":"boolean","description":"Every push to the branch rebuilds and redeploys"},"clonedFrom":{"description":"Public repository (owner/name) the app's repository was copied from at creation; null otherwise","type":["string","null"]}},"required":["installationId","repo","url","branch","contextDir","dockerfilePath","dockerfileOverride","dockerfileContent","autoDeploy","clonedFrom"],"additionalProperties":false},"AppStartOutcome":{"type":"object","properties":{"state":{"type":"string","enum":["requested","deferred","building","failed"],"description":"requested: the start was accepted, poll the status to follow it; deferred: machines are being provisioned for the app first, poll the status; building: the app starts once its first build succeeds, poll the build; failed: the app exists but is stopped, see error"},"error":{"description":"Why the automatic start failed","type":["string","null"]}},"required":["state","error"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PaymentRequired":{"description":"The balance or the card does not cover the action: insufficient_balance, balance_over_limit, card_declined, authentication_required or blocked_by_risk","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps":{"post":{"operationId":"apps.create","summary":"Create an app from a container image, or from a GitHub repository with source, and start it. With envFrom the new app takes another app's environment variables, secret values included, copied on the server. Omitted config fields take the dashboard defaults (1 GiB RAM, 1 GB disk, 1 to 3 instances, no GPU).","description":"Requires `apps:write` (Create, update, start, stop, restart and rebuild apps), `compute:spend` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances).\n\nErrors specific to this operation:\n- 402 `balance_over_limit`: The organization's balance is below the allowed negative limit; add credits and retry\n- 429 `app_creation_quota_exceeded`: The organization's app creation quota is used up; add a payment method or wait for the window\n- 400 `no_suitable_machines`: No machine can run this configuration; lower the hardware requirements or ask for provisioning\n- 400 `serverless_gpu_unavailable`: The app asks for a GPU and targets no grid; serverless placement is CPU-only, so pass grids.ids\n- 429 `grid_quota_exceeded`: The grids the app targets have no room for it under their per-person app and instance quotas\n- 403 `serverless_disabled`: The app would run on Kinesis serverless capacity, which the organization keeps to its admins; target a grid\n- 503 `github_not_configured`: GitHub deployments are not enabled on this server\n- 404 `github_installation_not_found`: The caller has no connected GitHub account with this installation id; connect it in the dashboard\n- 404 `github_repo_not_found`: The installation cannot see the repository; grant the GitHub App access to it\n- 502 `upstream_github`: GitHub did not answer; retry shortly\n- 404 `github_branch_not_found`: The repository has no such branch\n- 409 `app_config_unavailable`: The envFrom app has no configuration to copy from","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project to create the app in","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Any unique string of at most 255 characters. A retry with the same key and body returns the first call's response (with Idempotent-Replayed: true) instead of acting twice; a different body is refused with 409 idempotency_conflict, and a retry while the first call is still running gets 409 request_in_progress. Keys are kept for 24 hours.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^\\S+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"App name"},"config":{"type":"object","properties":{"image":{"description":"Container image reference, e.g. nginx:1.27 or ghcr.io/org/app:tag","type":"string","minLength":1,"maxLength":512},"registryAuth":{"description":"Credentials for a private image","type":"object","properties":{"username":{"type":"string","minLength":1,"description":"Registry login"},"password":{"type":"string","minLength":1,"description":"Registry password or token (write-only)"}},"required":["username","password"],"additionalProperties":false},"ports":{"description":"Ports to expose","maxItems":32,"type":"array","items":{"type":"object","properties":{"port":{"type":"integer","minimum":1,"maximum":65535,"description":"Container port"},"protocol":{"type":"string","enum":["tcp","udp","tcp_load_balancer","tcps_load_balancer","http_load_balancer","https_load_balancer","http80_load_balancer","https443_load_balancer","grpcs_load_balancer"],"description":"How the port is exposed"}},"required":["port","protocol"]}},"env":{"description":"Environment variables","maxItems":200,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","description":"Variable name"},"value":{"description":"Value; null keeps the stored value of an existing variable","type":["string","null"]},"secret":{"description":"Store as a secret: never returned by reads","type":"boolean"}},"required":["key","value"]}},"command":{"description":"Container command (CMD) override","maxItems":256,"type":"array","items":{"type":"string"}},"entrypoint":{"description":"Container entrypoint override","maxItems":256,"type":"array","items":{"type":"string"}},"startupCommand":{"description":"Command run inside the container once it starts; null clears it","anyOf":[{"type":"object","properties":{"args":{"minItems":1,"type":"array","items":{"type":"string"},"description":"Command and arguments"},"user":{"description":"User to run as","type":"string"},"timeoutSec":{"description":"Seconds before the command is considered failed","type":"integer","minimum":0},"startPeriodSec":{"description":"Seconds to wait after the container starts","type":"integer","minimum":0}},"required":["args"],"additionalProperties":false},{"type":"null"}]},"healthcheck":{"description":"Container health check; null clears it","anyOf":[{"type":"object","properties":{"test":{"minItems":1,"type":"array","items":{"type":"string"},"description":"Command that must exit 0 for the app to count as healthy"},"intervalSec":{"type":"integer","minimum":1,"description":"Seconds between checks"}},"required":["test","intervalSec"],"additionalProperties":false},{"type":"null"}]},"restartPolicy":{"description":"Restart behaviour","type":"object","properties":{"mode":{"type":"string","enum":["disabled","always","on_failure","task_completion"],"description":"When to restart a container that exits"},"startTimeoutSec":{"description":"Seconds a start may take before it counts as failed","type":"integer","minimum":0},"maxRetriesPerNode":{"description":"Restarts allowed on one server before moving on","type":"integer","minimum":0},"maxErrorTolerance":{"description":"Failures tolerated before the app is stopped","type":"integer","minimum":0},"numTasks":{"description":"For task_completion: runs to complete before stopping","type":"integer","minimum":0}},"required":["mode"],"additionalProperties":false},"instances":{"description":"Instance count range","type":"object","properties":{"min":{"type":"integer","minimum":0,"description":"Instances to keep running"},"max":{"type":"integer","minimum":0,"description":"Upper bound for scaling"}},"required":["min","max"],"additionalProperties":false},"stateful":{"description":"Keep each instance pinned to its server and disk","type":"boolean"},"hardware":{"description":"Hardware requirements per instance","type":"object","properties":{"gpuCount":{"description":"GPUs per instance; 0 for CPU-only. Above 0 needs grids.ids: serverless placement is CPU-only","type":"integer","minimum":0,"maximum":16},"gpuModels":{"description":"Acceptable GPU models, e.g. H100; empty means any","maxItems":16,"type":"array","items":{"type":"string","minLength":1}},"gpuManufacturer":{"description":"GPU vendor; null means any","anyOf":[{"type":"string","enum":["amd","apple","intel","nvidia","xilinx"]},{"type":"null"}]},"gpuVramBytes":{"description":"Minimum VRAM per GPU, in bytes","type":"integer","minimum":0},"ramBytes":{"description":"RAM per instance, in bytes","type":"integer","exclusiveMinimum":0},"storageBytes":{"description":"Disk per instance, in bytes","type":"integer","exclusiveMinimum":0},"shmemBytes":{"description":"Shared memory (/dev/shm) size, in bytes","type":"integer","minimum":0}},"additionalProperties":false},"placement":{"description":"Where the app may run and who may reach it","type":"object","properties":{"regions":{"description":"Kinesis regions to run in; empty means any","type":"array","items":{"type":"string","enum":["us-west","us-east","us-central","ca-west","ca-east","ca-central","eu-west","eu-north","eu-east","eu-south","eu-central","eu-south-east","ap-east","ap-south-east","ap-north-east","ap-south"]}},"providers":{"description":"Restrict placement to specific providers and regions","type":"array","items":{"type":"object","properties":{"csp":{"type":"string","enum":["aws","azure","gcp","kinesis"],"description":"Cloud provider"},"regions":{"type":"array","items":{"type":"object","properties":{"region":{"type":"string","minLength":1,"description":"Provider region"},"zones":{"type":"array","items":{"type":"string"},"description":"Zones within the region; empty means any"}},"required":["region","zones"],"additionalProperties":false},"description":"Regions of the provider to allow"}},"required":["csp","regions"],"additionalProperties":false}},"allowedIps":{"description":"Source IPs or CIDR ranges allowed to reach the app; empty means everyone","maxItems":100,"type":"array","items":{"type":"string"}}},"additionalProperties":false},"grids":{"description":"Run on grids instead of serverless capacity (members only, on grids they may deploy to)","type":"object","properties":{"ids":{"description":"Grids to run on; empty means serverless (CPU-only), so a GPU app names at least one","maxItems":20,"type":"array","items":{"type":"string","minLength":1}},"priorities":{"description":"Priority per grid id, -100 to 100","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","minimum":-100,"maximum":100}}},"additionalProperties":false},"volumes":{"description":"Persistent volumes","maxItems":4,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.-]{1,63}$","description":"Volume name, unique within the app"},"target":{"type":"string","pattern":"^\\/.+","description":"Absolute mount path inside the container"},"declaredSizeBytes":{"description":"Expected size, used for placement; 0 or omitted means unspecified","type":"integer","minimum":0,"maximum":17592186044416}},"required":["name","target"],"additionalProperties":false}}},"additionalProperties":false,"description":"Initial configuration; image is required unless source is set"},"source":{"description":"Build the image from a GitHub repository the caller connected (members of the project's organization); omit to pull config.image","type":"object","properties":{"kind":{"type":"string","const":"github","description":"Build the image from a GitHub repository"},"installationId":{"type":"integer","exclusiveMinimum":0,"description":"GitHub App installation id, from the connected accounts list"},"repo":{"description":"Repository as owner/name; omit with clone","type":"string","pattern":"^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\\/[A-Za-z0-9._-]{1,100}$"},"clone":{"description":"Copy a public repository into the connected account and build from the copy, instead of repo","type":"object","properties":{"sourceRepo":{"type":"string","minLength":3,"maxLength":300,"description":"Public GitHub repository to copy: a github.com URL (optionally .../tree/<branch>) or owner/name"},"sourceRef":{"description":"Branch, tag or commit to copy; default: the source's default branch","type":"string","minLength":1,"maxLength":255},"targetRepoName":{"type":"string","pattern":"^[A-Za-z0-9._-]{1,100}$","description":"Name of the new repository under the connected account (installationId)"},"targetVisibility":{"description":"Visibility of the new repository; private by default","type":"string","enum":["private","public"]}},"required":["sourceRepo","targetRepoName"],"additionalProperties":false},"branch":{"description":"Branch to build and follow; default: the repository's default branch","type":"string","minLength":1,"maxLength":255},"contextDir":{"description":"Directory the image is built from, relative to the repository root (default /)","type":"string","minLength":1,"maxLength":512},"dockerfilePath":{"description":"Dockerfile path relative to contextDir (default Dockerfile)","type":"string","minLength":1,"maxLength":512},"autoDeploy":{"description":"Rebuild and redeploy on every push to the branch (default true)","type":"boolean"},"dockerfileContent":{"description":"Inline Dockerfile built instead of dockerfilePath; how a repository without one is deployed","type":"string","maxLength":65536}},"required":["kind","installationId"],"additionalProperties":false},"envFrom":{"description":"Copy another app's environment variables, secret values included, on the server (developer access to that app); use overrides instead of config.env","type":"object","properties":{"projectId":{"type":"string","pattern":"^[0-9a-fA-F]{24}$","description":"Project of the app to copy from"},"appId":{"type":"string","pattern":"^[0-9a-fA-F]{24}$","description":"App to copy the variables from"},"overrides":{"description":"Variables set on top of the copied ones, by key; a null value keeps the copied value","maxItems":200,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","description":"Variable name"},"value":{"description":"Value; null keeps the copied value (a copied secret stays secret)","type":["string","null"]},"secret":{"description":"Store as a secret: never returned by reads","type":"boolean"}},"required":["key","value"]}}},"required":["projectId","appId"],"additionalProperties":false}},"required":["name","config"]}}}},"responses":{"201":{"description":"Created","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppCreateResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Get an app with its full configuration and last known status

> Requires \`apps:read\` (View apps, their configuration and status).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"AppDetail":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"projectId":{"type":"string"},"name":{"type":"string"},"guid":{"type":"string","description":"Runtime identifier of the app"},"source":{"description":"Where the image comes from: Docker Hub, a registry link, GitHub or an upload","type":["string","null"]},"image":{"type":["string","null"]},"domain":{"description":"Hostname the app answers on: the default custom domain, else the Kinesis-issued one","type":["string","null"]},"buildState":{"description":"Build pipeline state for GitHub-sourced apps","type":["string","null"]},"access":{"$ref":"#/components/schemas/Access"},"createdBy":{"anyOf":[{"$ref":"#/components/schemas/Person"},{"type":"null"}],"description":"Who created it. Null when nobody is on record, for another organization's, and for a credential without members:read"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"status":{"description":"Status as last cached; use the status endpoint for a live read","$ref":"#/components/schemas/AppStatus"},"config":{"anyOf":[{"$ref":"#/components/schemas/AppConfig"},{"type":"null"}]},"github":{"anyOf":[{"$ref":"#/components/schemas/AppGitHubSource"},{"type":"null"}],"description":"Repository settings of a GitHub-sourced app"},"defaultDomain":{"description":"Custom domain shown as the app's address in the dashboard; null for the Kinesis-issued one","type":["string","null"]}},"required":["id","projectId","name","guid","source","image","domain","buildState","access","createdBy","createdAt","status","config","github","defaultDomain"],"additionalProperties":false},"Access":{"type":"object","properties":{"role":{"type":"string","enum":["admin","developer","viewer"],"description":"The caller's role on it"},"outside":{"type":"boolean","description":"Shared with the caller from another organization"},"isCreator":{"type":"boolean","description":"The caller created it"}},"required":["role","outside","isCreator"],"additionalProperties":false},"Person":{"type":"object","properties":{"userId":{"type":"string","description":"User id, as members.list and the sharing calls use it"},"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["userId","name","email"],"additionalProperties":false},"AppStatus":{"type":"object","properties":{"state":{"type":"string","enum":["unknown","running","stopped","starting","stopping","scaling","updating","downloading","provisioning","start_blocked","error","building","build_failed"],"description":"Aggregate state; build states win while there is no runnable image"},"targetState":{"type":"string","enum":["running","stopped","unknown"],"description":"What the runtime was last asked for; unknown until it has been asked, as for a repository app before its first build succeeds"},"nodes":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"state":{"type":"string"},"reportedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the server last reported this state; not a start time"}},"required":["address","state","reportedAt"],"additionalProperties":false},"description":"Servers the app is placed on and the container state on each"},"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/AppEndpoint"},"description":"Where each configured port answers; a load-balanced port gets its address a minute or two after the first start"},"errors":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"message":{"type":"string"},"at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"details":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}],"description":"Extra data the runtime attached, such as the grid or server involved"}},"required":["type","message","at","details"],"additionalProperties":false},"description":"Recent runtime errors, newest first"},"workOrders":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"What the runtime asked the server to do"},"server":{"type":"string","description":"Server address"},"status":{"type":"string"},"createdAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"startedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"completedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["type","server","status","createdAt","startedAt","completedAt"],"additionalProperties":false},"description":"The runtime's latest instructions to servers, newest first; an order that never completes is the stall"},"grid":{"anyOf":[{"type":"object","properties":{"fill":{"anyOf":[{"type":"object","properties":{"target":{"type":"integer","description":"Members the grid is composed to have"},"online":{"type":"integer","description":"Members the app runs on"},"pending":{"type":"integer"},"converging":{"type":"boolean","description":"The grid is still acquiring members or placing the app"}},"required":["target","online","pending","converging"],"additionalProperties":false},{"type":"null"}],"description":"How far the grid has filled for this app"},"idleReclaim":{"type":"array","items":{"type":"object","properties":{"gridId":{"type":"string"},"warnedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"evictAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the app becomes evictable; null when the grid only warns"},"evictedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"cooldownEndsAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the grid takes the app again after an eviction"},"evidence":{"type":"string","description":"Why the grid considers the app idle"}},"required":["gridId","warnedAt","evictAt","evictedAt","cooldownEndsAt","evidence"],"additionalProperties":false},"description":"Grids whose idle policy has warned or evicted the app"},"queue":{"type":"array","items":{"type":"object","properties":{"gridId":{"type":"string"},"position":{"type":"integer","description":"1-based place in the grid's fair-share queue"},"queueLength":{"type":"integer"},"enqueuedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"held":{"type":"boolean","description":"The scheduler keeps the app off the grid until its turn comes"}},"required":["gridId","position","queueLength","enqueuedAt","held"],"additionalProperties":false},"description":"Full grids the app is queued on"}},"required":["fill","idleReclaim","queue"],"additionalProperties":false},{"type":"null"}],"description":"Grid placement details; null for a serverless app"},"pollAfterSec":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Seconds to wait before reading the status again while it is changing; null in a settled state"}},"required":["state","targetState","nodes","endpoints","errors","workOrders","grid","pollAfterSec"],"additionalProperties":false},"AppEndpoint":{"type":"object","properties":{"port":{"type":"integer","description":"Container port, as in config.ports"},"protocol":{"type":"string","description":"Protocol of that port, as in config.ports"},"address":{"description":"An http(s) URL for the HTTP protocols, host:port for the others; null until the endpoint is wired","type":["string","null"]},"server":{"description":"Server address of a direct tcp or udp endpoint; null when load-balanced","type":["string","null"]}},"required":["port","protocol","address","server"],"additionalProperties":false},"AppConfig":{"type":"object","properties":{"image":{"type":"string","description":"Container image reference"},"imageTag":{"description":"Tag, kept separately for Docker Hub images","type":["string","null"]},"registryUsername":{"description":"Registry login; the password is write-only","type":["string","null"]},"ports":{"type":"array","items":{"type":"object","properties":{"port":{"type":"integer"},"protocol":{"type":"string"}},"required":["port","protocol"],"additionalProperties":false}},"env":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":["string","null"]},"secret":{"type":"boolean"}},"required":["key","value","secret"],"additionalProperties":false},"description":"Environment variables; value is null for secrets, and on a connection that takes no credentials for values that look like one (null keeps a value on update)"},"command":{"type":"array","items":{"type":"string"}},"entrypoint":{"type":"array","items":{"type":"string"}},"startupCommand":{"anyOf":[{"type":"object","properties":{"args":{"type":"array","items":{"type":"string"}},"user":{"type":"string"},"timeoutSec":{"type":"number"},"startPeriodSec":{"type":"number"}},"required":["args","user","timeoutSec","startPeriodSec"],"additionalProperties":false},{"type":"null"}]},"healthcheck":{"anyOf":[{"type":"object","properties":{"test":{"type":"array","items":{"type":"string"}},"intervalSec":{"type":"number"}},"required":["test","intervalSec"],"additionalProperties":false},{"type":"null"}]},"restartPolicy":{"anyOf":[{"type":"object","properties":{"mode":{"type":"string"},"startTimeoutSec":{"type":"number"},"maxRetriesPerNode":{"type":"number"},"maxErrorTolerance":{"type":"number"},"numTasks":{"type":"number"}},"required":["mode","startTimeoutSec","maxRetriesPerNode","maxErrorTolerance","numTasks"],"additionalProperties":false},{"type":"null"}]},"instances":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"}},"required":["min","max"],"additionalProperties":false},"stateful":{"type":"boolean"},"hardware":{"type":"object","properties":{"gpuCount":{"type":"integer"},"gpuModels":{"type":"array","items":{"type":"string"}},"gpuManufacturer":{"type":["string","null"]},"gpuVramBytes":{"type":"number"},"ramBytes":{"type":"number"},"storageBytes":{"type":"number"},"shmemBytes":{"type":"number"}},"required":["gpuCount","gpuModels","gpuManufacturer","gpuVramBytes","ramBytes","storageBytes","shmemBytes"],"additionalProperties":false},"placement":{"type":"object","properties":{"regions":{"type":"array","items":{"type":"string"},"description":"Kinesis regions, e.g. us-west"},"providers":{"type":"array","items":{"type":"object","properties":{"csp":{"type":"string"},"regions":{"type":"array","items":{"type":"object","properties":{"region":{"type":"string"},"zones":{"type":"array","items":{"type":"string"}}},"required":["region","zones"],"additionalProperties":false}}},"required":["csp","regions"],"additionalProperties":false}},"allowedIps":{"type":"array","items":{"type":"string"},"description":"Source IPs or CIDR ranges allowed to reach the app"}},"required":["regions","providers","allowedIps"],"additionalProperties":false},"grids":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}},"priorities":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"},"description":"Priority per grid id"}},"required":["ids","priorities"],"additionalProperties":false},"volumes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"target":{"type":"string"},"declaredSizeBytes":{"type":"number"}},"required":["name","target","declaredSizeBytes"],"additionalProperties":false}},"domains":{"type":"array","items":{"type":"string"},"description":"Custom domains attached to the app (see the domain operations)"}},"required":["image","imageTag","registryUsername","ports","env","command","entrypoint","startupCommand","healthcheck","restartPolicy","instances","stateful","hardware","placement","grids","volumes","domains"],"additionalProperties":false},"AppGitHubSource":{"type":"object","properties":{"installationId":{"type":"integer","description":"GitHub App installation the repository is read through"},"repo":{"type":"string","description":"owner/name"},"url":{"type":"string"},"branch":{"type":"string","description":"Branch that is built and, with autoDeploy, followed"},"contextDir":{"type":"string"},"dockerfilePath":{"description":"Dockerfile path relative to contextDir; not used while dockerfileContent is set","type":["string","null"]},"dockerfileOverride":{"type":"boolean","description":"An inline Dockerfile (dockerfileContent) is built instead of dockerfilePath"},"dockerfileContent":{"description":"The inline Dockerfile that is built; null when the repository's own file is used","type":["string","null"]},"autoDeploy":{"type":"boolean","description":"Every push to the branch rebuilds and redeploys"},"clonedFrom":{"description":"Public repository (owner/name) the app's repository was copied from at creation; null otherwise","type":["string","null"]}},"required":["installationId","repo","url","branch","contextDir","dockerfilePath","dockerfileOverride","dockerfileContent","autoDeploy","clonedFrom"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}":{"get":{"operationId":"apps.get","summary":"Get an app with its full configuration and last known status","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppDetail"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Update the name, alerts, configuration or repository settings of an app. A running app is redeployed with the new configuration; while a GitHub-sourced app is still building, the change is applied by that build. Changing instances, hardware or volumes also needs compute:spend.

> Requires \`apps:write\` (Create, update, start, stop, restart and rebuild apps).\
> \
> Also requires \`compute:spend\` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances) when instances, hardware or volumes change.\
> \
> Also requires \`compute:spend\` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances) when source changes what is built (branch, contextDir, dockerfilePath, dockerfileContent).\
> \
> Errors specific to this operation:\
> \- 409 \`app\_source\_unsupported\`: The app's image is uploaded from the dashboard, or source was given for an image app\
> \- 400 \`grid\_to\_serverless\`: A grid app cannot move back to serverless\
> \- 400 \`no\_suitable\_machines\`: No machine can run the new configuration; lower the hardware requirements\
> \- 400 \`serverless\_gpu\_unavailable\`: The app would ask for a GPU while targeting no grid; serverless placement is CPU-only, so pass grids.ids or set hardware.gpuCount to 0 (a serverless app saved with a GPU earlier is refused on its next update too)\
> \- 429 \`grid\_quota\_exceeded\`: The grids the app targets have no room for it under their per-person app and instance quotas\
> \- 403 \`serverless\_disabled\`: The change needs new serverless machines, or starts a build of a serverless app, and the organization keeps serverless capacity to its admins; target a grid

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"AppUpdateResult":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"projectId":{"type":"string"},"name":{"type":"string"},"guid":{"type":"string","description":"Runtime identifier of the app"},"source":{"description":"Where the image comes from: Docker Hub, a registry link, GitHub or an upload","type":["string","null"]},"image":{"type":["string","null"]},"domain":{"description":"Hostname the app answers on: the default custom domain, else the Kinesis-issued one","type":["string","null"]},"buildState":{"description":"Build pipeline state for GitHub-sourced apps","type":["string","null"]},"access":{"$ref":"#/components/schemas/Access"},"createdBy":{"anyOf":[{"$ref":"#/components/schemas/Person"},{"type":"null"}],"description":"Who created it. Null when nobody is on record, for another organization's, and for a credential without members:read"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"status":{"description":"Status as last cached; use the status endpoint for a live read","$ref":"#/components/schemas/AppStatus"},"config":{"anyOf":[{"$ref":"#/components/schemas/AppConfig"},{"type":"null"}]},"github":{"anyOf":[{"$ref":"#/components/schemas/AppGitHubSource"},{"type":"null"}],"description":"Repository settings of a GitHub-sourced app"},"defaultDomain":{"description":"Custom domain shown as the app's address in the dashboard; null for the Kinesis-issued one","type":["string","null"]},"buildId":{"description":"Build started by a source change; null when nothing was rebuilt","type":["string","null"]}},"required":["id","projectId","name","guid","source","image","domain","buildState","access","createdBy","createdAt","status","config","github","defaultDomain","buildId"],"additionalProperties":false},"Access":{"type":"object","properties":{"role":{"type":"string","enum":["admin","developer","viewer"],"description":"The caller's role on it"},"outside":{"type":"boolean","description":"Shared with the caller from another organization"},"isCreator":{"type":"boolean","description":"The caller created it"}},"required":["role","outside","isCreator"],"additionalProperties":false},"Person":{"type":"object","properties":{"userId":{"type":"string","description":"User id, as members.list and the sharing calls use it"},"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["userId","name","email"],"additionalProperties":false},"AppStatus":{"type":"object","properties":{"state":{"type":"string","enum":["unknown","running","stopped","starting","stopping","scaling","updating","downloading","provisioning","start_blocked","error","building","build_failed"],"description":"Aggregate state; build states win while there is no runnable image"},"targetState":{"type":"string","enum":["running","stopped","unknown"],"description":"What the runtime was last asked for; unknown until it has been asked, as for a repository app before its first build succeeds"},"nodes":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"state":{"type":"string"},"reportedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the server last reported this state; not a start time"}},"required":["address","state","reportedAt"],"additionalProperties":false},"description":"Servers the app is placed on and the container state on each"},"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/AppEndpoint"},"description":"Where each configured port answers; a load-balanced port gets its address a minute or two after the first start"},"errors":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"message":{"type":"string"},"at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"details":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}],"description":"Extra data the runtime attached, such as the grid or server involved"}},"required":["type","message","at","details"],"additionalProperties":false},"description":"Recent runtime errors, newest first"},"workOrders":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"What the runtime asked the server to do"},"server":{"type":"string","description":"Server address"},"status":{"type":"string"},"createdAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"startedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"completedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["type","server","status","createdAt","startedAt","completedAt"],"additionalProperties":false},"description":"The runtime's latest instructions to servers, newest first; an order that never completes is the stall"},"grid":{"anyOf":[{"type":"object","properties":{"fill":{"anyOf":[{"type":"object","properties":{"target":{"type":"integer","description":"Members the grid is composed to have"},"online":{"type":"integer","description":"Members the app runs on"},"pending":{"type":"integer"},"converging":{"type":"boolean","description":"The grid is still acquiring members or placing the app"}},"required":["target","online","pending","converging"],"additionalProperties":false},{"type":"null"}],"description":"How far the grid has filled for this app"},"idleReclaim":{"type":"array","items":{"type":"object","properties":{"gridId":{"type":"string"},"warnedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"evictAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the app becomes evictable; null when the grid only warns"},"evictedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"cooldownEndsAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the grid takes the app again after an eviction"},"evidence":{"type":"string","description":"Why the grid considers the app idle"}},"required":["gridId","warnedAt","evictAt","evictedAt","cooldownEndsAt","evidence"],"additionalProperties":false},"description":"Grids whose idle policy has warned or evicted the app"},"queue":{"type":"array","items":{"type":"object","properties":{"gridId":{"type":"string"},"position":{"type":"integer","description":"1-based place in the grid's fair-share queue"},"queueLength":{"type":"integer"},"enqueuedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"held":{"type":"boolean","description":"The scheduler keeps the app off the grid until its turn comes"}},"required":["gridId","position","queueLength","enqueuedAt","held"],"additionalProperties":false},"description":"Full grids the app is queued on"}},"required":["fill","idleReclaim","queue"],"additionalProperties":false},{"type":"null"}],"description":"Grid placement details; null for a serverless app"},"pollAfterSec":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Seconds to wait before reading the status again while it is changing; null in a settled state"}},"required":["state","targetState","nodes","endpoints","errors","workOrders","grid","pollAfterSec"],"additionalProperties":false},"AppEndpoint":{"type":"object","properties":{"port":{"type":"integer","description":"Container port, as in config.ports"},"protocol":{"type":"string","description":"Protocol of that port, as in config.ports"},"address":{"description":"An http(s) URL for the HTTP protocols, host:port for the others; null until the endpoint is wired","type":["string","null"]},"server":{"description":"Server address of a direct tcp or udp endpoint; null when load-balanced","type":["string","null"]}},"required":["port","protocol","address","server"],"additionalProperties":false},"AppConfig":{"type":"object","properties":{"image":{"type":"string","description":"Container image reference"},"imageTag":{"description":"Tag, kept separately for Docker Hub images","type":["string","null"]},"registryUsername":{"description":"Registry login; the password is write-only","type":["string","null"]},"ports":{"type":"array","items":{"type":"object","properties":{"port":{"type":"integer"},"protocol":{"type":"string"}},"required":["port","protocol"],"additionalProperties":false}},"env":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":["string","null"]},"secret":{"type":"boolean"}},"required":["key","value","secret"],"additionalProperties":false},"description":"Environment variables; value is null for secrets, and on a connection that takes no credentials for values that look like one (null keeps a value on update)"},"command":{"type":"array","items":{"type":"string"}},"entrypoint":{"type":"array","items":{"type":"string"}},"startupCommand":{"anyOf":[{"type":"object","properties":{"args":{"type":"array","items":{"type":"string"}},"user":{"type":"string"},"timeoutSec":{"type":"number"},"startPeriodSec":{"type":"number"}},"required":["args","user","timeoutSec","startPeriodSec"],"additionalProperties":false},{"type":"null"}]},"healthcheck":{"anyOf":[{"type":"object","properties":{"test":{"type":"array","items":{"type":"string"}},"intervalSec":{"type":"number"}},"required":["test","intervalSec"],"additionalProperties":false},{"type":"null"}]},"restartPolicy":{"anyOf":[{"type":"object","properties":{"mode":{"type":"string"},"startTimeoutSec":{"type":"number"},"maxRetriesPerNode":{"type":"number"},"maxErrorTolerance":{"type":"number"},"numTasks":{"type":"number"}},"required":["mode","startTimeoutSec","maxRetriesPerNode","maxErrorTolerance","numTasks"],"additionalProperties":false},{"type":"null"}]},"instances":{"type":"object","properties":{"min":{"type":"integer"},"max":{"type":"integer"}},"required":["min","max"],"additionalProperties":false},"stateful":{"type":"boolean"},"hardware":{"type":"object","properties":{"gpuCount":{"type":"integer"},"gpuModels":{"type":"array","items":{"type":"string"}},"gpuManufacturer":{"type":["string","null"]},"gpuVramBytes":{"type":"number"},"ramBytes":{"type":"number"},"storageBytes":{"type":"number"},"shmemBytes":{"type":"number"}},"required":["gpuCount","gpuModels","gpuManufacturer","gpuVramBytes","ramBytes","storageBytes","shmemBytes"],"additionalProperties":false},"placement":{"type":"object","properties":{"regions":{"type":"array","items":{"type":"string"},"description":"Kinesis regions, e.g. us-west"},"providers":{"type":"array","items":{"type":"object","properties":{"csp":{"type":"string"},"regions":{"type":"array","items":{"type":"object","properties":{"region":{"type":"string"},"zones":{"type":"array","items":{"type":"string"}}},"required":["region","zones"],"additionalProperties":false}}},"required":["csp","regions"],"additionalProperties":false}},"allowedIps":{"type":"array","items":{"type":"string"},"description":"Source IPs or CIDR ranges allowed to reach the app"}},"required":["regions","providers","allowedIps"],"additionalProperties":false},"grids":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}},"priorities":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"},"description":"Priority per grid id"}},"required":["ids","priorities"],"additionalProperties":false},"volumes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"target":{"type":"string"},"declaredSizeBytes":{"type":"number"}},"required":["name","target","declaredSizeBytes"],"additionalProperties":false}},"domains":{"type":"array","items":{"type":"string"},"description":"Custom domains attached to the app (see the domain operations)"}},"required":["image","imageTag","registryUsername","ports","env","command","entrypoint","startupCommand","healthcheck","restartPolicy","instances","stateful","hardware","placement","grids","volumes","domains"],"additionalProperties":false},"AppGitHubSource":{"type":"object","properties":{"installationId":{"type":"integer","description":"GitHub App installation the repository is read through"},"repo":{"type":"string","description":"owner/name"},"url":{"type":"string"},"branch":{"type":"string","description":"Branch that is built and, with autoDeploy, followed"},"contextDir":{"type":"string"},"dockerfilePath":{"description":"Dockerfile path relative to contextDir; not used while dockerfileContent is set","type":["string","null"]},"dockerfileOverride":{"type":"boolean","description":"An inline Dockerfile (dockerfileContent) is built instead of dockerfilePath"},"dockerfileContent":{"description":"The inline Dockerfile that is built; null when the repository's own file is used","type":["string","null"]},"autoDeploy":{"type":"boolean","description":"Every push to the branch rebuilds and redeploys"},"clonedFrom":{"description":"Public repository (owner/name) the app's repository was copied from at creation; null otherwise","type":["string","null"]}},"required":["installationId","repo","url","branch","contextDir","dockerfilePath","dockerfileOverride","dockerfileContent","autoDeploy","clonedFrom"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}":{"patch":{"operationId":"apps.update","summary":"Update the name, alerts, configuration or repository settings of an app. A running app is redeployed with the new configuration; while a GitHub-sourced app is still building, the change is applied by that build. Changing instances, hardware or volumes also needs compute:spend.","description":"Requires `apps:write` (Create, update, start, stop, restart and rebuild apps).\n\nAlso requires `compute:spend` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances) when instances, hardware or volumes change.\n\nAlso requires `compute:spend` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances) when source changes what is built (branch, contextDir, dockerfilePath, dockerfileContent).\n\nErrors specific to this operation:\n- 409 `app_source_unsupported`: The app's image is uploaded from the dashboard, or source was given for an image app\n- 400 `grid_to_serverless`: A grid app cannot move back to serverless\n- 400 `no_suitable_machines`: No machine can run the new configuration; lower the hardware requirements\n- 400 `serverless_gpu_unavailable`: The app would ask for a GPU while targeting no grid; serverless placement is CPU-only, so pass grids.ids or set hardware.gpuCount to 0 (a serverless app saved with a GPU earlier is refused on its next update too)\n- 429 `grid_quota_exceeded`: The grids the app targets have no room for it under their per-person app and instance quotas\n- 403 `serverless_disabled`: The change needs new serverless machines, or starts a build of a serverless app, and the organization keeps serverless capacity to its admins; target a grid","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"New app name","type":"string","minLength":1,"maxLength":100},"alerts":{"description":"Health-check email alerts","type":"object","properties":{"enabled":{"type":"boolean","description":"Send an email when the app is unhealthy"},"emails":{"maxItems":10,"type":"array","items":{"type":"string","format":"email"},"description":"Recipients"},"delayMinutes":{"type":"integer","minimum":0,"maximum":30,"description":"Minutes the app must stay unhealthy before an email"}},"required":["enabled","emails","delayMinutes"],"additionalProperties":false},"config":{"description":"Configuration changes; list fields replace the stored list, object fields merge per key","type":"object","properties":{"image":{"description":"Container image reference, e.g. nginx:1.27 or ghcr.io/org/app:tag","type":"string","minLength":1,"maxLength":512},"registryAuth":{"description":"Credentials for a private image","type":"object","properties":{"username":{"type":"string","minLength":1,"description":"Registry login"},"password":{"type":"string","minLength":1,"description":"Registry password or token (write-only)"}},"required":["username","password"],"additionalProperties":false},"ports":{"description":"Ports to expose","maxItems":32,"type":"array","items":{"type":"object","properties":{"port":{"type":"integer","minimum":1,"maximum":65535,"description":"Container port"},"protocol":{"type":"string","enum":["tcp","udp","tcp_load_balancer","tcps_load_balancer","http_load_balancer","https_load_balancer","http80_load_balancer","https443_load_balancer","grpcs_load_balancer"],"description":"How the port is exposed"}},"required":["port","protocol"]}},"env":{"description":"Environment variables","maxItems":200,"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Za-z_][A-Za-z0-9_]*$","description":"Variable name"},"value":{"description":"Value; null keeps the stored value of an existing variable","type":["string","null"]},"secret":{"description":"Store as a secret: never returned by reads","type":"boolean"}},"required":["key","value"]}},"command":{"description":"Container command (CMD) override","maxItems":256,"type":"array","items":{"type":"string"}},"entrypoint":{"description":"Container entrypoint override","maxItems":256,"type":"array","items":{"type":"string"}},"startupCommand":{"description":"Command run inside the container once it starts; null clears it","anyOf":[{"type":"object","properties":{"args":{"minItems":1,"type":"array","items":{"type":"string"},"description":"Command and arguments"},"user":{"description":"User to run as","type":"string"},"timeoutSec":{"description":"Seconds before the command is considered failed","type":"integer","minimum":0},"startPeriodSec":{"description":"Seconds to wait after the container starts","type":"integer","minimum":0}},"required":["args"],"additionalProperties":false},{"type":"null"}]},"healthcheck":{"description":"Container health check; null clears it","anyOf":[{"type":"object","properties":{"test":{"minItems":1,"type":"array","items":{"type":"string"},"description":"Command that must exit 0 for the app to count as healthy"},"intervalSec":{"type":"integer","minimum":1,"description":"Seconds between checks"}},"required":["test","intervalSec"],"additionalProperties":false},{"type":"null"}]},"restartPolicy":{"description":"Restart behaviour","type":"object","properties":{"mode":{"type":"string","enum":["disabled","always","on_failure","task_completion"],"description":"When to restart a container that exits"},"startTimeoutSec":{"description":"Seconds a start may take before it counts as failed","type":"integer","minimum":0},"maxRetriesPerNode":{"description":"Restarts allowed on one server before moving on","type":"integer","minimum":0},"maxErrorTolerance":{"description":"Failures tolerated before the app is stopped","type":"integer","minimum":0},"numTasks":{"description":"For task_completion: runs to complete before stopping","type":"integer","minimum":0}},"required":["mode"],"additionalProperties":false},"instances":{"description":"Instance count range","type":"object","properties":{"min":{"type":"integer","minimum":0,"description":"Instances to keep running"},"max":{"type":"integer","minimum":0,"description":"Upper bound for scaling"}},"required":["min","max"],"additionalProperties":false},"stateful":{"description":"Keep each instance pinned to its server and disk","type":"boolean"},"hardware":{"description":"Hardware requirements per instance","type":"object","properties":{"gpuCount":{"description":"GPUs per instance; 0 for CPU-only. Above 0 needs grids.ids: serverless placement is CPU-only","type":"integer","minimum":0,"maximum":16},"gpuModels":{"description":"Acceptable GPU models, e.g. H100; empty means any","maxItems":16,"type":"array","items":{"type":"string","minLength":1}},"gpuManufacturer":{"description":"GPU vendor; null means any","anyOf":[{"type":"string","enum":["amd","apple","intel","nvidia","xilinx"]},{"type":"null"}]},"gpuVramBytes":{"description":"Minimum VRAM per GPU, in bytes","type":"integer","minimum":0},"ramBytes":{"description":"RAM per instance, in bytes","type":"integer","exclusiveMinimum":0},"storageBytes":{"description":"Disk per instance, in bytes","type":"integer","exclusiveMinimum":0},"shmemBytes":{"description":"Shared memory (/dev/shm) size, in bytes","type":"integer","minimum":0}},"additionalProperties":false},"placement":{"description":"Where the app may run and who may reach it","type":"object","properties":{"regions":{"description":"Kinesis regions to run in; empty means any","type":"array","items":{"type":"string","enum":["us-west","us-east","us-central","ca-west","ca-east","ca-central","eu-west","eu-north","eu-east","eu-south","eu-central","eu-south-east","ap-east","ap-south-east","ap-north-east","ap-south"]}},"providers":{"description":"Restrict placement to specific providers and regions","type":"array","items":{"type":"object","properties":{"csp":{"type":"string","enum":["aws","azure","gcp","kinesis"],"description":"Cloud provider"},"regions":{"type":"array","items":{"type":"object","properties":{"region":{"type":"string","minLength":1,"description":"Provider region"},"zones":{"type":"array","items":{"type":"string"},"description":"Zones within the region; empty means any"}},"required":["region","zones"],"additionalProperties":false},"description":"Regions of the provider to allow"}},"required":["csp","regions"],"additionalProperties":false}},"allowedIps":{"description":"Source IPs or CIDR ranges allowed to reach the app; empty means everyone","maxItems":100,"type":"array","items":{"type":"string"}}},"additionalProperties":false},"grids":{"description":"Run on grids instead of serverless capacity (members only, on grids they may deploy to)","type":"object","properties":{"ids":{"description":"Grids to run on; empty means serverless (CPU-only), so a GPU app names at least one","maxItems":20,"type":"array","items":{"type":"string","minLength":1}},"priorities":{"description":"Priority per grid id, -100 to 100","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","minimum":-100,"maximum":100}}},"additionalProperties":false},"volumes":{"description":"Persistent volumes","maxItems":4,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.-]{1,63}$","description":"Volume name, unique within the app"},"target":{"type":"string","pattern":"^\\/.+","description":"Absolute mount path inside the container"},"declaredSizeBytes":{"description":"Expected size, used for placement; 0 or omitted means unspecified","type":"integer","minimum":0,"maximum":17592186044416}},"required":["name","target"],"additionalProperties":false}}},"additionalProperties":false},"source":{"description":"Repository settings of a GitHub-sourced app (members of the project's organization); a change to the branch, directories or Dockerfile starts a rebuild","type":"object","properties":{"branch":{"description":"Branch to build and follow; default: the repository's default branch","type":"string","minLength":1,"maxLength":255},"contextDir":{"description":"Directory the image is built from, relative to the repository root (default /)","type":"string","minLength":1,"maxLength":512},"dockerfilePath":{"description":"Dockerfile path relative to contextDir (default Dockerfile)","type":"string","minLength":1,"maxLength":512},"autoDeploy":{"description":"Rebuild and redeploy on every push to the branch (default true)","type":"boolean"},"dockerfileContent":{"description":"Inline Dockerfile used instead of dockerfilePath; null goes back to the file in the repository","anyOf":[{"type":"string","maxLength":65536},{"type":"null"}]}},"additionalProperties":false}}}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppUpdateResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Delete a stopped app (admins, or its creator). Fails with app\_running while any node is still live. Irreversible.

> Requires \`apps:admin\` (Delete or move apps and manage who they are shared with).\
> \
> Errors specific to this operation:\
> \- 409 \`app\_running\`: A node is still running or stopping the app; stop it and retry once the status reports stopped

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}}},"paths":{"/projects/{projectId}/apps/{appId}":{"delete":{"operationId":"apps.delete","summary":"Delete a stopped app (admins, or its creator). Fails with app_running while any node is still live. Irreversible.","description":"Requires `apps:admin` (Delete or move apps and manage who they are shared with).\n\nErrors specific to this operation:\n- 409 `app_running`: A node is still running or stopping the app; stop it and retry once the status reports stopped","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Id of the deleted app"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Read the live status of an app from the runtime. Aggregate state, each server's container state, where each port answers, recent errors. Poll this after start, stop or delete.

> Requires \`apps:read\` (View apps, their configuration and status).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"AppEndpoint":{"type":"object","properties":{"port":{"type":"integer","description":"Container port, as in config.ports"},"protocol":{"type":"string","description":"Protocol of that port, as in config.ports"},"address":{"description":"An http(s) URL for the HTTP protocols, host:port for the others; null until the endpoint is wired","type":["string","null"]},"server":{"description":"Server address of a direct tcp or udp endpoint; null when load-balanced","type":["string","null"]}},"required":["port","protocol","address","server"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}/status":{"get":{"operationId":"apps.status","summary":"Read the live status of an app from the runtime. Aggregate state, each server's container state, where each port answers, recent errors. Poll this after start, stop or delete.","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"state":{"type":"string","enum":["unknown","running","stopped","starting","stopping","scaling","updating","downloading","provisioning","start_blocked","error","building","build_failed"],"description":"Aggregate state; build states win while there is no runnable image"},"targetState":{"type":"string","enum":["running","stopped","unknown"],"description":"What the runtime was last asked for; unknown until it has been asked, as for a repository app before its first build succeeds"},"nodes":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"state":{"type":"string"},"reportedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the server last reported this state; not a start time"}},"required":["address","state","reportedAt"],"additionalProperties":false},"description":"Servers the app is placed on and the container state on each"},"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/AppEndpoint"},"description":"Where each configured port answers; a load-balanced port gets its address a minute or two after the first start"},"errors":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"message":{"type":"string"},"at":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"details":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}],"description":"Extra data the runtime attached, such as the grid or server involved"}},"required":["type","message","at","details"],"additionalProperties":false},"description":"Recent runtime errors, newest first"},"workOrders":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"What the runtime asked the server to do"},"server":{"type":"string","description":"Server address"},"status":{"type":"string"},"createdAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"startedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"completedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]}},"required":["type","server","status","createdAt","startedAt","completedAt"],"additionalProperties":false},"description":"The runtime's latest instructions to servers, newest first; an order that never completes is the stall"},"grid":{"anyOf":[{"type":"object","properties":{"fill":{"anyOf":[{"type":"object","properties":{"target":{"type":"integer","description":"Members the grid is composed to have"},"online":{"type":"integer","description":"Members the app runs on"},"pending":{"type":"integer"},"converging":{"type":"boolean","description":"The grid is still acquiring members or placing the app"}},"required":["target","online","pending","converging"],"additionalProperties":false},{"type":"null"}],"description":"How far the grid has filled for this app"},"idleReclaim":{"type":"array","items":{"type":"object","properties":{"gridId":{"type":"string"},"warnedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"evictAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the app becomes evictable; null when the grid only warns"},"evictedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"cooldownEndsAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}],"description":"When the grid takes the app again after an eviction"},"evidence":{"type":"string","description":"Why the grid considers the app idle"}},"required":["gridId","warnedAt","evictAt","evictedAt","cooldownEndsAt","evidence"],"additionalProperties":false},"description":"Grids whose idle policy has warned or evicted the app"},"queue":{"type":"array","items":{"type":"object","properties":{"gridId":{"type":"string"},"position":{"type":"integer","description":"1-based place in the grid's fair-share queue"},"queueLength":{"type":"integer"},"enqueuedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"held":{"type":"boolean","description":"The scheduler keeps the app off the grid until its turn comes"}},"required":["gridId","position","queueLength","enqueuedAt","held"],"additionalProperties":false},"description":"Full grids the app is queued on"}},"required":["fill","idleReclaim","queue"],"additionalProperties":false},{"type":"null"}],"description":"Grid placement details; null for a serverless app"},"pollAfterSec":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Seconds to wait before reading the status again while it is changing; null in a settled state"},"id":{"type":"string","description":"App id"}},"required":["state","targetState","nodes","endpoints","errors","workOrders","grid","pollAfterSec","id"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Check which servers could run an existing app: with its stored configuration, or with config layered on top to test a change before update\_app. Nothing is changed.

> Requires \`apps:read\` (View apps, their configuration and status).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"Placement":{"type":"object","properties":{"placeable":{"type":"boolean","description":"A server can take the app now, a hibernated one would fit once woken, or one can be provisioned"},"serversWithCapacity":{"type":"integer","description":"Servers that match and have room now"},"serversWithoutCapacity":{"type":"integer","description":"Servers that match but are full"},"wakeable":{"type":"integer","description":"Hibernated servers that would match once woken (power_servers wake, or the automatic wake-up on start)"},"wakeableAwaitingStock":{"type":"integer","description":"Of wakeable, servers whose provider has no stock right now, so a wake would not land yet"},"provisionable":{"type":"boolean","description":"The platform can provision a matching cloud machine on demand for a serverless app"},"rejections":{"type":"array","items":{"type":"object","properties":{"server":{"type":"string","description":"Server address"},"reason":{"type":"string"}},"required":["server","reason"],"additionalProperties":false},"description":"Why sampled servers cannot take the app; each distinct reason appears first, then repeats"}},"required":["placeable","serversWithCapacity","serversWithoutCapacity","wakeable","wakeableAwaitingStock","provisionable","rejections"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}/placement":{"post":{"operationId":"apps.placement","summary":"Check which servers could run an existing app: with its stored configuration, or with config layered on top to test a change before update_app. Nothing is changed.","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"config":{"description":"Changes to test, merged over the app's stored configuration","type":"object","properties":{"instances":{"description":"Instance count range","type":"object","properties":{"min":{"type":"integer","minimum":0,"description":"Instances to keep running"},"max":{"type":"integer","minimum":0,"description":"Upper bound for scaling"}},"required":["min","max"],"additionalProperties":false},"stateful":{"description":"Keep each instance pinned to its server and disk","type":"boolean"},"hardware":{"description":"Hardware requirements per instance","type":"object","properties":{"gpuCount":{"description":"GPUs per instance; 0 for CPU-only. Above 0 needs grids.ids: serverless placement is CPU-only","type":"integer","minimum":0,"maximum":16},"gpuModels":{"description":"Acceptable GPU models, e.g. H100; empty means any","maxItems":16,"type":"array","items":{"type":"string","minLength":1}},"gpuManufacturer":{"description":"GPU vendor; null means any","anyOf":[{"type":"string","enum":["amd","apple","intel","nvidia","xilinx"]},{"type":"null"}]},"gpuVramBytes":{"description":"Minimum VRAM per GPU, in bytes","type":"integer","minimum":0},"ramBytes":{"description":"RAM per instance, in bytes","type":"integer","exclusiveMinimum":0},"storageBytes":{"description":"Disk per instance, in bytes","type":"integer","exclusiveMinimum":0},"shmemBytes":{"description":"Shared memory (/dev/shm) size, in bytes","type":"integer","minimum":0}},"additionalProperties":false},"placement":{"description":"Where the app may run and who may reach it","type":"object","properties":{"regions":{"description":"Kinesis regions to run in; empty means any","type":"array","items":{"type":"string","enum":["us-west","us-east","us-central","ca-west","ca-east","ca-central","eu-west","eu-north","eu-east","eu-south","eu-central","eu-south-east","ap-east","ap-south-east","ap-north-east","ap-south"]}},"providers":{"description":"Restrict placement to specific providers and regions","type":"array","items":{"type":"object","properties":{"csp":{"type":"string","enum":["aws","azure","gcp","kinesis"],"description":"Cloud provider"},"regions":{"type":"array","items":{"type":"object","properties":{"region":{"type":"string","minLength":1,"description":"Provider region"},"zones":{"type":"array","items":{"type":"string"},"description":"Zones within the region; empty means any"}},"required":["region","zones"],"additionalProperties":false},"description":"Regions of the provider to allow"}},"required":["csp","regions"],"additionalProperties":false}},"allowedIps":{"description":"Source IPs or CIDR ranges allowed to reach the app; empty means everyone","maxItems":100,"type":"array","items":{"type":"string"}}},"additionalProperties":false},"grids":{"description":"Run on grids instead of serverless capacity (members only, on grids they may deploy to)","type":"object","properties":{"ids":{"description":"Grids to run on; empty means serverless (CPU-only), so a GPU app names at least one","maxItems":20,"type":"array","items":{"type":"string","minLength":1}},"priorities":{"description":"Priority per grid id, -100 to 100","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","minimum":-100,"maximum":100}}},"additionalProperties":false},"volumes":{"description":"Persistent volumes","maxItems":4,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.-]{1,63}$","description":"Volume name, unique within the app"},"target":{"type":"string","pattern":"^\\/.+","description":"Absolute mount path inside the container"},"declaredSizeBytes":{"description":"Expected size, used for placement; 0 or omitted means unspecified","type":"integer","minimum":0,"maximum":17592186044416}},"required":["name","target"],"additionalProperties":false}}},"additionalProperties":false}}}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Placement"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Ask the runtime to start an app. Returns once the request is accepted; poll the status to follow it.

> Requires \`apps:write\` (Create, update, start, stop, restart and rebuild apps), \`compute:spend\` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances).\
> \
> Errors specific to this operation:\
> \- 402 \`balance\_over\_limit\`: The organization's balance is below the allowed negative limit; add credits and retry\
> \- 429 \`grid\_quota\_exceeded\`: The grids the app targets have no room for it under their per-person app and instance quotas\
> \- 403 \`serverless\_disabled\`: The app would run on Kinesis serverless capacity, which the organization keeps to its admins; target a grid

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PaymentRequired":{"description":"The balance or the card does not cover the action: insufficient_balance, balance_over_limit, card_declined, authentication_required or blocked_by_risk","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}}},"paths":{"/projects/{projectId}/apps/{appId}/start":{"post":{"operationId":"apps.start","summary":"Ask the runtime to start an app. Returns once the request is accepted; poll the status to follow it.","description":"Requires `apps:write` (Create, update, start, stop, restart and rebuild apps), `compute:spend` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances).\n\nErrors specific to this operation:\n- 402 `balance_over_limit`: The organization's balance is below the allowed negative limit; add credits and retry\n- 429 `grid_quota_exceeded`: The grids the app targets have no room for it under their per-person app and instance quotas\n- 403 `serverless_disabled`: The app would run on Kinesis serverless capacity, which the organization keeps to its admins; target a grid","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"responses":{"202":{"description":"Accepted","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"targetState":{"type":"string","enum":["running","stopped"],"description":"State the runtime is now converging on"}},"required":["id","targetState"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Ask the runtime to stop an app. Returns once the request is accepted; poll the status to follow it.

> Requires \`apps:write\` (Create, update, start, stop, restart and rebuild apps).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}}},"paths":{"/projects/{projectId}/apps/{appId}/stop":{"post":{"operationId":"apps.stop","summary":"Ask the runtime to stop an app. Returns once the request is accepted; poll the status to follow it.","description":"Requires `apps:write` (Create, update, start, stop, restart and rebuild apps).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"responses":{"202":{"description":"Accepted","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"targetState":{"type":"string","enum":["running","stopped"],"description":"State the runtime is now converging on"}},"required":["id","targetState"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Stop an app, wait for it to report stopped, then start it again. Waits up to waitSec (default 30); if the app is still stopping by then the start is issued anyway. Poll the status to follow the start.

> Requires \`apps:write\` (Create, update, start, stop, restart and rebuild apps), \`compute:spend\` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances).\
> \
> Errors specific to this operation:\
> \- 402 \`balance\_over\_limit\`: The organization's balance is below the allowed negative limit; add credits and retry\
> \- 429 \`grid\_quota\_exceeded\`: The grids the app targets have no room for it under their per-person app and instance quotas\
> \- 403 \`serverless\_disabled\`: The app would run on Kinesis serverless capacity, which the organization keeps to its admins; target a grid

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PaymentRequired":{"description":"The balance or the card does not cover the action: insufficient_balance, balance_over_limit, card_declined, authentication_required or blocked_by_risk","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}}},"paths":{"/projects/{projectId}/apps/{appId}/restart":{"post":{"operationId":"apps.restart","summary":"Stop an app, wait for it to report stopped, then start it again. Waits up to waitSec (default 30); if the app is still stopping by then the start is issued anyway. Poll the status to follow the start.","description":"Requires `apps:write` (Create, update, start, stop, restart and rebuild apps), `compute:spend` (Spend credits: start, scale or resize apps, provision or wake servers, rent spot instances).\n\nErrors specific to this operation:\n- 402 `balance_over_limit`: The organization's balance is below the allowed negative limit; add credits and retry\n- 429 `grid_quota_exceeded`: The grids the app targets have no room for it under their per-person app and instance quotas\n- 403 `serverless_disabled`: The app would run on Kinesis serverless capacity, which the organization keeps to its admins; target a grid","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"waitSec":{"description":"Seconds to wait for the stop before starting, 0 to 180 (default 30)","type":"integer","minimum":0,"maximum":180}}}}}},"responses":{"202":{"description":"Accepted","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"targetState":{"type":"string","const":"running","description":"State the runtime is now converging on"},"stoppedBeforeStart":{"type":"boolean","description":"The app reported stopped before the start was issued; false when the wait ran out"},"waitedSec":{"type":"integer","description":"Seconds spent waiting for the stop"}},"required":["id","targetState","stoppedBeforeStart","waitedSec"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Read a page of container logs for an app. Paging starts at the newest lines and moves back in time by default; inside a page, chunks and lines run oldest to newest, so the last line is the most recent. Lines are the app's own output, as it wrote them, so they can hold anything it prints, sensitive data included.

> Requires \`monitoring:read\` (Read usage metrics, app logs, build logs and server logs).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"AppLogs":{"type":"object","properties":{"logs":{"type":"array","items":{"type":"object","properties":{"node":{"type":"string","description":"Server address the lines came from"},"from":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"to":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"lines":{"type":"array","items":{"type":"string"}}},"required":["node","from","to","lines"],"additionalProperties":false},"description":"Chunks in chronological order, consecutive lines from one server merged into a chunk that from and to span; the last line of the last chunk is the newest"},"nextCursorNs":{"description":"Pass as cursorNs to fetch the next page in the same direction; null at the end","type":["string","null"]},"hasMore":{"type":"boolean"},"totalLines":{"type":"integer","description":"Lines in this page across every chunk"}},"required":["logs","nextCursorNs","hasMore","totalLines"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}/logs":{"get":{"operationId":"apps.logs","summary":"Read a page of container logs for an app. Paging starts at the newest lines and moves back in time by default; inside a page, chunks and lines run oldest to newest, so the last line is the most recent. Lines are the app's own output, as it wrote them, so they can hold anything it prints, sensitive data included.","description":"Requires `monitoring:read` (Read usage metrics, app logs, build logs and server logs).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"nodes","in":"query","required":false,"description":"Server addresses to read from; omit for every server the app ran on","schema":{"maxItems":50,"type":"array","items":{"type":"string","minLength":1}},"style":"form","explode":true},{"name":"cursorNs","in":"query","required":false,"description":"Cursor from a previous page (nextCursorNs)","schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"description":"Unix time in milliseconds to seek to when no cursorNs is given; 0 or omitted means now","schema":{"type":"integer","minimum":0}},{"name":"pageSize","in":"query","required":false,"description":"Lines per page, at most 1000 (default 200)","schema":{"type":"integer","minimum":1,"maximum":1000}},{"name":"direction","in":"query","required":false,"description":"Which way the next page moves from the cursor: older (the default) or newer. Lines inside a page are always chronological","schema":{"type":"string","enum":["older","newer"]}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppLogs"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Resource usage of an app over a time range, bucketed per server

> Requires \`monitoring:read\` (Read usage metrics, app logs, build logs and server logs).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"AppUsage":{"type":"object","properties":{"start":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"end":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"intervalSeconds":{"type":"integer","description":"Width of each bucket"},"series":{"type":"array","items":{"type":"object","properties":{"node":{"type":"string","description":"Server address"},"points":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string","format":"date-time","description":"Bucket start"},"cpuNs":{"type":"number","description":"CPU time consumed, in nanoseconds"},"gpuNs":{"type":"number","description":"GPU time consumed, in nanoseconds"},"gpuMemBytesSecs":{"type":"number","description":"GPU memory held, in byte-seconds"},"memBytesSecs":{"type":"number","description":"RAM held, in byte-seconds"},"storageBytesSecs":{"type":"number","description":"Disk held, in byte-seconds"},"logStorageBytesSecs":{"type":"number","description":"Log storage held, in byte-seconds"},"bwInBytes":{"type":"number","description":"Bytes received"},"bwOutBytes":{"type":"number","description":"Bytes sent"}},"required":["at","cpuNs","gpuNs","gpuMemBytesSecs","memBytesSecs","storageBytesSecs","logStorageBytesSecs","bwInBytes","bwOutBytes"],"additionalProperties":false}}},"required":["node","points"],"additionalProperties":false},"description":"One series per server the app ran on; each point sums the bucket"}},"required":["start","end","intervalSeconds","series"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}/usage":{"get":{"operationId":"apps.usage","summary":"Resource usage of an app over a time range, bucketed per server","description":"Requires `monitoring:read` (Read usage metrics, app logs, build logs and server logs).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"start","in":"query","required":false,"description":"Range start (ISO 8601); defaults to one hour before end","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","required":false,"description":"Range end (ISO 8601); defaults to now. At most 30 days after start","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppUsage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Move an app to another project of its organization. Admins may, and so may the app's creator. Nothing about the app itself changes.

> Requires \`apps:admin\` (Delete or move apps and manage who they are shared with).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"App":{"type":"object","properties":{"id":{"type":"string","description":"App id"},"projectId":{"type":"string"},"name":{"type":"string"},"guid":{"type":"string","description":"Runtime identifier of the app"},"source":{"description":"Where the image comes from: Docker Hub, a registry link, GitHub or an upload","type":["string","null"]},"image":{"type":["string","null"]},"domain":{"description":"Hostname the app answers on: the default custom domain, else the Kinesis-issued one","type":["string","null"]},"buildState":{"description":"Build pipeline state for GitHub-sourced apps","type":["string","null"]},"access":{"$ref":"#/components/schemas/Access"},"createdBy":{"anyOf":[{"$ref":"#/components/schemas/Person"},{"type":"null"}],"description":"Who created it. Null when nobody is on record, for another organization's, and for a credential without members:read"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"}},"required":["id","projectId","name","guid","source","image","domain","buildState","access","createdBy","createdAt"],"additionalProperties":false},"Access":{"type":"object","properties":{"role":{"type":"string","enum":["admin","developer","viewer"],"description":"The caller's role on it"},"outside":{"type":"boolean","description":"Shared with the caller from another organization"},"isCreator":{"type":"boolean","description":"The caller created it"}},"required":["role","outside","isCreator"],"additionalProperties":false},"Person":{"type":"object","properties":{"userId":{"type":"string","description":"User id, as members.list and the sharing calls use it"},"name":{"type":["string","null"]},"email":{"type":"string"}},"required":["userId","name","email"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}/move":{"post":{"operationId":"apps.move","summary":"Move an app to another project of its organization. Admins may, and so may the app's creator. Nothing about the app itself changes.","description":"Requires `apps:admin` (Delete or move apps and manage who they are shared with).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targetProjectId":{"type":"string","pattern":"^[0-9a-fA-F]{24}$","description":"Project to move the app into"}},"required":["targetProjectId"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/App"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## How long the app's container logs are kept

> Requires \`apps:read\` (View apps, their configuration and status).

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"LogRetention":{"type":"object","properties":{"days":{"type":"integer","description":"How many days of container logs are kept"},"isDefault":{"type":"boolean","description":"The platform default applies; no per-app setting"}},"required":["days","isDefault"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}/logs/retention":{"get":{"operationId":"apps.logs.retention.get","summary":"How long the app's container logs are kept","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogRetention"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Set how many days the app's container logs are kept. 1 to 180; 0 goes back to the platform default

> Requires \`apps:write\` (Create, update, start, stop, restart and rebuild apps).\
> \
> Errors specific to this operation:\
> \- 429 \`too\_many\_attempts\`: More than three log changes in a minute

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"schemas":{"LogRetention":{"type":"object","properties":{"days":{"type":"integer","description":"How many days of container logs are kept"},"isDefault":{"type":"boolean","description":"The platform default applies; no per-app setting"}},"required":["days","isDefault"],"additionalProperties":false},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/projects/{projectId}/apps/{appId}/logs/retention":{"patch":{"operationId":"apps.logs.retention.update","summary":"Set how many days the app's container logs are kept. 1 to 180; 0 goes back to the platform default","description":"Requires `apps:write` (Create, update, start, stop, restart and rebuild apps).\n\nErrors specific to this operation:\n- 429 `too_many_attempts`: More than three log changes in a minute","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"days":{"type":"integer","minimum":0,"maximum":180,"description":"Days to keep; 0 for the default"}},"required":["days"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogRetention"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## Delete the app's container logs older than a point in time. Cannot be undone.

> Requires \`apps:write\` (Create, update, start, stop, restart and rebuild apps).\
> \
> Errors specific to this operation:\
> \- 429 \`too\_many\_attempts\`: More than three log changes in a minute

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The resource is in a state that does not allow the action, or an idempotency key was reused","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request body exceeds the limit given in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}}},"paths":{"/projects/{projectId}/apps/{appId}/logs/clear":{"post":{"operationId":"apps.logs.clear","summary":"Delete the app's container logs older than a point in time. Cannot be undone.","description":"Requires `apps:write` (Create, update, start, stop, restart and rebuild apps).\n\nErrors specific to this operation:\n- 429 `too_many_attempts`: More than three log changes in a minute","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"olderThan":{"type":"string","format":"date-time","description":"Lines before this instant are deleted"}},"required":["olderThan"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"deletedCount":{"type":"integer","description":"Lines deleted"}},"required":["deletedCount"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```

## The app's container logs as one text, oldest first. Every line is stamped with its time and server, up to maxBytes (1 MiB by default, 4 MiB at most). For a page at a time use apps.logs instead. Lines are the app's own output, as it wrote them, so they can hold anything it prints, sensitive data included.

> Requires \`monitoring:read\` (Read usage metrics, app logs, build logs and server logs).\
> \
> Errors specific to this operation:\
> \- 429 \`too\_many\_attempts\`: More than three log changes in a minute

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Apps"}],"servers":[{"url":"https://api.kinesis.network/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Account settings, e.g. kn_..."}},"headers":{"RequestId":{"description":"Id of this request; quote it when contacting support","schema":{"type":"string"}},"RateLimitLimit":{"description":"Requests per minute allowed for this key, or for the user across all keys, whichever is lower","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left in the current window","schema":{"type":"integer"}},"RateLimitReset":{"description":"Unix time in seconds when the window resets","schema":{"type":"integer"}},"RetryAfter":{"description":"Seconds to wait before retrying","schema":{"type":"integer"}}},"responses":{"BadRequest":{"description":"The request body, query or headers are invalid (invalid_request, invalid_idempotency_key, ...)","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The API key is missing, malformed, unknown, revoked or expired","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks a required permission (insufficient_scope), is limited to other projects or to projects while the call acts on the organization (key_project_restricted), the caller's role on the resource is too low (forbidden), or the account is frozen","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, or the caller cannot see it","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see the X-RateLimit-* headers and Retry-After","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Something failed on our side; the request id is in the body","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UpstreamError":{"description":"A service we depend on (the runtime, GitHub) did not answer; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"The feature is not enabled on this server (github_not_configured), or a service we depend on is down; retry later","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"GatewayTimeout":{"description":"A service we depend on did not answer in time; retry shortly","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable, machine-readable error code"},"message":{"type":"string","description":"Human-readable explanation"},"requestId":{"type":"string","description":"Quote this when contacting support"},"issues":{"type":"array","description":"Present on invalid_request: one entry per invalid field","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"insufficient_scope: the permissions the key lacks"},"billingUrl":{"type":"string","description":"Dashboard page where the user can resolve a billing problem (insufficient_balance, no_payment_method, ...)"},"topUpNeededCents":{"type":"integer","description":"insufficient_balance: credits to add, in US cents"},"appIds":{"type":"array","items":{"type":"string"},"description":"project_has_running_apps: the apps that are still live"},"resetAt":{"type":"string","format":"date-time","description":"rate_limited, topup_limit: when the window resets"},"retryAfterSec":{"type":"integer","description":"request_in_progress: seconds to wait before retrying"},"limit":{"type":"integer","description":"payload_too_large: bytes allowed; rate_limited: requests per window"},"maxCents":{"type":"integer","description":"amount_too_large: the per-transaction maximum"},"declineCode":{"type":"string","description":"card_declined: the issuer's decline code"},"paymentIntentId":{"type":"string","description":"card outcomes: the Stripe payment intent involved"},"allowed":{"type":"array","items":{"type":"string"},"description":"method_not_allowed: the methods the path accepts"}},"additionalProperties":true}}}}},"paths":{"/projects/{projectId}/apps/{appId}/logs/export":{"get":{"operationId":"apps.logs.export","summary":"The app's container logs as one text, oldest first. Every line is stamped with its time and server, up to maxBytes (1 MiB by default, 4 MiB at most). For a page at a time use apps.logs instead. Lines are the app's own output, as it wrote them, so they can hold anything it prints, sensitive data included.","description":"Requires `monitoring:read` (Read usage metrics, app logs, build logs and server logs).\n\nErrors specific to this operation:\n- 429 `too_many_attempts`: More than three log changes in a minute","tags":["Apps"],"parameters":[{"name":"projectId","in":"path","required":true,"description":"Project id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"appId","in":"path","required":true,"description":"App id","schema":{"type":"string","pattern":"^[0-9a-fA-F]{24}$"}},{"name":"nodes","in":"query","required":false,"description":"Server addresses to include; omit for all","schema":{"maxItems":50,"type":"array","items":{"type":"string","minLength":1}},"style":"form","explode":true},{"name":"maxBytes","in":"query","required":false,"description":"Stop after this many bytes of text; 1048576 by default","schema":{"type":"integer","minimum":1024,"maximum":4194304}}],"responses":{"200":{"description":"OK","headers":{"X-Request-Id":{"$ref":"#/components/headers/RequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"The log lines, newline-separated"},"lines":{"type":"integer"},"truncated":{"type":"boolean","description":"maxBytes was reached before the end; the newest lines are missing"}},"required":["text","lines","truncated"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"},"502":{"$ref":"#/components/responses/UpstreamError"},"503":{"$ref":"#/components/responses/Unavailable"},"504":{"$ref":"#/components/responses/GatewayTimeout"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.kinesis.network/api/apps.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
