Record a deploy
POST
/v1/deploys
Opens a deploy record for a deploy that
b3os apply runs, from a machine (source: cli) or a GitHub Actions
workflow (source: github_actions), so it shows in the dashboard beside the GitHub App's deploys. The record
is queued in the caller's project; the same credential then moves it with Update a deploy. B3OS runs
nothing for it: the CLI does the work and reports it. b3os apply opens one by itself when its key holds
sandboxes:write, the scope a deploy of services needs anyway, and uses the record's id as its deploy id
(b3os.deploy); without the scope it deploys and records nothing.Authentication
Bearer Token (b3os_sk_ API key or b3os_pat_ token)
Header Parameters
Idempotency-Key
string
optional
header
A unique value (for example a UUID) that makes this request safe to retry. Scoped to your project for 24
hours: a retry with the same key, method, path and body returns the stored response with
Idempotent-Replayed: true, and only to the same API key. Reusing the key for a different request returns
409 idempotency_key_conflict. A retry that arrives while the first request runs gets 409 idempotency_request_in_progress with Retry-After. The first request runs to completion and its response
is stored even if your client disconnects. A node keeps a bounded number of keys per organization: past
that bound a request with a new key is refused (429 quota_exceeded, retryable) rather than run without
its key. When a node is full, organizations holding more than their share may have their oldest stored
responses dropped; a retry with such a key gets 409 idempotency_response_evicted and is not run again.Min length
1Max length 255Request Body required
application/jsonapp
string
REQUIRED
An application's name, the
name in its b3os.yaml.Min length
1Max length 63Pattern ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$env
string
Default
productionPattern ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$source
string
Default
cliValues cli github_actionscommit
object | null
The commit it deploys; null outside git.
sha
string
REQUIRED
Pattern
^[0-9a-f]{40}$message
string | null
The first line of the commit message.
Max length
500branch
string | null
Max length
255dirty
boolean
Default
falserepository
object | null
The GitHub repository, for
github_actions (GITHUB_REPOSITORY and GITHUB_REPOSITORY_ID).id
integer | null
Min
1full_name
string
REQUIRED
Pattern
^[A-Za-z0-9-]{1,39}/[A-Za-z0-9._-]{1,100}$manifest_path
string
Default
b3os.yamlMin length 1Max length 255manifest_sha
string | null
Pattern
^[0-9a-f]{12,64}$plan
object
The plan as
b3os apply printed it, its counts and its findings at their line in b3os.yaml.text
string
REQUIRED
Max length
200000summary
object
REQUIRED
Plan items per action.
create
integer
update
integer
ok
integer
gap
integer
problem
integer
unchecked
integer
remove
integer
findings
object[]
Max items
500run_url
string | null
The workflow run,
https://github.com/<owner>/<repo>/actions/runs/<id>.Pattern
^https://github\.com/[A-Za-z0-9-]{1,39}/[A-Za-z0-9._-]{1,100}/actions/runs/[0-9]{1,20}(/attempts/[0-9]{1,5})?$requested_by
string | null
github_actions only: the GitHub login that ran the workflow (GITHUB_ACTOR). Otherwise the record names
the calling user or key.Pattern
^[A-Za-z0-9][A-Za-z0-9-]{0,38}(\[bot\])?$rollback_of
string | null
b3os app rollback only: the deploy it runs again, a deploy of this application. The record keeps the
source of where it ran (cli, github_actions); rollback is the GitHub App's.Pattern
^dep_[0-9a-hjkmnp-tv-z]{26}$recreated
object[]
b3os apply --keepalive only: the services it recreates and why. Keepalive opens a record only when it
recreates something; a run that only renews records nothing.Max items
10
Array of:
item
string
REQUIRED
service/<name>.Pattern
^service/[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$cause
string
REQUIRED
Values
process crash lease probe stoppedreason
string
REQUIRED
In words, with the time in UTC (
process 466 killed by TERM at 01:15:37 UTC, the lease ended at 20:24:07 UTC).Max length
300lines
string[]
REQUIRED
Max items
20Item max length 300Responses
201
The deploy, queued.
application/jsonid
string
REQUIRED
object
string
REQUIRED
Values
deployapp
string
REQUIRED
An application's name, the
name in its b3os.yaml.env
string
REQUIRED
project_id
string
REQUIRED
status
string
REQUIRED
queued (waiting its turn), building (plan, routines, builds and new service generations, all undone on a
failure), applying (the cutover), live (what the application runs now, also when something went wrong
after its cutover: error says what), superseded (was live; a newer
deploy went live), failed, cancelled (stopped before it started: a newer commit, an unlinked repository,
a removed installation; or stopped part-way and undone: a cancelled workflow run, Ctrl-C, a newer deploy) or
skipped (nothing the manifest reads changed, auto-deploy is paused, or the branch had already moved past
the pushed commit).Values
queued building applying live superseded failed cancelled skippedsource
string
REQUIRED
What ran the deploy:
github_app (a push to the linked branch, or Deploy in the dashboard), redeploy and
rollback (the dashboard's, through the GitHub App), or b3os apply, which records its own deploys: cli
from a machine, github_actions from a workflow.Values
cli github_actions github_app redeploy rollbackrequested_by
string | null
REQUIRED
The GitHub login that pushed (or that ran the workflow, for
github_actions), or the user or key that
asked for a redeploy or rollback, or that ran b3os apply (cli).commit
object | null
REQUIRED
sha
string
REQUIRED
message
string | null
REQUIRED
branch
string | null
REQUIRED
dirty
boolean
REQUIRED
The tree held uncommitted changes, which deployed with it (
b3os apply from a machine).repository
object | null
REQUIRED
id
integer | null
REQUIRED
GitHub's id; null when
b3os apply named the repository without it.full_name
string
REQUIRED
installation_id
integer | null
REQUIRED
manifest_path
string
REQUIRED
manifest_sha
string | null
REQUIRED
previous_id
string | null
REQUIRED
The deploy that was live before this one went live.
rollback_of
string | null
REQUIRED
The deploy a rollback ran again: the dashboard's (
source: rollback), or b3os app rollback's (source: cli or github_actions).recreated
object[] | null
A deploy
b3os apply --keepalive recorded because it recreated services: each one and why, with its lost
process's last lines. Null for any other deploy, and absent from edges before 2026-11-11.
Array of:
item
string
REQUIRED
service/<name>.cause
string
REQUIRED
Values
process crash lease probe stoppedreason
string
REQUIRED
In words, with the time in UTC (
process 466 killed by TERM at 01:15:37 UTC, the lease ended at 20:24:07 UTC).lines
string[]
REQUIRED
plan_summary
object | null
REQUIRED
Plan items per action.
create
integer
update
integer
ok
integer
gap
integer
problem
integer
unchecked
integer
remove
integer
plan
object | null
Get a deploy only. The plan as
b3os apply --dry-run printed it, with its findings.text
string
summary
object
Plan items per action.
create
integer
update
integer
ok
integer
gap
integer
problem
integer
unchecked
integer
remove
integer
findings
object[]
items
object[]
Get a deploy only. Per item, what the deploy did and the ids it made, and since 2026-11-11 when each step
began and ended (
started_at, ended_at; a new generation also probe and cutover, each with both
times). Older records have no times.output
object[]
Get a deploy only. What the processes of a deploy B3OS ran printed, per step (a build's apt step when
build.apt lists packages, a build's install, a generation's prepare), in the order the steps started: the last 400 lines or 64 KiB of each, whichever
is smaller, with credentials in URLs and paths redacted. Written as the output arrives, about every 5
seconds while a step runs, so a deploy that is building shows its install as it goes. Empty for a deploy
b3os apply recorded: it prints the output where it runs.
Array of:
item
string
REQUIRED
The item the step belongs to (
build/agent for an apt step or an install, service/agent for a
prepare).step
string
REQUIRED
apt is the build's apt-get install of build.apt, run as root before install.Values
install prepare aptstatus
string
REQUIRED
running while the process runs; a step the deploy stopped before it ended is failed.Values
running succeeded failedlines
string[]
REQUIRED
The newest lines, oldest first, without their newline.
dropped
integer
REQUIRED
Earlier lines that are no longer kept.
started_at
string (date-time)
REQUIRED
ended_at
string (date-time) | null
REQUIRED
step
string | null
Where the deploy is, in the deployer's words (
build/agent install-wait (2 min), service/agent ready),
as it last reported; null before it starts.run_url
string | null
The GitHub Actions run that deployed it (
source: github_actions).checks
object
REQUIRED
The check runs on the commit (GitHub ids).
deploy
integer | null
REQUIRED
plan
integer | null
REQUIRED
error
string | null
REQUIRED
Why it failed. On a
live deploy: what went wrong after its cutover (a retire, a service that stopped,
a run cut short); its new generations serve anyway, and B3OS keeps them alive.reason
string | null
REQUIRED
Why it was cancelled or skipped. On a
live deploy b3os apply recorded: that it replaced a deploy B3OS
kept alive, so nothing but b3os apply renews the application now.github_error
string | null
REQUIRED
The last check run or comment GitHub refused (the deploy went on without it).
attempts
integer
REQUIRED
created_at
string (date-time)
REQUIRED
updated_at
string (date-time)
REQUIRED
started_at
string (date-time) | null
REQUIRED
live_at
string (date-time) | null
REQUIRED
finished_at
string (date-time) | null
REQUIRED
400
The request failed validation (
invalid_request, invalid_url).
401
Missing, malformed, expired or revoked credentials (
unauthorized).
403
Authenticated but not allowed (
forbidden, egress_denied).
409
The object's state does not allow this operation, or the idempotency key conflicts.
413
The request body exceeds this operation's limit.
415
The Content-Type is not accepted by this operation.
429
A rate, concurrency or quota limit applies (
rate_limited, concurrency_limited, quota_exceeded).
500
Something failed inside B3OS (
internal). Retry with backoff.
503
The node or the product is not available right now (
node_unavailable, product_unavailable, capacity_unavailable).
curl -X POST 'https://beta-api.b3os.org/v1/deploys' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "app": "research-agent", "source": "github_actions", "commit": { "sha": "3f2c1b0a9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a", "message": "Update the harness", "branch": "main", "dirty": false }, "repository": { "id": 812345678, "full_name": "acme/research-agent" }, "manifest_path": "b3os.yaml", "manifest_sha": "0123456789ab", "run_url": "https://github.com/acme/research-agent/actions/runs/18492771204", "requested_by": "dana", "plan": { "text": " + service agent new generation", "summary": { "create": 1, "update": 0, "ok": 1, "gap": 0, "problem": 0, "unchecked": 0, "remove": 0 }, "findings": [] }}'
const response = await fetch('https://beta-api.b3os.org/v1/deploys', { method: 'POST', headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "app": "research-agent", "source": "github_actions", "commit": { "sha": "3f2c1b0a9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a", "message": "Update the harness", "branch": "main", "dirty": false }, "repository": { "id": 812345678, "full_name": "acme/research-agent" }, "manifest_path": "b3os.yaml", "manifest_sha": "0123456789ab", "run_url": "https://github.com/acme/research-agent/actions/runs/18492771204", "requested_by": "dana", "plan": { "text": " + service agent new generation", "summary": { "create": 1, "update": 0, "ok": 1, "gap": 0, "problem": 0, "unchecked": 0, "remove": 0 }, "findings": [] } })});const data = await response.json();console.log(data);
import requestsheaders = { 'Authorization': 'Bearer YOUR_API_TOKEN'}response = requests.post('https://beta-api.b3os.org/v1/deploys', headers=headers, json={ "app": "research-agent", "source": "github_actions", "commit": { "sha": "3f2c1b0a9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a", "message": "Update the harness", "branch": "main", "dirty": false }, "repository": { "id": 812345678, "full_name": "acme/research-agent" }, "manifest_path": "b3os.yaml", "manifest_sha": "0123456789ab", "run_url": "https://github.com/acme/research-agent/actions/runs/18492771204", "requested_by": "dana", "plan": { "text": " + service agent new generation", "summary": { "create": 1, "update": 0, "ok": 1, "gap": 0, "problem": 0, "unchecked": 0, "remove": 0 }, "findings": [] }})print(response.json())
201
Response
{ "id": "dep_01m6a2zq8x9hkqd3n7c5b4v2tw", "object": "deploy", "app": "research-agent", "env": "production", "project_id": "prj_01m5t3pf8heewxt65ej3dm577y", "status": "queued", "source": "github_actions", "requested_by": "dana", "commit": { "sha": "3f2c1b0a9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a", "message": "Update the harness", "branch": "main", "dirty": false }, "repository": { "id": 812345678, "full_name": "acme/research-agent" }, "installation_id": null, "manifest_path": "b3os.yaml", "manifest_sha": "0123456789ab", "previous_id": null, "rollback_of": null, "plan_summary": { "create": 1, "update": 0, "ok": 1, "gap": 0, "problem": 0, "unchecked": 0, "remove": 0 }, "plan": { "text": " + service agent new generation", "summary": { "create": 1, "update": 0, "ok": 1, "gap": 0, "problem": 0, "unchecked": 0, "remove": 0 }, "findings": [] }, "items": [], "step": null, "run_url": "https://github.com/acme/research-agent/actions/runs/18492771204", "checks": { "deploy": null, "plan": null }, "error": null, "reason": null, "github_error": null, "attempts": 0, "created_at": "2026-11-07T09:10:00.000Z", "updated_at": "2026-11-07T09:10:00.000Z", "started_at": null, "live_at": null, "finished_at": null}
API Playground
Try this endpoint
POST
/v1/deploys