> ## 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 keyword captures on GitHub, 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 search 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 search requires **exactly one of `query` or `repo`**: they are two different reads. `kind` and `repo` are this Source's own criteria: on the keyword they go in the search's `overrides.filters` (see [Keywords](/keywords#create)).

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

### 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. It answers `422` past it, so a longer query is refused when the keyword is written 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 search 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 keyword. Twenty searches 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, and 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 to 86400** seconds. At most **20** active GitHub searches 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`. `webhookUrl` is optional: without it the keyword still records every match, readable through `GET /v1/keywords/{id}/events` in the same shape. See [Webhooks](/webhooks#replay).

```bash theme={null}
curl -X POST https://api.nephia.cc/v1/keywords \
  -H "x-api-key: $NEPHIA_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "name": "nephia on GitHub",
    "refreshIntervalSeconds": 300,
    "globalCriteria": { "market": "global", "query": "nephia in:title,body NOT is:archived" },
    "sources": [
      {
        "source": "github",
        "enabled": true,
        "searches": [
          {
            "overridesEnabled": true,
            "overrides": {
              "filters": {
                "kind": "issues"
              }
            }
          }
        ]
      }
    ],
    "webhookUrl": "https://example.com/hooks/nephia"
  }'
```

Watching a project's releases:

```bash theme={null}
curl -X POST https://api.nephia.cc/v1/keywords \
  -H "x-api-key: $NEPHIA_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "name": "Next.js releases",
    "refreshIntervalSeconds": 900,
    "globalCriteria": { "market": "global" },
    "sources": [
      {
        "source": "github",
        "enabled": true,
        "searches": [
          {
            "overridesEnabled": true,
            "overrides": {
              "filters": {
                "repo": "vercel/next.js"
              }
            }
          }
        ]
      }
    ]
  }'
```

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 keyword reports it in its activity, readable through `GET /v1/keywords/{id}/activity`. A deployment with no `GITHUB_TOKEN` omits `github` from `capabilities.liveSources`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.