API reference
The API
Start runs on tracker issues from your own systems, read how they went, and hear back by webhook. Every run is tied to an issue, and ends, at best, in a draft pull request a person merges.
Its address
Your workspace’s own host, under /v1: https://<workspace>.nightlab.io/v1/. Version 1 only gains fields and calls; anything that would break a caller would be /v2.
Keys
A workspace admin makes a key in the portal, under Settings › Integrations › API keys, or through the workspace’s admin API, POST /workspace/api-keys, signed in (with their second factor, where sign-in asks for one). Send the key on every call as Authorization: Bearer $NIGHTLAB_API_KEY. It’s shown once, and opens /v1 alone, at its own workspace’s address, within its scopes and projects:
runs:read: get and list runs;runs:write: start and cancel them;projects:read: list projects;events:read: read events.
A key can’t approve a run, merge, or change a setting. GET /v1/key says which key you used and when it ends. Start runs from CI walks through making one.
Answers and limits
401: no key, or one that’s unknown, revoked or expired. It doesn’t say which.403: the key lacks the call’s scope, the call came from outside its allow-list, or (when you start a run) the issue’s project isn’t one of the key’s.404: a run that doesn’t exist, or isn’t in the key’s projects.429: the key’s rate limit, 600 reads and 60 writes a minute, withRetry-Afterin seconds; or too many bad keys from one address (wait a minute).
A successful answer, and the rate limit’s own 429, carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds until the window resets). Other refusals don’t.
Errors
A refusal is application/problem+json (RFC 9457): its status, the status’s title, and a detail saying what to change. A 422 for a wrong field also lists each one in errors.
{
"type": "about:blank",
"title": "Conflict",
"status": 409,
"detail": "SHOP-1431 already has an active run (run-42): let it finish…"
}
Pages
A list comes a page at a time: pass its next_cursor as cursor for the next, until it’s null. Runs come newest first.
The run
What every run call answers. It never carries issue text, code or amounts.
| Field | What it is |
|---|---|
id | The run’s id, like run-42. |
project, issue | Its project’s slug, and the tracker issue. |
action | build or improve; runs started elsewhere can also be refresh or review. |
state | Where it is (below). |
outcome | How a completed run ended, like pr_opened, no_pr or gates_failed; null until then. |
no_pr_reason | Why no pull request opened, when none did. |
pr_url, pr_state | Its pull request, and whether it’s draft, open, merged or closed, once known. |
external_ref | Your reference, as you started it; empty for runs started elsewhere. |
summary | For the people who raised the issue, once the run has ended: resolves (yes, partially, no or unknown) and text, with no code, file paths, commands or credentials. For an issue with a Jira security level, it says what happened to the run without describing the issue. null until it’s written, usually within a minute of the end, and for runs not started through the API. |
created_at, updated_at, finished_at | When, in UTC. |
links | The run in the API (api) and in the portal (portal). |
States
queued: waiting for a slot. A run you start begins here.waiting_for_approval: held for a person to approve. Runs a tracker rule or a batch in the portal starts can wait here, never one a key starts.running, thenwaiting_for_answerif a person needs to answer a question.completed,failed,cancelledorskipped: ended.