---
title: "GitHub"
description: "Use github.com and GitHub Enterprise Server: issues, pull requests, discussions, notifications, Actions, checks, releases and webhooks."
canonical_url: "https://forges.link/providers/github"
---
# GitHub

> Use github.com and GitHub Enterprise Server: issues, pull requests, discussions, notifications, Actions, checks, releases and webhooks.

The GitHub provider works with github.com and GitHub Enterprise Server. It can read and write issues, pull requests, discussions and commit comments, and it also covers notifications, Actions runs and jobs, checks, releases, security alerts, webhooks and GitHub App installations.

<provider-header provider="github">
<table>
<thead>
  <tr>
    <th>
      Detail
    </th>
    
    <th>
      Value
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Import
    </td>
    
    <td>
      <code>
        forges/github
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      Factories
    </td>
    
    <td>
      <code>
        github()
      </code>
      
      , <code>
        githubLite()
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      Auth
    </td>
    
    <td>
      <code>
        token
      </code>
      
      , <code>
        app
      </code>
      
      , <code>
        anonymous
      </code>
    </td>
  </tr>
</tbody>
</table>
</provider-header>

## Authentication

The provider accepts a personal access token (classic or fine-grained), an OAuth token or the credentials of a GitHub App:

```ts
import { github } from 'forges/github'

const forge = github({
  auth: { type: 'token', token: process.env.GITHUB_TOKEN! },
}).create()

const app = github({
  auth: {
    type: 'app',
    appId: 123456,
    privateKey: process.env.GITHUB_APP_PRIVATE_KEY!,
    installationId: 7890,
  },
}).create()
```

For app authentication, `privateKey` is the PEM key of the app, in PKCS#1 or PKCS#8 format. If you pass an `installationId` as well, the provider acts as that installation, and it creates and caches installation tokens whenever it needs one. If you leave it out, the provider authenticates as the app itself. In that case, `installations.list()` lists the installations of the app, and `installations.provider(installation)` gives you a provider for one of them.

If you leave out `auth` altogether, the provider makes anonymous reads of public data. GitHub serves job logs and code search only to authenticated requests, so `ci.log` and `search.code` aren't supported without `auth`.

An app without an `installationId` can only use `installations`, so every other capability is unsupported for it.

What a token can do depends on its kind, which the provider reads from the token's prefix:

<table>
<thead>
  <tr>
    <th>
      <code>
        kind
      </code>
    </th>
    
    <th>
      Prefix
    </th>
    
    <th>
      Token
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        classic
      </code>
    </td>
    
    <td>
      <code>
        ghp_
      </code>
      
      , <code>
        gho_
      </code>
    </td>
    
    <td>
      A personal access token (classic) or an OAuth app token
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fine-grained
      </code>
    </td>
    
    <td>
      <code>
        github_pat_
      </code>
    </td>
    
    <td>
      A fine-grained personal access token
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        app-user
      </code>
    </td>
    
    <td>
      <code>
        ghu_
      </code>
    </td>
    
    <td>
      A GitHub App user access token
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        installation
      </code>
    </td>
    
    <td>
      <code>
        ghs_
      </code>
    </td>
    
    <td>
      A GitHub App installation access token, such as the <code>
        GITHUB_TOKEN
      </code>
      
       of a workflow
    </td>
  </tr>
</tbody>
</table>

If `token` is a function, pass `kind` as well, or the provider assumes that the token can do anything a token can:

```ts
const forge = github({
  auth: { type: 'token', token: () => refreshUserToken(), kind: 'app-user' },
}).create()
```

GitHub serves notifications only to `classic` tokens, so `notifications` is unsupported for every other kind and for app authentication. `users.me()` needs a token that belongs to an account, so it isn't supported for an `installation` token or an app installation.

## Sponsors

`users.sponsorable(login)` reports whether a user or organisation has a GitHub Sponsors listing, so you can link to `https://github.com/sponsors/<login>` when it does:

```ts
if (await forge.users.sponsorable('danielroe')) {
  console.log('https://github.com/sponsors/danielroe')
}
```

GitHub reports Sponsors listings only over GraphQL, which needs a token or an app installation, so `users.sponsorable` isn't supported without `auth`. GitHub Enterprise Server doesn't have GitHub Sponsors, so it isn't supported there either.

## GitHub Enterprise Server

To use GitHub Enterprise Server, set `baseUrl` to the API root of your server. The `instance` in every ref is then the host of the server:

```ts
github({
  baseUrl: 'https://ghe.example.com/api/v3',
  auth,
  instanceVersion: '3.14.0',
})
```

Two capabilities depend on the version of the server. Marking notifications as done requires version 3.13 or later, and Dependabot alerts require version 3.8 or later. If you know the version, pass it as `instanceVersion`. If you don't, `refreshCapabilities()` reads it from `/meta`.

## Listing pull requests

GitHub lists pull requests in full pages. When you filter by label, author, assignee or `since`, though, the provider can't use that listing and reads the pull requests from GitHub's issues listing instead, which mixes issues and pull requests. The provider drops the issues, so a page can contain fewer items than `perPage`. To list merged pull requests, the provider uses GitHub's search API, which has a lower rate limit and can lag a little behind the repository. See [Page through results](https://forges.link/guides/pagination) for how to deal with short pages.

## Listing an owner's repositories

With `visibility: 'public'`, `repos.byOwner()` lists the repositories of a user or an organisation in a single request. For any other visibility, it reads the repositories of an organisation first. When no organisation has that name, it reads the repositories of the user instead, so listing a user's repositories costs one more request. For the authenticated user, that includes private repositories. GitHub lists only the public repositories of other users, so for them, `visibility: 'private'` or `'internal'` returns an empty page with a `filter_unsupported` warning.

## Contributors

GitHub links at most the first 500 author emails in a repository to accounts. A contributor from `repos.contributors()` whose email is not linked has a `name` and an `email` but no `actor`. GitHub does not list the contributors of a repository whose history is too large.

## Contributor statistics

GitHub computes the statistics behind `repos.contributorStats()` in the background, and responds with `202 Accepted` until they are ready. The provider asks again for about 15 seconds, and then throws a `ForgeApiError` with status `202`, so you can try again later. The statistics leave out merge commits and empty commits. In a repository with 10,000 or more commits, GitHub reports `0` lines added and deleted for every week.

## Templates

`repos.templates()` reads the folders GitHub reads: `.github/ISSUE_TEMPLATE/` for issues, forms first and then Markdown templates, as in the template chooser, and `.github/`, the root or `docs/` for the pull request template, first match wins. Every file in a `PULL_REQUEST_TEMPLATE/` folder comes after it. It's one request per folder and one per template.

When a repository has nothing of a kind, the templates come from the `.github` repository of its owner, like on the web, and carry it in `source`. That is the owner the repository lives under now, so a transferred repository gets the templates of its new owner. The provider uses a `.github` repository only while it is public, or internal, as GitHub does, which costs one more request. A lone `config.yml` in `.github/ISSUE_TEMPLATE/` still counts as having issue templates, so GitHub skips the fallback, and so does the provider. If reading the `.github` repository fails for any reason other than a `404`, `repos.templates()` rejects.

The provider returns each file as it is, so `body` is the raw file, `name` is the file name, and `title`, `about`, `labels` and `fields` stay empty. Parse the front matter or the form in `body` for the name GitHub shows.

## Merging

If you call `merge()` without a `method`, the provider asks GitHub which merge methods the repository allows. When exactly one method is allowed, it uses that one. When several are allowed, it can't choose for you and throws `MergeMethodRequiredError`.

Both `merge()` and `approveAndMerge()` request a direct merge through GitHub's asynchronous merge API, which means that neither of them adds the pull request to a merge queue. They wait for GitHub to report the result, within the `timeout` of the provider (30 seconds by default), and resolve with the merge commit once the pull request is merged. That includes a pull request that was already merged. In every other case, they reject with one of these errors:

- `MergeBlockedError` when GitHub refuses or fails the merge, for example because of a draft, a failing required check or a pull request that is already in a merge queue. If GitHub reports a failed merge, the message of the error is GitHub's description of the failure.
- `MergeConflictError` when GitHub responds with a conflict status that doesn't name a pending merge request.
- `ForgeTimeoutError` when the merge is still pending after `timeout`. The message includes the UUID of the merge request. GitHub can still complete the merge after this error, so read the state of the pull request before you try again.

If a direct merge with the same method is already pending, and it expects the same head sha when you pass `sha`, the operation waits for that request instead of starting a new one. A pending request with different options rejects with `MergeBlockedError`. Passing a `title` or a `message` also prevents the provider from adopting a pending request, because GitHub doesn't return the commit title or message of a request.

When the pull request is part of a stack, GitHub also merges every open pull request below it in the stack. `approveAndMerge()` still approves only the pull request that you pass. GitHub Enterprise Server releases without the asynchronous merge API use the synchronous merge endpoint instead, and that endpoint doesn't support stacked pull requests.

Two options aren't available, and they reject with `UnsupportedOperationError`. One is `whenChecksPass`, because the REST API doesn't enable auto-merge. The other is the `rebase_merge` and `fast_forward_only` methods, which GitHub doesn't have.

## Review replies

GitHub doesn't support replies to replies, so when you pass a reply to `replyToReviewComment()`, it posts to the comment in its `inReplyTo` instead. The new comment carries the `thread` of the comment you pass, so you can call `resolveReviewThread()` with it.

## Checks

What `checks.report()` writes depends on your credential. With the credential of an app installation, it writes a check run, and with any other credential it writes a commit status. `checks.rerun()` re-requests a check run, so it can't re-run a commit status.

## Large files and trees

Files over 1 MB are read through the Git blobs API, so the result of `contents.file()` has `encoding: 'none'` for them. When GitHub truncates a large tree, `contents.tree()` adds a `tree_truncated` warning to the result.

## Comparisons

Without `commitLimit`, `contents.compare()` returns the newest 250 commits of the comparison. GitHub pages a comparison from its oldest commit, so with `commitLimit`, the provider reads the first page, and then the last pages, which hold the newest commits. Each page holds `commitLimit` commits, up to 100. A comparison that fits on the first page takes one request. GitHub always sends the changed files with the first page, up to 300 of them, so `files: false` leaves them out of the result but not out of the response.

## Committing files

Without `author`, `contents.commitFiles()` makes the commit with one GraphQL `createCommitOnBranch` mutation, so GitHub signs it and attributes it to the account of the credential. With `author`, the provider writes the commit through the Git database API instead, and moves the branch with the GraphQL `updateRefs` mutation, which checks that the branch is still where the change started. GitHub doesn't sign that commit, and it records `author` as the committer too.

Without `author`, `createFrom` creates the branch before the commit. If the commit fails, the provider deletes the branch again, unless it has moved since.

A file keeps its mode when you write over it: an executable file stays executable, and a symlink stays a symlink, pointing at the new contents.

## Search

GitHub gives search a lower rate limit than the rest of its API, and code search has a limit of its own, separate from the search for issues, commits and repositories. After a search, `page.rateLimit` reports the limit that the search used, and its `resource` names it, such as `search` or `code_search`. `rateLimits()` and `onRateLimit` keep it apart from the `core` budget of the rest of the API.

Repository search can't sort by creation time. If you ask for that order, you get the results by relevance, together with a `sort_unsupported` warning.

When you call `search.threads()` without a `kind`, it uses GitHub's advanced search to return issues and pull requests in a single sorted list. `text` and `queryRaw` are each wrapped in parentheses, so an `OR` in one of them stays inside it. Parentheses and an unclosed `"` in `text` are ignored, in the same way that GitHub's legacy search ignores them. On GitHub Enterprise Server, or with a GitHub App user access token (`ghu_`), the provider searches issues first and pull requests after that instead, so the results are only sorted within each kind.

`queryRaw` is added to the search query as it is, which means you can use any [GitHub search qualifier](https://docs.github.com/search-github/searching-on-github):

```ts
const page = await gh.search.threadsPage({ kind: 'pull_request', queryRaw: 'review-requested:@me' })
```

`search.code()` gets the tightest limit of all: 10 requests a minute, in a pool of its own. It only sees the default branch, and only files under 384 KB. Each result is a file, with `ref` set to the commit that GitHub indexed. `fragments` holds the excerpts that GitHub highlighted. They have no line numbers, because GitHub doesn't send any. When GitHub stops a search before it finishes, the page has a `search_incomplete` warning.

## GraphQL

For what the data model doesn't cover, a GitHub provider has `graphql()`, which sends a query or mutation to the GraphQL API of its instance with the provider's credentials. It resolves with the `data` of the response. When the response carries errors, it rejects with a `ForgeApiError`, with an `InsufficientScopeError` when the token lacks a scope that a field needs, or with a `RateLimitedError` for a rate limit, which GitHub reports with a `200`:

```ts
const { viewer } = await forge.graphql<{ viewer: { login: string } }>(
  'query { viewer { login } }',
)
```

To have the result and the variables typed for you, pass a typed document instead of a string. [GraphQL Code Generator](https://the-guild.dev/graphql/codegen) creates them from GitHub's [public schema](https://docs.github.com/public/fpt/schema.docs.graphql) with its client preset and `documentMode: 'string'`, in `codegen.ts`:

```ts
import type { CodegenConfig } from '@graphql-codegen/cli'

export default {
  schema: 'https://docs.github.com/public/fpt/schema.docs.graphql',
  documents: ['src/**/*.ts'],
  generates: {
    './src/gql/': { preset: 'client', config: { documentMode: 'string' } },
  },
} satisfies CodegenConfig
```

The result of `graphql()` then has the type of the document's selection, and the variables that the document requires must be passed:

```ts
import { graphql } from './gql'

const Stars = graphql(`
  query Stars($owner: String!, $name: String!) {
    repository(owner: $owner, name: $name) { stargazerCount }
  }
`)

const { repository } = await forge.graphql(Stars, { owner: 'danielroe', name: 'forges' })
```

A read-only provider runs queries and rejects mutations with `ReadOnlyError`. GitHub's GraphQL API needs a credential, so an anonymous provider can't use it. Accounts in the data model carry the numeric ID, which GraphQL calls `databaseId`, so select that field to compare them with your results.

## Activity feeds

`repos.events()` and `users.events()` read GitHub's events API. A feed holds up to 300 events from the last 30 days, and GitHub can take from 30 seconds to 6 hours to add an event to it. Events come in the order GitHub added them, so an event that arrived late can follow one that happened after it. When the credential belongs to the account you read, `users.events()` includes its private activity too.

GitHub asks clients to wait between reads of a feed, usually 60 seconds, in its `X-Poll-Interval` header. The provider remembers that wait for each feed. If you read the first page of a feed again before it's over, you get a page with `throttled: true` and no items, and no request is sent. The page keeps the `etag` you passed and carries a `feed_throttled` warning. A throttled feed and a quiet one both yield nothing from `events()`, so the warning is the only way to tell them apart:

```ts
const events = gh.repos.events(repo)
for await (const event of events) {
  console.log(event.summary)
}
if (events.warnings.some(warning => warning.code === 'feed_throttled')) {
  // too soon, not empty
}
```

To read anyway, pass `force: true`:

```ts
const page = await gh.repos.eventsPage(repo, { force: true })
```

The provider only remembers the wait for as long as it exists, so a job that creates a new provider for every run isn't held back. Such a job can keep the `nextPollAt` of the page it read, which says when GitHub allows the next read, and schedule its next run for then.

`notifications.listPage()` follows the same rules, with one wait for the whole notifications listing, and takes `force: true` as well.

Feed items are smaller than webhook deliveries. On GitHub.com, a push has no commits and no commit count, so its `detail` has no `commitCount` and its summary leaves the number out. GitHub Enterprise Server still sends both, and they fill in the detail there. A pull request event has no title, and GitHub reports a merge as the action `merged`, which the provider reads as `kind: 'state_change'` and `action: 'merged'`.

## Webhook management

If the credential lacks `admin:repo_hook` or `admin:org_hook`, GitHub responds with a `404` on its webhook endpoints. The provider raises this response as a `ForbiddenError` with `reason: 'resource_protected'`, so check the scopes of your credential when you see it.

`webhooks.deliveries()` reads the delivery log of a hook, and `webhooks.redeliver()` sends a delivery again.

## Webhooks

To verify deliveries, set `webhookSecret` to the secret that you configured on the hook:

```ts
const forge = github({
  webhookSecret: process.env.GITHUB_WEBHOOK_SECRET,
}).create()

const events = await forge.webhooks.ingest({
  headers: request.headers,
  body: await request.text(),
})
```

With each delivery, GitHub sends these headers:

<table>
<thead>
  <tr>
    <th>
      Header
    </th>
    
    <th>
      Content
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        X-Hub-Signature-256
      </code>
    </td>
    
    <td>
      <code>
        sha256=
      </code>
      
       followed by the hex HMAC-SHA256 of the body
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        X-GitHub-Event
      </code>
    </td>
    
    <td>
      The event name
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        X-GitHub-Delivery
      </code>
    </td>
    
    <td>
      The delivery ID
    </td>
  </tr>
</tbody>
</table>

Deliveries of the `installation` and `installation_repositories` events become `installation` events.

## Organisation teams

`orgs.teams()` reads the teams of an organisation with `GET /orgs/{org}/teams`, and `orgs.teamMembers()` reads `GET /orgs/{org}/teams/{slug}/members`. Both need a token with the `read:org` scope, or the `members` read permission on a fine-grained token, so `can('orgs.teams')` is `false` without a credential. A team's members include the members of its child teams.

## Capabilities

<provider-capabilities provider="github">
<table>
<thead>
  <tr>
    <th>
      Capability
    </th>
    
    <th>
      Classic token
    </th>
    
    <th>
      Fine-grained token
    </th>
    
    <th>
      App installation
    </th>
    
    <th>
      App
    </th>
    
    <th>
      Without credentials
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        experimental
      </code>
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sources.poll
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sources.webhook
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sources.subscribe
      </code>
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.get
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        users.get
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        users.me
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        users.sponsorable
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        users.events
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.list
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.byOwner
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.labels
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.createLabel
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.milestones
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.collaborators
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.contributors
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.contributorStats
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.templates
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.permissionFor
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.addCollaborator
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.assignableUsers
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.reviewerCandidates
      </code>
    </td>
    
    <td>
      emulated
    </td>
    
    <td>
      emulated
    </td>
    
    <td>
      emulated
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repos.events
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        orgs.teams
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        orgs.teamMembers
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        threads.get
      </code>
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      issue, PR, commit
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        threads.list
      </code>
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      issue, PR
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        threads.getMany
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        threads.events
      </code>
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      issue, PR, commit
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        comments.list
      </code>
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      issue, PR, commit
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        comments.get
      </code>
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      issue (unverified), PR, commit (unverified)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        comments.edit
      </code>
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        comments.delete
      </code>
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reactions.list
      </code>
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      issue, PR
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        notifications.list
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        notifications.markRead
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        notifications.markDone
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        notifications.unsubscribe
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        notifications.markAllRead
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        notifications.markAllDone
      </code>
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        notifications.unreadCount
      </code>
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.comment
      </code>
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      issue, PR, discussion, commit
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.upsertComment
      </code>
    </td>
    
    <td>
      issue (emulated), PR (emulated), discussion (emulated), commit (emulated)
    </td>
    
    <td>
      issue (emulated), PR (emulated), discussion (emulated), commit (emulated)
    </td>
    
    <td>
      issue (emulated), PR (emulated), discussion (emulated), commit (emulated)
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.close
      </code>
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.reopen
      </code>
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.create
      </code>
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.update
      </code>
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.setLabels
      </code>
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.addLabels
      </code>
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.removeLabels
      </code>
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.setMilestone
      </code>
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.react
      </code>
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.setAssignees
      </code>
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      issue, PR
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.requestReview
      </code>
    </td>
    
    <td>
      PR
    </td>
    
    <td>
      PR
    </td>
    
    <td>
      PR
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.merge
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.approveAndMerge
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.transfer
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        writes.markDuplicate
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        subscriptions.get
      </code>
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        subscriptions.set
      </code>
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      issue, PR, discussion
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        installations
      </code>
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        checks.thread
      </code>
    </td>
    
    <td>
      PR
    </td>
    
    <td>
      PR
    </td>
    
    <td>
      PR
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      PR
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        checks.list
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        checks.get
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        checks.report
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        checks.rerun
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ci.runs
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ci.run
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ci.jobs
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ci.job
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ci.log
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.file
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.tree
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.branches
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.tags
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.resolveRef
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.commits
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.commit
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.compare
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.commitFiles
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.threadFiles
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        contents.threadCommits
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reviews.list
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reviews.get
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      unverified
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reviews.create
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reviews.submit
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reviews.approve
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reviews.reply
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reviews.resolveThread
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        releases.list
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        releases.get
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        releases.latest
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        releases.getByTag
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        releases.downloadAsset
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        releases.create
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        releases.update
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        webhooks.list
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        webhooks.create
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        webhooks.update
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        webhooks.delete
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        webhooks.rotateSecret
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        webhooks.deliveries
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        webhooks.redeliver
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        search.threads
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        search.repos
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        search.commits
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ✅
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        search.code
      </code>
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ✅
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        securityAlerts
      </code>
    </td>
    
    <td>
      dependency, code scanning, secret
    </td>
    
    <td>
      dependency, code scanning, secret
    </td>
    
    <td>
      dependency, code scanning, secret
    </td>
    
    <td>
      ❌
    </td>
    
    <td>
      ❌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        eventKinds
      </code>
    </td>
    
    <td>
      native
    </td>
    
    <td>
      native
    </td>
    
    <td>
      native
    </td>
    
    <td>
      native
    </td>
    
    <td>
      native
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        authKinds
      </code>
    </td>
    
    <td>
      <code>
        token
      </code>
      
      , <code>
        app
      </code>
      
      , <code>
        anonymous
      </code>
    </td>
    
    <td>
      <code>
        token
      </code>
      
      , <code>
        app
      </code>
      
      , <code>
        anonymous
      </code>
    </td>
    
    <td>
      <code>
        token
      </code>
      
      , <code>
        app
      </code>
      
      , <code>
        anonymous
      </code>
    </td>
    
    <td>
      <code>
        token
      </code>
      
      , <code>
        app
      </code>
      
      , <code>
        anonymous
      </code>
    </td>
    
    <td>
      <code>
        token
      </code>
      
      , <code>
        app
      </code>
      
      , <code>
        anonymous
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        limits
      </code>
    </td>
    
    <td>
      body 65536, comment 65536, label 50
    </td>
    
    <td>
      body 65536, comment 65536, label 50
    </td>
    
    <td>
      body 65536, comment 65536, label 50
    </td>
    
    <td>
      body 65536, comment 65536, label 50
    </td>
    
    <td>
      body 65536, comment 65536, label 50
    </td>
  </tr>
</tbody>
</table>

Support depends on the kind of credential:

- `classic` (Classic token): A personal access token (classic) or an OAuth app token
- `fine-grained` (Fine-grained token): A fine-grained personal access token or a GitHub App user access token
- `installation` (App installation): An app with an `installationId`, or an installation access token such as the `GITHUB_TOKEN` of a workflow
- `app` (App): An app without an `installationId`

</provider-capabilities>


## Sitemap

See the full [sitemap](https://forges.link/sitemap.md) for all pages.
