Deployments (CI/CD)
Report CI/CD deployments to BugWatch so errors line up with the release that caused them. Every deploy shows up on the project's Deployments tab, its stage logs are searchable, and a failed deploy opens a DeploymentFailure issue automatically.
Scope required: deploy:write · Auth: central SECRET key (x-api-key: {{apiKey}}). The BugWatch environment (production/staging/…) comes from the key's resource scope, so you never send it.
Use the CLI (recommended)link
@newinstance/bugwatch-cli wraps all three endpoints, auto-detects CI metadata (commit, repo, branch) and persists the deployment id between steps (.bugwatch-deploy file or BUGWATCH_DEPLOY_ID env var):
export BUGWATCH_AUTH_TOKEN="sk_live_KEYID:secret" # needs deploy:write
npx @newinstance/bugwatch-cli deploy start --release "2.4.1"
npx @newinstance/bugwatch-cli deploy run --stage migrate -- ./scripts/migrate.sh
npx @newinstance/bugwatch-cli deploy run --stage deploy -- ./scripts/deploy.sh
npx @newinstance/bugwatch-cli deploy finish
# on failure instead:
npx @newinstance/bugwatch-cli deploy fail --summary "migrate exited 1" --stage migratedeploy run PATCHes the stage to running, streams the command's stdout/stderr to the logs endpoint as NDJSON, then PATCHes succeeded or failed with the exit code.
Lifecyclelink
POST /deploy → 201 { id: "dep_…" } status: in_progress
PATCH /deploy/{id} → stage transitions { stage: { key, status, … } }
POST /deploy/{id}/logs?stage → 202 log batches (NDJSON)
PATCH /deploy/{id} → { finish: true } status derived from stages
or { fail: { summary, stageKey } } → status: failedA deployment that is no longer in_progress ignores further PATCHes and echoes its final status, so retrying a finish is safe.
Start deployment
Creates a deployment record. Call it at the start of your CI deploy job.
Scope: deploy:write
Every field is optional, and an empty body is valid.
| Field | Type | Required | Description |
|---|---|---|---|
release | string | No | The release this deploy ships, up to 200 characters. Match what your SDK reports at runtime so errors correlate. |
meta | object | No | String map with commit, repo, branch and triggeredBy, each up to 300 characters. |
Keep the returned id: every later call needs it. The status starts as in_progress. A 404 means the project bound to this key no longer exists.
Authorization
x-api-keyAPI key · headerrequiredRequest body
application/json{
"release": "1.0.0",
"meta": {
"commit": "9f2c1ab",
"repo": "acme/checkout",
"branch": "main",
"triggeredBy": "gitlab-ci"
}
}Responses
201Deployment created401Invalid or missing API key403Missing deploy:write404Project not foundcurl -X POST 'https://api.newinstance.cloud/api/v1/bugwatch/deploy' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{
"release": "1.0.0",
"meta": {
"commit": "9f2c1ab",
"repo": "acme/checkout",
"branch": "main",
"triggeredBy": "gitlab-ci"
}
}'{
"id": "dep_64fa3c9e2b7d41c8a9f01234"
}Report stage · finish · fail
Updates a deployment with a stage transition, a finish or an explicit failure. The body carries one of stage, finish or fail.
Scope: deploy:write
deployId in the path is the id returned by Start deployment. Only a key for the same project can update it; any other key gets 404.
1. Stage transition
{ "stage": { "key": "migrate", "name": "Run DB migrations", "status": "running" } }status is running, succeeded or failed; exitCode and errorSummary are optional. Repeat per stage. A stage key is upserted, so re-sending updates it.
2. Finish
{ "finish": true }Final status is derived from stages: any failed stage ⇒ failed, else succeeded. A failed finish opens a DeploymentFailure issue in the project.
3. Fail explicitly
{ "fail": { "summary": "migrate exited 1", "stageKey": "migrate" } }Once the status is no longer in_progress, further PATCHes are no-ops that echo the final status, so they are safe to retry.
| Status | When it happens |
|---|---|
400 | A per-deployment stage or log limit is exceeded |
Authorization
x-api-keyAPI key · headerrequiredParameters
deployIdpath · stringrequireddefault: Request body
application/json{
"stage": {
"key": "migrate",
"name": "Run DB migrations",
"status": "succeeded",
"exitCode": 0
}
}Responses
200Stage recorded401Invalid or missing API key403Missing deploy:write404Deployment not foundcurl -X PATCH 'https://api.newinstance.cloud/api/v1/bugwatch/deploy/{deployId}' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{
"stage": {
"key": "migrate",
"name": "Run DB migrations",
"status": "succeeded",
"exitCode": 0
}
}'{
"id": "dep_64fa3c9e2b7d41c8a9f01234",
"status": "in_progress"
}Append stage logs (NDJSON)
Streams a batch of log lines for one stage. Call it repeatedly while the stage runs; the CLI's deploy run does this for you from the wrapped command's stdout/stderr.
Scope: deploy:write · Max body: 2 MB per batch
deployId in the path is the id returned by Start deployment.
Body: NDJSON (one JSON object per line) or a JSON array of { level, time, message }:
level: Pino-style number, 10 trace · 20 debug · 30 info · 40 warn · 50 error · 60 fataltime: epoch millisecondsmessage: the log line
Deploy tags (deployId, stage) are injected server-side, so do not add them yourself. Lines land in the project's normal log search.
truncated: true means the per-deployment log cap was reached; further batches are dropped, while finish and fail still work.
Authorization
x-api-keyAPI key · headerrequiredParameters
stagequery · stringdefault: Required. Key of the stage these log lines belong to, up to 100 characters, such as migrate.
deployIdpath · stringrequireddefault: Request body
application/json{"level":30,"time":{{nowMs}},"message":"Applying migration 0042_add_billing_index"}
{"level":30,"time":{{nowMs}},"message":"Migration complete in 1.2s"}Responses
202Batch accepted401Invalid or missing API key403Missing deploy:write404Deployment not foundcurl -X POST 'https://api.newinstance.cloud/api/v1/bugwatch/deploy/{deployId}/logs?stage=migrate' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{"level":30,"time":{{nowMs}},"message":"Applying migration 0042_add_billing_index"}
{"level":30,"time":{{nowMs}},"message":"Migration complete in 1.2s"}'{
"ingested": 2,
"skipped": 0,
"deduped": 0,
"truncated": false
}