# Credentials (/api/credentials)



Every endpoint except [`GET /api/info`](/api/info/get-control-plane-info) requires a credential. The control plane accepts a bearer token, and rejects anything else with [`401 UNAUTHENTICATED`](/api/errors).

## Bearer token

What [`sling login`](/sling-cli/commands/auth#sling-login) stores at `~/.config/sling/credentials`, sent in the `Authorization` header:

<ApiRequest path="/api/whoami" />

<Callout type="warn">
  Anyone holding your token can read everything it has access to. Keep it in a secret store or CI secret. Never commit it, and never put it in a URL, where it leaks into logs and browser history.
</Callout>

## Confirming your credential

[`GET /api/whoami`](/api/identity/get-whoami) reports the caller's identity, org, plan, scopes, and token expiry. It is the fastest way to tell an expired token from a scope problem:

<ApiRequest path="/api/whoami" />

## Scopes

Three endpoint groups require a named scope. A credential that lacks it is rejected with [`403 INSUFFICIENT_SCOPE`](/api/errors), not `401`: the token was valid, it just could not reach that resource.

| Scope        | Required by                                                                                  |
| ------------ | -------------------------------------------------------------------------------------------- |
| `orgs:read`  | [`GET /api/orgs`](/api/identity/list-orgs)                                                   |
| `usage:read` | [`GET /api/usage`](/api/usage/get-usage), [`GET /api/top`](/api/top/get-top)                 |
| `bill:read`  | [`GET /api/bill`](/api/bill/get-bill), [`GET /api/bill/history`](/api/bill/get-bill-history) |

Endpoints not listed here need a valid credential but no particular scope. Grant the narrowest set that does the job: a credential that only powers a cost dashboard needs `usage:read` and nothing more.

## Org scoping

Authentication establishes *who* you are; org membership establishes *what* you can see. Results are always scoped to the orgs the caller belongs to.

Every org-scoped endpoint takes `org` as a **required** query parameter. The API never infers it, even when you belong to exactly one org. (The CLI is what makes it feel optional: it fills in the default org you set with `sling org switch`.) Call [`GET /api/orgs`](/api/identity/list-orgs) to list the slugs you can use.

A run, job, or attempt belonging to an org you cannot reach returns [`404 NOT_FOUND`](/api/errors) rather than `403`. This is deliberate: a `403` would confirm the id exists somewhere, which is itself a disclosure. Do not read a `404` as proof that an id is invalid.
