Errors
The error body shape, what each status code means, and how the CLI maps them to exit codes
Every failure returns a JSON body with the same shape, so a client can branch on one field rather than parsing prose.
Error body
{
"code": "INSUFFICIENT_SCOPE",
"message": "This credential is missing the bill:read scope."
}| Field | Type | Notes |
|---|---|---|
code | string | A stable machine-readable identifier. Branch on this, never on message. |
message | string | Human-readable explanation. Wording may change at any time. |
details | array | Present on validation failures only. Each entry is { "path": …, "error": … }, naming the offending parameter. |
code is drawn from a closed set:
code | Meaning |
|---|---|
VALIDATION | A parameter was present but unacceptable — an unknown enum value, an out-of-range limit, two mutually exclusive window parameters. |
MALFORMED_REQUEST | The request could not be parsed — bad JSON in a POST body, or a query string the server cannot read. |
UNAUTHENTICATED | No credential, or one that is expired or invalid. |
INSUFFICIENT_SCOPE | The credential is valid but lacks a required scope. |
NOT_FOUND | No such resource within the orgs you can reach. |
Status codes
| Status | Typical code | What to do |
|---|---|---|
400 | MALFORMED_REQUEST | Fix the request itself. Retrying unchanged will not help. |
401 | UNAUTHENTICATED | Supply a credential, or refresh an expired session. See Authentication. |
403 | INSUFFICIENT_SCOPE | Reissue the credential with the scope the endpoint names. |
404 | NOT_FOUND | Check the id — but note it may exist in an org you cannot reach. |
422 | VALIDATION | Read details for the offending parameter and correct it. |
500 | — | A control-plane fault. Safe to retry with backoff; every endpoint in this reference is read-only. |
A 404 is deliberately indistinguishable from "exists, but not yours". The API will not confirm that an id exists in an org you cannot see, so treat 404 as "not visible to this credential" rather than "does not exist".
Retrying
Every endpoint documented here is a read, so retries are safe and cannot double-charge or mutate state. Retry 500 and 429 with exponential backoff; do not retry 400, 401, 403, 404, or 422 without changing the request, since the outcome is deterministic.
If you are rate limited the control plane returns 429. Back off before retrying.
Exit codes in the CLI
The sling CLI maps these responses onto a fixed exit-code table, so a script or agent can branch on $? without parsing output:
| Exit | Meaning | From |
|---|---|---|
0 | Success | 2xx |
1 | Unexpected CLI crash | never an API outcome |
2 | Usage error — bad flags, conflicting parameters | client-side, or 422 |
3 | Not found | 404 |
4 | Auth — missing, expired, or under-scoped credential | 401, 403 |
5 | Control-plane or transport failure | 5xx |
6 | Partial — telemetry incomplete, result still returned | 200 with gaps |
7 | Rate limited | 429 |
10 | Remote outcome failed — e.g. a run concluded unsuccessfully | 200 |
Note that 10 is not an error: the request succeeded and the result was a failure. It is what lets sling runs show <id> --wait gate a pipeline on a run's conclusion.
Credentials
Authenticate with a bearer token, and the scopes each endpoint requires
List workflow runs GET
Filtered workflow-run listing (sling runs list): branch / status / conclusion / trigger / workflow_path / runner-label / time-window filters over the CI facts store, keyset-paginated via an opaque cursor. Authenticated; scoped to the caller's orgs by membership.