Docs
Search docs

Get a workspace's CI minutes usage for a month

GET/api/owners/{handle}/ci/usage

getOwnerCiUsage

The owner's workspace CI minutes for one calendar month (UTC): `used_seconds` is the billed meter the CI quota gate reads and `included_minutes` the allowance it compares against. `repos` breaks the month down over the repositories the caller can read; minutes of repositories the caller cannot read, or that were deleted, are `other_seconds`. Requires workspace membership (non-members get 404).

Authentication is not described for this operation in the spec — that does not mean it is public. Check tokens and scopes.

curl

curl -X GET 'https://neosource.dev/api/owners/HANDLE/ci/usage'

fetch

fetch("https://neosource.dev/api/owners/HANDLE/ci/usage", {
  method: "GET",
});

Path parameters

handlerequired

Handle of the owner — either a user account or an organization.

string

Query parameters

month

Month to report, `YYYY-MM`. Default the current month; a future or malformed month is a 400.

string

Responses

200CI usage

application/json

OwnerCiUsageResponse

object

`GET /api/owners/{handle}/ci/usage` — the workspace's CI minutes for one month.

included_minutesrequired

integerint32

The workspace's monthly allowance in minutes, as the quota gate resolves it NOW (override, else plan). `0` means no hosted CI; there is no unlimited value. New hosted work is held once `used_seconds` reaches `included_minutes * 60`.

other_secondsrequired

integerint64

`used_seconds` not accounted for by `repos`' hosted seconds (never negative): repositories the viewer cannot read, deleted repositories, jobs whose runner clock put their completion across a month boundary from the meter's, and hosted jobs among `repos`' `unattributed_seconds`.

period_startrequired

string

First day of the reported month, `YYYY-MM-DD`.

reposrequired

array

The viewer's readable repositories with an executed job in the month, billed hosted seconds descending.

items

OwnerCiUsageRepo

object

One repository's CI usage in the reported month.

hosted_billed_secondsrequired

integerint64

job_countrequired

integerint64

namerequired

string

The repository's name.

ownerrequired

string

The repository's owner handle (the path's `{handle}`).

self_hosted_secondsrequired

integerint64

unattributed_secondsrequired

integerint64

Ran before runner provenance was recorded (July 2026); may be hosted or self-hosted.

resets_atrequired

string

First day of the following month, `YYYY-MM-DD` — when the allowance resets.

used_secondsrequired

integerint64

Billed seconds the workspace's meter recorded for the month: exactly what the CI quota gate compares against the allowance.

403Forbidden — one of: forbidden, needs_scope

application/json

one of
  • ErrorForbidden
  • NeedsScopeError

    object

    `403` body returned when a classic OAuth token is asked for something its granted scopes do not cover — an explicit private listing without `repo`, or the one-click GitHub mirror without `admin:public_key`. `scope` names the missing grant so the client can say exactly what the token lacks. There is no elevation route to widen it any more (a re-link goes through the GitHub App, whose tokens carry no scopes), so the client's answer is to say so, never to start a handshake.

    errorrequired

    string

    Always `needs_scope` — this body exists to carry the extra fields that kind needs.

    "needs_scope"

    scoperequired

    string

    The provider scope to request via elevation (e.g. `"repo"`).

Standard errors

Bodies documented once for the whole API — see standard errors.

  • 400Bad Request — one of: invalid_input
  • 404Not Found — one of: not_found
  • 429Rate limited — retry after the `Retry-After` header
  • 500Internal server error
  • 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
  • 504Gateway timeout — the request exceeded the server's handling budget