> 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/builds.md).

# Builds

Follow repository builds, read builder logs and trigger a deployment.

Check whether an earlier build image is available with GET on its /rollback path. POST redeploys that image without rebuilding: a running app redeploys, a stopped app uses it at its next start. Rollback needs apps:write and permission to edit, changes only the image in the current configuration, and is refused during an active build or without a deployable image. The next build replaces it.

## List the builds of a GitHub-sourced app, newest first

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

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Builds"}],"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":{"Build":{"type":"object","properties":{"id":{"type":"string","description":"Build id"},"appId":{"type":"string"},"status":{"type":"string","enum":["pending","running","succeeded","failed","cancelled"],"description":"running until the image is built and the app deployed"},"step":{"type":"string","enum":["vcs_import","image_build","app_deploy","completed"],"description":"Pipeline step in progress, or completed"},"imageBuildStatus":{"description":"The image builder's own status (Created, Running, Completed, Failed, Canceled, TimedOut) once that step started","type":["string","null"]},"source":{"anyOf":[{"type":"object","properties":{"repo":{"type":["string","null"]},"branch":{"type":["string","null"]},"commitSha":{"type":["string","null"]},"commitMessage":{"type":["string","null"]},"contextDir":{"type":["string","null"]},"dockerfilePath":{"type":["string","null"]}},"required":["repo","branch","commitSha","commitMessage","contextDir","dockerfilePath"],"additionalProperties":false},{"type":"null"}],"description":"What was built; the commit is filled in once the build starts"},"error":{"anyOf":[{"type":"object","properties":{"step":{"type":"string","description":"Step the build failed at"},"message":{"type":"string"},"code":{"type":["string","null"]}},"required":["step","message","code"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"startedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"pollAfterSec":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Seconds to wait before reading the build again; null once it has finished"}},"required":["id","appId","status","step","imageBuildStatus","source","error","createdAt","startedAt","finishedAt","pollAfterSec"],"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}/builds":{"get":{"operationId":"apps.builds.list","summary":"List the builds of a GitHub-sourced app, newest first","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Builds"],"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":"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":{"builds":{"type":"array","items":{"$ref":"#/components/schemas/Build"}},"nextCursor":{"description":"Pass as cursor to fetch the next page; null on the last page","type":["string","null"]}},"required":["builds","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"}}}}}}
```

## Start a new build of a GitHub-sourced app from its branch head, or from one commit, cancelling any build still running. The app is redeployed and started when the build succeeds; poll apps.builds.get 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:\
> \- 409 \`app\_source\_unsupported\`: The app is not built from a repository\
> \- 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\_commit\_not\_found\`: No commit has this sha

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Builds"}],"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":{"Build":{"type":"object","properties":{"id":{"type":"string","description":"Build id"},"appId":{"type":"string"},"status":{"type":"string","enum":["pending","running","succeeded","failed","cancelled"],"description":"running until the image is built and the app deployed"},"step":{"type":"string","enum":["vcs_import","image_build","app_deploy","completed"],"description":"Pipeline step in progress, or completed"},"imageBuildStatus":{"description":"The image builder's own status (Created, Running, Completed, Failed, Canceled, TimedOut) once that step started","type":["string","null"]},"source":{"anyOf":[{"type":"object","properties":{"repo":{"type":["string","null"]},"branch":{"type":["string","null"]},"commitSha":{"type":["string","null"]},"commitMessage":{"type":["string","null"]},"contextDir":{"type":["string","null"]},"dockerfilePath":{"type":["string","null"]}},"required":["repo","branch","commitSha","commitMessage","contextDir","dockerfilePath"],"additionalProperties":false},{"type":"null"}],"description":"What was built; the commit is filled in once the build starts"},"error":{"anyOf":[{"type":"object","properties":{"step":{"type":"string","description":"Step the build failed at"},"message":{"type":"string"},"code":{"type":["string","null"]}},"required":["step","message","code"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"startedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"pollAfterSec":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Seconds to wait before reading the build again; null once it has finished"}},"required":["id","appId","status","step","imageBuildStatus","source","error","createdAt","startedAt","finishedAt","pollAfterSec"],"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}/builds":{"post":{"operationId":"apps.builds.create","summary":"Start a new build of a GitHub-sourced app from its branch head, or from one commit, cancelling any build still running. The app is redeployed and started when the build succeeds; poll apps.builds.get 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- 409 `app_source_unsupported`: The app is not built from a repository\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_commit_not_found`: No commit has this sha","tags":["Builds"],"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":{"commitSha":{"description":"Commit to build instead of the branch head","type":"string","pattern":"^[0-9a-fA-F]{7,40}$"}}}}}},"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":{"build":{"$ref":"#/components/schemas/Build"},"cancelledBuilds":{"type":"integer","description":"Builds that were still running and were cancelled"}},"required":["build","cancelledBuilds"],"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"}}}}}}
```

## Get one build: its status, pipeline step, source commit and error

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

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Builds"}],"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":{"Build":{"type":"object","properties":{"id":{"type":"string","description":"Build id"},"appId":{"type":"string"},"status":{"type":"string","enum":["pending","running","succeeded","failed","cancelled"],"description":"running until the image is built and the app deployed"},"step":{"type":"string","enum":["vcs_import","image_build","app_deploy","completed"],"description":"Pipeline step in progress, or completed"},"imageBuildStatus":{"description":"The image builder's own status (Created, Running, Completed, Failed, Canceled, TimedOut) once that step started","type":["string","null"]},"source":{"anyOf":[{"type":"object","properties":{"repo":{"type":["string","null"]},"branch":{"type":["string","null"]},"commitSha":{"type":["string","null"]},"commitMessage":{"type":["string","null"]},"contextDir":{"type":["string","null"]},"dockerfilePath":{"type":["string","null"]}},"required":["repo","branch","commitSha","commitMessage","contextDir","dockerfilePath"],"additionalProperties":false},{"type":"null"}],"description":"What was built; the commit is filled in once the build starts"},"error":{"anyOf":[{"type":"object","properties":{"step":{"type":"string","description":"Step the build failed at"},"message":{"type":"string"},"code":{"type":["string","null"]}},"required":["step","message","code"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"startedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"pollAfterSec":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Seconds to wait before reading the build again; null once it has finished"}},"required":["id","appId","status","step","imageBuildStatus","source","error","createdAt","startedAt","finishedAt","pollAfterSec"],"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}/builds/{buildId}":{"get":{"operationId":"apps.builds.get","summary":"Get one build: its status, pipeline step, source commit and error","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Builds"],"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":"buildId","in":"path","required":true,"description":"Build 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/Build"}}}},"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"}}}}}}
```

## Read the image builder's log for a build. The whole log once the build has finished, a snapshot of what has been written so far while it runs (empty until the builder starts writing). It includes whatever the repository's build steps print, 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":"Builds"}],"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":{"BuildLogs":{"type":"object","properties":{"id":{"type":"string","description":"Build id"},"status":{"type":"string","enum":["pending","running","succeeded","failed","cancelled"]},"imageBuildStatus":{"type":["string","null"]},"lines":{"type":"array","items":{"type":"string"},"description":"Builder output, oldest first"},"complete":{"type":"boolean","description":"The image build has finished, so the log is final"},"truncated":{"type":"boolean","description":"Older lines were dropped to keep the last 2000"}},"required":["id","status","imageBuildStatus","lines","complete","truncated"],"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}/builds/{buildId}/logs":{"get":{"operationId":"apps.builds.logs","summary":"Read the image builder's log for a build. The whole log once the build has finished, a snapshot of what has been written so far while it runs (empty until the builder starts writing). It includes whatever the repository's build steps print, sensitive data included.","description":"Requires `monitoring:read` (Read usage metrics, app logs, build logs and server logs).","tags":["Builds"],"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":"buildId","in":"path","required":true,"description":"Build 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/BuildLogs"}}}},"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"}}}}}}
```

## Whether an earlier build's image can still be redeployed with rollback\_build. False when the build has no image (it failed or was cancelled) or its image is no longer stored.

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

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Builds"}],"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}/builds/{buildId}/rollback":{"get":{"operationId":"apps.builds.rollbackCheck","summary":"Whether an earlier build's image can still be redeployed with rollback_build. False when the build has no image (it failed or was cancelled) or its image is no longer stored.","description":"Requires `apps:read` (View apps, their configuration and status).","tags":["Builds"],"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":"buildId","in":"path","required":true,"description":"Build 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":{"imageAvailable":{"type":"boolean","description":"The build's image can be redeployed"}},"required":["imageAvailable"],"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"}}}}}}
```

## Redeploy the image of an earlier build without rebuilding it. A running app is redeployed with that image; a stopped app uses it at its next start. The next build (a push with autoDeploy on, or a triggered build) replaces it again.

> Requires \`apps:write\` (Create, update, start, stop, restart and rebuild apps).\
> \
> Errors specific to this operation:\
> \- 409 \`app\_source\_unsupported\`: The app is not built from a repository\
> \- 409 \`build\_not\_deployable\`: Nothing to roll back to: the build has no image (it failed or was cancelled before its image was built, or the image is gone), or the app has never been deployed (start a new build instead)\
> \- 409 \`build\_in\_progress\`: A build is running and deploys when it finishes

```json
{"openapi":"3.1.0","info":{"title":"Kinesis API","version":"1.5.0"},"tags":[{"name":"Builds"}],"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":{"Build":{"type":"object","properties":{"id":{"type":"string","description":"Build id"},"appId":{"type":"string"},"status":{"type":"string","enum":["pending","running","succeeded","failed","cancelled"],"description":"running until the image is built and the app deployed"},"step":{"type":"string","enum":["vcs_import","image_build","app_deploy","completed"],"description":"Pipeline step in progress, or completed"},"imageBuildStatus":{"description":"The image builder's own status (Created, Running, Completed, Failed, Canceled, TimedOut) once that step started","type":["string","null"]},"source":{"anyOf":[{"type":"object","properties":{"repo":{"type":["string","null"]},"branch":{"type":["string","null"]},"commitSha":{"type":["string","null"]},"commitMessage":{"type":["string","null"]},"contextDir":{"type":["string","null"]},"dockerfilePath":{"type":["string","null"]}},"required":["repo","branch","commitSha","commitMessage","contextDir","dockerfilePath"],"additionalProperties":false},{"type":"null"}],"description":"What was built; the commit is filled in once the build starts"},"error":{"anyOf":[{"type":"object","properties":{"step":{"type":"string","description":"Step the build failed at"},"message":{"type":"string"},"code":{"type":["string","null"]}},"required":["step","message","code"],"additionalProperties":false},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},"startedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"finishedAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC)"},{"type":"null"}]},"pollAfterSec":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Seconds to wait before reading the build again; null once it has finished"}},"required":["id","appId","status","step","imageBuildStatus","source","error","createdAt","startedAt","finishedAt","pollAfterSec"],"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}/builds/{buildId}/rollback":{"post":{"operationId":"apps.builds.rollback","summary":"Redeploy the image of an earlier build without rebuilding it. A running app is redeployed with that image; a stopped app uses it at its next start. The next build (a push with autoDeploy on, or a triggered build) replaces it again.","description":"Requires `apps:write` (Create, update, start, stop, restart and rebuild apps).\n\nErrors specific to this operation:\n- 409 `app_source_unsupported`: The app is not built from a repository\n- 409 `build_not_deployable`: Nothing to roll back to: the build has no image (it failed or was cancelled before its image was built, or the image is gone), or the app has never been deployed (start a new build instead)\n- 409 `build_in_progress`: A build is running and deploys when it finishes","tags":["Builds"],"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":"buildId","in":"path","required":true,"description":"Build 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":{"build":{"description":"The build whose image is now deployed","$ref":"#/components/schemas/Build"},"redeploying":{"type":"boolean","description":"The app is running and is being redeployed with the image"}},"required":["build","redeploying"],"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"}}}}}}
```


---

# 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/builds.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.
