> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nephia.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub

> What a Nephia Watch on GitHub captures, and what arrives in each event.

<Note>
  GitHub needs a token on the deployment. On Nephia's hosted API it is configured; if you self-host, set `GITHUB_TOKEN` (a fine-grained token with **public read** is enough) or this Source will not be offered. `GET /account` reports which Sources a deployment offers in `capabilities.liveSources`.
</Note>

## The item

A GitHub Watch emits a **GithubItem**, and `type` says which of four things it is: `issue`, `pull_request`, `repository` or `release`.

`pull_request` is its own type rather than a flag. GitHub's issue search returns pull requests — they *are* issues to GitHub — and a reader filtering for one or the other should not have to know that.

`repo` is `owner/name` and is present on all four types, including a repository row. `stars` is present only on a repository: an issue has no audience GitHub reports, so it contributes `null` rather than a zero dressed up as one.

`body` is truncated to 4 000 characters. A release changelog runs to tens of kilobytes and a stored jsonb column is not where that belongs.

## Coverage

A Watch requires **exactly one of `query` or `repo`** — they are two different endpoints.

| Criterion | Values                   | Default  |
| --------- | ------------------------ | -------- |
| `query`   | GitHub search syntax     | —        |
| `kind`    | `issues`, `repositories` | `issues` |
| `repo`    | `owner/name`             | —        |

### query — GitHub's own syntax, passed through

Whatever you write reaches GitHub untouched: `in:title,body`, `org:vercel`, `repo:owner/name`, `label:bug`, `type:pr`, `type:issue`, `NOT`, `OR`, quoted phrases. Re-implementing any of that here would be a second, worse search language on top of one you already know.

That is also why this Source takes no `terms` list: `foo OR bar` is already expressible, in GitHub's spelling.

`kind: "issues"` returns issues **and** pull requests. Add `type:issue` to the query if you only want one.

Search is capped at **256 characters** — GitHub's limit, and it answers `422` past it, so a longer query is refused when the Watch is created rather than failing on every tick.

### repo — one project's releases

`repo: "vercel/next.js"` polls that project's releases instead of searching. **Drafts are skipped** — a draft is visible only to the project's own maintainers, and announcing one would announce what they have not. **Prereleases are kept**, with `state: "prerelease"`: "they cut an rc" is exactly the news a release watch is for.

### Rate limits, and why the floor is five minutes

GitHub's search budget is **30 requests a minute per token**, and the token belongs to the deployment rather than to your Watch. Twenty Watches at the 300 s floor is 4 requests a minute, which leaves room for Explore runs and retries on the same token. A shorter floor would fit the cap on paper and have no headroom for a burst; the failure mode of exceeding it is a `403` for every user of the Source at once.

The releases leg is cheaper still: it is an ordinary REST read on the 5 000-per-hour budget, and it sends a conditional request — a `304` costs no budget at all.

**Not covered**: Discussions (GraphQL-only) and code search (a different token scope). Both are deferred rather than silently missing.

Interval: **300–86400** seconds. Cap: **20** active Watches per Account. Each tick costs **1 credit**, including a tick that gets a `304`.

## What an event carries

The first tick establishes a silent baseline and emits nothing. Later ticks emit `github_item.created`. `webhook_url` is optional — without it the Watch still records every match, readable through `GET /v1/github/watches/{id}/events`. See [Webhooks](/webhooks).

```bash theme={null}
curl -X POST https://api.nephia.cc/v1/github/watches \
  -H "x-api-key: $NEPHIA_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "query": "nephia in:title,body NOT is:archived",
    "kind": "issues",
    "refresh_interval_seconds": 300,
    "webhook_url": "https://example.com/hooks/nephia"
  }'
```

Watching a project's releases:

```bash theme={null}
curl -X POST https://api.nephia.cc/v1/github/watches \
  -H "x-api-key: $NEPHIA_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "repo": "vercel/next.js",
    "refresh_interval_seconds": 900
  }'
```

The search leg narrows with a `created:>` qualifier and also dedupes by id, so an item the index picks up late still arrives exactly once.

## Errors

A temporary GitHub failure is **503** and is not charged; the Watch reports it in its activity, readable through `GET /v1/github/watches/{id}/activity`. A deployment with no `GITHUB_TOKEN` answers **503** on these routes and omits `github` from `capabilities.liveSources`.
