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

# GitHub

> Overview of the GitHub provider and registering webhooks

## Overview

GitHub allows you to create two kinds of webhooks.

1. **Organization Webhooks** : These are webhooks that are created at the organization level. They are triggered by events that happen in the organization.
2. **Repository Webhooks** : These are webhooks that are created at the repository level. They are triggered by events that happen in the repository.

### GitHub API Quirks

Every GitHub REST API request for creating a webhook requires a minimum of either an `organization` or a combination of an `organization` and a `repository`. We provider two usefull hooks to help you get the `organization` and `repository` values for your users. See the below example on how to create a webhook for your user.

### Creating a Webhook for a User using the SDK

1. **Get a list of your users Organizations with useGetGitHubOrganizations**: This hook returns a list of organizations that the user is a part of based off of their GitHub access token. You can get this access token from your third party provider like `Nango`.

   ```javascript create-GitHub.ts theme={null}
   import { useGetGitHubOrganizations } from 'syncd-hooks';
   ...
   // Note: this is not async
   const { data, isLoading, error } = useGetGitHubOrganizations({
    // Get this from a third party like Nango
    accessToken,
   });
   ...
    <select
    name="org"
    id="org"
    >
      {isLoading && <option value="loading">Loading...</option>}
      <option value="default">Select an organization</option>
      {data?.map((org) => (
        <option key={org.id} value={org.login}>
          {org.login}
        </option>
      ))}
   </select>
   ...
   ```

2. **(OPTIONAL) Get a list of your users Repositories with useGetGitHubReposForOrganization**: If you want to listen to a specific repository and not just the overarching Organization, this hook returns a list of repositories that the user is a part of based off of their GitHub access token and the organization they chose in the previous step. Don't worry about the organization name not being selected yet, the repo hook handles the retry logic for you.

   ```javascript create-GitHub.ts theme={null}
   import { useGetGitHubReposForOrganization } from 'syncd-hooks;
   ...
   // Note: this is not async
   const { data, isLoading, error } = useGetGitHubReposForOrganization({
    accessToken: <access-token>,
    // get this from the useGetGitHubOrganizations hook
    organization: <organization-name>,
   });
   ...
    <select
    name="org"
    id="org"
    >
      {isLoading && <option value="loading">Loading...</option>}
      <option value="default">Select an organization</option>
      {data?.map((org) => (
        <option key={org.id} value={org.login}>
          {org.login}
        </option>
      ))}
   </select>
   ...
   ```

3. Create a new webhook with all the information we gatherd from our user in the previous steps.

```javascript create-GitHub.ts theme={null}
/**
 * We use JSDocs in the SDK to give you the best experience possible.
 * If you need to know what a function does, you can hover over it in your IDE.
 * If you need to know why you need a projectId for example, you can hover over it.
 */
const res = await syncdClient.providers.github.webhooks.create({
  accessToken: nango.github,
  callbackUrl: "<your-callback-url>",
  events: ["*"],
  // This can be anything you want... just for the dashboard so you can identify the webhook
  endpointName: `${
    user.id
  } - github - ${selectedOrg} - ${selectedRepo} - ${new Date().toISOString()}`,
  // Get this from the useGetGitHubReposForOrganization hook
  organization: selectedOrg,
  // Get this from the dashboard... it is safe to use on the client side
  projectId: "project_123",
  type: "org", // either org or repo
  endpoindDescription: "This is a test endpoint",
  // If you want to associate this with a user in your app
  // pass this through - but change the information to your user
  externalUser: {
    uniqueId: user.id,
    firstName: "Thomas",
    lastName: "Cistulli",
    metadata: {
      email: "tcistull@syncd.dev",
    },
  },
});
```

### Updating a Webhook for a User

If you want you can update an existing webhook to listen to new events, update callback endpoints, and more. The resulting webhook will be under the same project and endpointId so you don't need to worry about updating things in your database/storage.

This would look something like this:

```javascript theme={null}
await syncdClient.providers.github.webhooks.update({
  ...
})
```

### Example Payloads

With each provider we have example payloads so you can test the webhook events. This can be useful for debugging and testing your application.

To import, each payload example starts with the provider name and then the event name. For example, `figmaFileCommentEventExamplePayload`. Use intelligent auto-complete in your IDE to find the payload you need.

Here is an example payload for `branch_protection_rule`:

```javascript theme={null}
  {
    "name": "branch_protection_rule",
    "description": "Activity related to a branch protection rule. For more information, see \"[About branch protection rules](https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches#about-branch-protection-rules).\"",
    "actions": ["created", "deleted", "edited"],
    "properties": {
      "rule": {
        "type": "object",
        "description": "The branch protection rule. Includes a `name` and all the [branch protection settings](https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches#about-branch-protection-settings) applied to branches that match the name. Binary settings are boolean. Multi-level configurations are one of `off`, `non_admins`, or `everyone`. Actor and build lists are arrays of strings."
      },
      "changes": {
        "type": "object",
        "description": "If the action was `edited`, the changes to the rule."
      },
      "repository": {
        "type": "object",
        "description": "The [`repository`](https://docs.github.com/en/rest/reference/repos#get-a-repository) where the event occurred."
      },
      "organization": {
        "type": "object",
        "description": "Webhook payloads contain the [`organization`](https://docs.github.com/en/rest/reference/orgs#get-an-organization) object when the webhook is configured for an organization or the event occurs from activity in a repository owned by an organization."
      },
      "sender": {
        "type": "object",
        "description": "The user that triggered the event."
      }
    },
    "examples": [
      {
        "action": "edited",
        "rule": {
          "id": 21796960,
          "repository_id": 259377789,
          "name": "production",
          "created_at": "2021-08-19T12:16:32.000-04:00",
          "updated_at": "2021-08-19T12:16:32.000-04:00",
          "pull_request_reviews_enforcement_level": "off",
          "required_approving_review_count": 1,
          "dismiss_stale_reviews_on_push": false,
          "require_code_owner_review": false,
          "authorized_dismissal_actors_only": false,
          "ignore_approvals_from_contributors": false,
          "required_status_checks": ["basic-CI"],
          "required_status_checks_enforcement_level": "non_admins",
          "strict_required_status_checks_policy": false,
          "signature_requirement_enforcement_level": "off",
          "linear_history_requirement_enforcement_level": "off",
          "admin_enforced": false,
          "allow_force_pushes_enforcement_level": "off",
          "allow_deletions_enforcement_level": "off",
          "merge_queue_enforcement_level": "off",
          "required_deployments_enforcement_level": "off",
          "required_conversation_resolution_level": "off",
          "authorized_actors_only": true,
          "authorized_actor_names": ["Codertocat"]
        },
        "changes": {
          "authorized_actors_only": { "from": false },
          "authorized_actor_names": { "from": [] }
        },
        "repository": {
          "id": 17273051,
          "node_id": "MDEwOlJlcG9zaXRvcnkxNzI3MzA1MQ==",
          "name": "octo-repo",
          "full_name": "octo-org/octo-repo",
          "private": true,
          "owner": {
            "login": "octo-org",
            "id": 6811672,
            "node_id": "MDEyOk9yZ2FuaXphdGlvbjY4MTE2NzI=",
            "avatar_url": "https://avatars.githubusercontent.com/u/6811672?v=4",
            "gravatar_id": "",
            "url": "https://api.github.com/users/octo-org",
            "html_url": "https://github.com/octo-org",
            "followers_url": "https://api.github.com/users/octo-org/followers",
            "following_url": "https://api.github.com/users/octo-org/following{/other_user}",
            "gists_url": "https://api.github.com/users/octo-org/gists{/gist_id}",
            "starred_url": "https://api.github.com/users/octo-org/starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users/octo-org/subscriptions",
            "organizations_url": "https://api.github.com/users/octo-org/orgs",
            "repos_url": "https://api.github.com/users/octo-org/repos",
            "events_url": "https://api.github.com/users/octo-org/events{/privacy}",
            "received_events_url": "https://api.github.com/users/octo-org/received_events",
            "type": "Organization",
            "site_admin": false
          },
          "html_url": "https://github.com/octo-org/octo-repo",
          "description": "My first repo on GitHub!",
          "fork": false,
          "url": "https://api.github.com/repos/octo-org/octo-repo",
          "forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks",
          "keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}",
          "collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}",
          "teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams",
          "hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks",
          "issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}",
          "events_url": "https://api.github.com/repos/octo-org/octo-repo/events",
          "assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}",
          "branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}",
          "tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags",
          "blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}",
          "git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}",
          "git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}",
          "trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}",
          "statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}",
          "languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages",
          "stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers",
          "contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors",
          "subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers",
          "subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription",
          "commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}",
          "git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}",
          "comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}",
          "issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}",
          "contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}",
          "compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}",
          "merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges",
          "archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}",
          "downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads",
          "issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}",
          "pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}",
          "milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}",
          "notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}",
          "labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}",
          "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}",
          "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments",
          "created_at": "2014-02-28T02:42:51Z",
          "updated_at": "2021-03-11T14:54:13Z",
          "pushed_at": "2021-03-11T14:54:10Z",
          "git_url": "git://github.com/octo-org/octo-repo.git",
          "ssh_url": "org-6811672@github.com:octo-org/octo-repo.git",
          "clone_url": "https://github.com/octo-org/octo-repo.git",
          "svn_url": "https://github.com/octo-org/octo-repo",
          "homepage": "",
          "size": 300,
          "stargazers_count": 0,
          "watchers_count": 0,
          "language": "JavaScript",
          "has_issues": true,
          "has_projects": false,
          "has_downloads": true,
          "has_wiki": false,
          "has_pages": true,
          "forks_count": 0,
          "mirror_url": null,
          "archived": false,
          "disabled": false,
          "open_issues_count": 39,
          "license": null,
          "forks": 0,
          "open_issues": 39,
          "watchers": 0,
          "default_branch": "main"
        },
        "organization": {
          "login": "octo-org",
          "id": 6811672,
          "node_id": "MDEyOk9yZ2FuaXphdGlvbjY4MTE2NzI=",
          "url": "https://api.github.com/orgs/octo-org",
          "repos_url": "https://api.github.com/orgs/octo-org/repos",
          "events_url": "https://api.github.com/orgs/octo-org/events",
          "hooks_url": "https://api.github.com/orgs/octo-org/hooks",
          "issues_url": "https://api.github.com/orgs/octo-org/issues",
          "members_url": "https://api.github.com/orgs/octo-org/members{/member}",
          "public_members_url": "https://api.github.com/orgs/octo-org/public_members{/member}",
          "avatar_url": "https://avatars.githubusercontent.com/u/6811672?v=4",
          "description": "Working better together!"
        },
        "sender": {
          "login": "Codertocat",
          "id": 21031067,
          "node_id": "MDQ6VXNlcjIxMDMxMDY3",
          "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
          "gravatar_id": "",
          "url": "https://api.github.com/users/Codertocat",
          "html_url": "https://github.com/Codertocat",
          "followers_url": "https://api.github.com/users/Codertocat/followers",
          "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
          "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
          "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
          "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
          "organizations_url": "https://api.github.com/users/Codertocat/orgs",
          "repos_url": "https://api.github.com/users/Codertocat/repos",
          "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
          "received_events_url": "https://api.github.com/users/Codertocat/received_events",
          "type": "User",
          "site_admin": false
        }
      },
      ...
    ]
  },
```

### Types

In the background for GitHub we use `Octoit` for all our types. You can find a list of all the types and requests in the GitHub provider here: [GitHub Types](https://www.npmjs.com/package/@octokit/webhooks-types)

## Seeing logs and webhook bodies

To view logs or webhook bodies for debugging, you can use the `Dashboard`. If you messed up the callback URL endpoint you can change it here.

You can go to the dashboard here: [Syncd](https://syncd.dev/dashboard).
