# What GitHub will not give

The endpoints that are verified not to work on a personal account, written down so nobody rediscovers them.

Source: https://docs.jmrp.io/ghchronicle/api/limits/

Every entry here was checked against the live API from a personal account, and
most of it is not in GitHub's documentation, which describes what an endpoint
should return rather than what it does. It is written down so nobody
spends an afternoon finding it out again, and so that a missing panel can be
told apart from a broken collector.

## Why do two statistics endpoints never answer?

`stats/code_frequency` and `stats/contributors` answer **202 with an empty body,
indefinitely**, on a personal account. A 202 normally means "still being
computed, ask again", and for these two the next answer is another 202. They
are deliberately not called.

The lines added and removed that `code_frequency` would have given come from
the commits collector instead, per commit rather than per week, attributed to
an author and dated to the commit. `stats/participation` and `stats/punch_card`
do work and are used.

Ten seconds is all it takes to see it on your own account:

```sh
curl -s -o /dev/null -w '%{http_code}\n' \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  https://api.github.com/repos/OWNER/REPO/stats/code_frequency   # 202, for ever
curl -s -o /dev/null -w '%{http_code}\n' \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  https://api.github.com/repos/OWNER/REPO/stats/participation    # 200
```

## Billing

| Endpoint                                | Answer   |
| --------------------------------------- | -------- |
| `/settings/billing/actions`             | 410 Gone |
| `/settings/billing/packages`            | 410 Gone |
| `/settings/billing/shared-storage`      | 410 Gone |
| `/user/settings/billing/usage`          | 404      |
| `/users/{login}/settings/billing/usage` | works    |

Only the last form works for a personal account, and it returns full RFC 3339
timestamps in a field its documentation describes as a date.

## Organisation and enterprise only

Custom repository properties, classic projects, cost centres and the audit log.
A personal account cannot see any of them, however the token is scoped.

## Endpoints that answer, but say nothing

- **`workflows/{id}/timing`** returns 200 with an always-empty `billable`
  object. It looks like the source for per-workflow minutes and is not.
- **The stargazer list, to anyone but the repository's admins and collaborators.**
  [Since July 2026](https://docs.github.com/en/rest/activity/starring#new-access-restrictions)
  GitHub serves it to no one else. REST answers 404, and GraphQL's
  `stargazers` answers an empty list with a `totalCount` of 0 while
  `stargazerCount` beside it still gives the real number: measured on
  `cli/cli` and `octocat/Hello-World` with a token holding every scope.
  ghchronicle therefore writes `gh_star`, who starred and when to the second,
  only where the token has that access, which it always has on the account's
  own repositories and on those of an organisation the account administers;
  one named in `targets.repos` or reached through `targets.orgs` without it
  has its stars counted per day from the history below, and nobody named.
- **`/user/installations`** returns 403 without a GitHub App.

## The star history github.com serves to anyone

[`stargazers/history`](https://docs.github.com/en/rest/activity/starring#get-repository-star-history)
answers where the stargazer list does not. It serves anyone who can see the
repository, unauthenticated too: the stars given per day, grouped by week,
thirty weeks to a page, which is both the default and the most `per_page` allows
(a smaller one is honoured, a larger one is cut to thirty), paging back to the
repository's first week (measured on `cli/cli`: thirteen pages, back to 2019).
It names no stargazers, so it cannot stand in for `gh_star`, which is one row
per star at the instant it was given and says who gave it. It can stand in for
the count, and ghchronicle reads it for every repository it collects, writes it
as `gh_star_day` and draws from it the panels that count stars by day in every
store but Prometheus, which cannot hold a history and still counts `gh_star`.

Three things about it were measured rather than read in its documentation. The
days are GitHub's calendar days in America/Los_Angeles, under a `week` labelled
as Sunday 00:00 UTC: against the stargazer lists of nineteen repositories, the
Pacific day matched all 440 stars and the UTC day did not. It counts the
repository's current stargazers, each on the day they starred, so an unstar
takes a star off a day in the past rather than the day it happened. And a 304
answer to it carries no `Link` header, where a 200 carries `next` and `last`,
so the walk reads no `Link` at all and stops at a page shorter than thirty
weeks or an empty one.

## GraphQL is wrong about packages

GraphQL reports zero packages for an account while REST lists them. The pretty
query is simply wrong here, so packages come from REST, at one call per package
for its versions.

## Traffic goes stale rather than empty

A repository with no traffic does not return an empty window. GitHub keeps
returning the last fourteen days that _had_ data, so the window can end weeks
ago. The collector records what it is told.

> **This is why gh_security_feature exists**
>
> Several of the entries above have the same shape: an endpoint that answers
> nothing is indistinguishable from a feature that is switched off, which is
> indistinguishable from a repository with nothing to report.
> `gh_security_feature` records explicitly which features are enabled, so "no
> alerts" and "no data" stop looking alike on a dashboard.

## What this means for a sweep

None of the above is treated as a failure. `ghapi.UnavailableError` (403 or
404: the feature is switched off) and `ghapi.NotReadyError` (202: GitHub is
still computing) both mean "there is nothing here", and the sweep continues to
the next
repository. The activity feeds have their own version of this: past their
ceiling GitHub answers **422 "pagination is limited for this resource"**, which
is read as the end of the data rather than as an error.

## Where to go next

- [Rate limits](https://docs.jmrp.io/ghchronicle/api/) is the other half of this: what the calls
  that do work cost, and why a 304 costs nothing.
- [Cost of a sweep](https://docs.jmrp.io/ghchronicle/api/cost/) prices every family.
