# Lo que GitHub no da

Los endpoints que se ha verificado que no funcionan en una cuenta personal, escritos para que nadie los vuelva a descubrir.

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

Cada entrada de aquí se comprobó contra la API real desde una cuenta personal, y
la mayor parte no está en la documentación de GitHub, que describe lo que un endpoint
debería devolver y no lo que devuelve. Está escrita para que nadie
pierda una tarde volviendo a averiguarlo, y para que un panel que falta se pueda
distinguir de un colector roto.

## ¿Por qué dos endpoints de estadísticas no responden nunca?

`stats/code_frequency` y `stats/contributors` responden **202 con cuerpo vacío,
indefinidamente**, en una cuenta personal. Un 202 normalmente significa "aún se
está calculando, vuelve a preguntar", y para estos dos la siguiente respuesta es
otro 202. No se llaman a propósito.

Las líneas añadidas y quitadas que habría dado `code_frequency` salen en su
lugar del colector de commits, por commit y no por semana, atribuidas a un autor
y fechadas en el commit. `stats/participation` y `stats/punch_card` sí funcionan
y se usan.

Diez segundos bastan para verlo en tu propia cuenta:

```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, para siempre
curl -s -o /dev/null -w '%{http_code}\n' \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  https://api.github.com/repos/OWNER/REPO/stats/participation    # 200
```

## Facturación

| Endpoint                                | Respuesta |
| --------------------------------------- | --------- |
| `/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` | funciona  |

Solo la última forma funciona para una cuenta personal, y devuelve marcas de
tiempo RFC 3339 completas en un campo que su documentación describe como fecha.

## Solo para organización o empresa

Propiedades personalizadas de repositorio, proyectos clásicos, centros de coste
y el registro de auditoría. Una cuenta personal no puede ver ninguno, sean
cuales sean los permisos del token.

## Endpoints que responden, pero no dicen nada

- **`workflows/{id}/timing`** devuelve 200 con un objeto `billable` siempre
  vacío. Parece la fuente de los minutos por workflow y no lo es.
- **La lista de stargazers, para quien no administra ni colabora en el repositorio.**
  [Desde julio de 2026](https://docs.github.com/es/rest/activity/starring#new-access-restrictions)
  GitHub no la sirve a nadie más. REST responde 404, y `stargazers` en GraphQL
  responde una lista vacía con `totalCount` 0 mientras `stargazerCount`, a su
  lado, sigue dando el número real: medido en `cli/cli` y `octocat/Hello-World`
  con un token con todos los permisos. Por eso ghchronicle escribe `gh_star`,
  quién dio la estrella y cuándo al segundo, solo donde el token tiene ese
  acceso, que siempre tiene en los repositorios de la propia cuenta y en los de
  una organización que la cuenta administra; uno nombrado en `targets.repos` o
  alcanzado por `targets.orgs` sin él tiene sus estrellas contadas por día con
  el historial de abajo, y a nadie nombrado.
- **`/user/installations`** devuelve 403 sin una GitHub App.

## El historial de estrellas que github.com sirve a cualquiera

[`stargazers/history`](https://docs.github.com/es/rest/activity/starring#get-repository-star-history)
responde donde la lista de stargazers no lo hace. Lo sirve a cualquiera que
pueda ver el repositorio, también sin autenticar: las estrellas dadas por día,
agrupadas por semana, treinta semanas por página, el valor por defecto y el
máximo que admite `per_page` (uno menor se respeta, uno mayor se recorta a
treinta), paginando hasta la primera semana del repositorio (medido en
`cli/cli`: trece páginas, hasta 2019). No nombra a ningún stargazer, así que no
puede sustituir a `gh_star`, que es una fila por estrella en el instante en que
se dio y dice quién la dio. Sí puede sustituir al recuento, y ghchronicle lo lee
para cada repositorio que recoge, lo escribe como `gh_star_day` y dibuja con él
los paneles que cuentan estrellas por día en todos los almacenes menos
Prometheus, que no puede guardar un historial y sigue contando `gh_star`.

Tres cosas de él se midieron en lugar de leerse en su documentación. Los días
son días naturales de GitHub en America/Los_Angeles, bajo una `week` etiquetada
como domingo a las 00:00 UTC: contra las listas de stargazers de diecinueve
repositorios, el día del Pacífico acertó en las 440 estrellas y el día UTC no.
Cuenta los stargazers actuales del repositorio, cada uno en el día en que marcó
la estrella, así que quitar una estrella la saca de un día del pasado y no del
día en que ocurrió. Y un 304 suyo no lleva cabecera `Link`, mientras que un 200
lleva `next` y `last`, así que el recorrido no lee `Link` en absoluto y se
detiene en una página de menos de treinta semanas o en una vacía.

## GraphQL se equivoca con los paquetes

GraphQL informa de cero paquetes para una cuenta mientras REST los lista. Aquí
la consulta bonita está sencillamente equivocada, así que los paquetes vienen de
REST, a una llamada por paquete para sus versiones.

## El tráfico se queda obsoleto, no vacío

Un repositorio sin tráfico no devuelve una ventana vacía. GitHub sigue
devolviendo los últimos catorce días que _tuvieron_ datos, así que la ventana
puede terminar hace semanas. El colector anota lo que le dicen.

> **Por esto existe gh_security_feature**
>
> Varias de las entradas de arriba tienen la misma forma: un endpoint que no
> responde nada es indistinguible de una función apagada, que es indistinguible
> de un repositorio sin nada que informar. `gh_security_feature` anota
> explícitamente qué funciones están activadas, para que "sin alertas" y "sin
> datos" dejen de parecerse en un dashboard.

## Qué significa esto para una pasada

Nada de lo anterior se trata como un fallo. `ghapi.UnavailableError` (403 o
404: la función está apagada) y `ghapi.NotReadyError` (202: GitHub aún está
calculando) significan ambos "aquí no hay nada", y la pasada sigue con el
siguiente
repositorio. Los feeds de actividad tienen su propia versión de esto: pasado su
techo GitHub responde **422 "pagination is limited for this resource"**, que se
lee como el final de los datos y no como un error.

## Por dónde seguir

- [Límites de la API](https://docs.jmrp.io/ghchronicle/es/api/) es la otra mitad de esto: lo que
  cuestan las llamadas que sí funcionan, y por qué un 304 no cuesta nada.
- [Coste de una pasada](https://docs.jmrp.io/ghchronicle/es/api/cost/) pone precio a cada familia.
