# GitHub API Reference This reference provides comprehensive documentation for GitHub REST and GraphQL APIs, focusing on common operations accessible via `gh api`. ## Table of Contents 1. [Authentication](#authentication) 2. [Pull Requests API](#pull-requests-api) 3. [Issues API](#issues-api) 4. [Repositories API](#repositories-api) 5. [Actions/Workflows API](#actionsworkflows-api) 6. [Search API](#search-api) 7. [GraphQL API](#graphql-api) 8. [Rate Limiting](#rate-limiting) 9. [Webhooks](#webhooks) ## Authentication All API calls via `gh api` automatically use the authenticated token from `gh auth login`. ```bash # Check authentication status gh auth status # View current token (use cautiously) gh auth status --show-token ``` **API Headers:** - `Accept: application/vnd.github+json` (automatically set) - `X-GitHub-Api-Version: 2022-11-28` (recommended) ## Pull Requests API ### List Pull Requests **Endpoint:** `GET /repos/{owner}/{repo}/pulls` ```bash # List all open PRs gh api repos/{owner}/{repo}/pulls # List PRs with filters gh api repos/{owner}/{repo}/pulls -f state=closed -f base=main # List PRs sorted by updated gh api repos/{owner}/{repo}/pulls -f sort=updated -f direction=desc ``` **Query Parameters:** - `state`: `open`, `closed`, `all` (default: `open`) - `head`: Filter by branch name (format: `user:ref-name`) - `base`: Filter by base branch - `sort`: `created`, `updated`, `popularity`, `long-running` - `direction`: `asc`, `desc` - `per_page`: Results per page (max: 100) - `page`: Page number ### Get Pull Request **Endpoint:** `GET /repos/{owner}/{repo}/pulls/{pull_number}` ```bash # Get PR details gh api repos/{owner}/{repo}/pulls/123 # Get PR with specific fields gh api repos/{owner}/{repo}/pulls/123 --jq '.title, .state, .mergeable' ``` **Response includes:** - Basic PR info (title, body, state) - Author and assignees - Labels, milestone - Merge status and conflicts - Review status - Head and base branch info ### Create Pull Request **Endpoint:** `POST /repos/{owner}/{repo}/pulls` ```bash # Create PR via API gh api repos/{owner}/{repo}/pulls \ -f title="NOJIRA: New feature" \ -f body="Description of changes" \ -f head="feature-branch" \ -f base="main" # Create draft PR gh api repos/{owner}/{repo}/pulls \ -f title="WIP: Feature" \ -f body="Work in progress" \ -f head="feature-branch" \ -f base="main" \ -F draft=true ``` **Required fields:** - `title`: PR title - `head`: Branch containing changes - `base`: Branch to merge into **Optional fields:** - `body`: PR description - `draft`: Boolean for draft PR - `maintainer_can_modify`: Allow maintainer edits ### Update Pull Request **Endpoint:** `PATCH /repos/{owner}/{repo}/pulls/{pull_number}` ```bash # Update PR title and body gh api repos/{owner}/{repo}/pulls/123 \ -X PATCH \ -f title="Updated title" \ -f body="Updated description" # Convert to draft gh api repos/{owner}/{repo}/pulls/123 \ -X PATCH \ -F draft=true # Change base branch gh api repos/{owner}/{repo}/pulls/123 \ -X PATCH \ -f base="develop" ``` ### Merge Pull Request **Endpoint:** `PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge` ```bash # Merge with commit message gh api repos/{owner}/{repo}/pulls/123/merge \ -X PUT \ -f commit_title="Merge PR #123" \ -f commit_message="Additional merge message" \ -f merge_method="squash" # Merge methods: merge, squash, rebase ``` ### List PR Comments **Endpoint:** `GET /repos/{owner}/{repo}/pulls/{pull_number}/comments` ```bash # Get all review comments gh api repos/{owner}/{repo}/pulls/123/comments # Get issue comments (conversation tab) gh api repos/{owner}/{repo}/issues/123/comments ``` ### Create PR Review **Endpoint:** `POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews` ```bash # Approve PR gh api repos/{owner}/{repo}/pulls/123/reviews \ -f event="APPROVE" \ -f body="Looks good!" # Request changes gh api repos/{owner}/{repo}/pulls/123/reviews \ -f event="REQUEST_CHANGES" \ -f body="Please address these issues" # Comment without approval/rejection gh api repos/{owner}/{repo}/pulls/123/reviews \ -f event="COMMENT" \ -f body="Some feedback" ``` **Review events:** - `APPROVE`: Approve the PR - `REQUEST_CHANGES`: Request changes - `COMMENT`: General comment ### List PR Reviews **Endpoint:** `GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews` ```bash # Get all reviews gh api repos/{owner}/{repo}/pulls/123/reviews # Parse review states gh api repos/{owner}/{repo}/pulls/123/reviews --jq '[.[] | {user: .user.login, state: .state}]' ``` ### Request Reviewers **Endpoint:** `POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers` ```bash # Request user reviewers gh api repos/{owner}/{repo}/pulls/123/requested_reviewers \ -f reviewers[]="user1" \ -f reviewers[]="user2" # Request team reviewers gh api repos/{owner}/{repo}/pulls/123/requested_reviewers \ -f team_reviewers[]="team-slug" ``` ## Issues API ### List Issues **Endpoint:** `GET /repos/{owner}/{repo}/issues` ```bash # List all issues gh api repos/{owner}/{repo}/issues # Filter by state and labels gh api repos/{owner}/{repo}/issues -f state=open -f labels="bug,priority-high" # Filter by assignee gh api repos/{owner}/{repo}/issues -f assignee="username" # Filter by milestone gh api repos/{owner}/{repo}/issues -f milestone="v1.0" ``` **Query Parameters:** - `state`: `open`, `closed`, `all` - `labels`: Comma-separated label names - `assignee`: Username or `none` or `*` - `creator`: Username - `mentioned`: Username - `milestone`: Milestone number or `none` or `*` - `sort`: `created`, `updated`, `comments` - `direction`: `asc`, `desc` ### Create Issue **Endpoint:** `POST /repos/{owner}/{repo}/issues` ```bash # Create basic issue gh api repos/{owner}/{repo}/issues \ -f title="Bug: Something broke" \ -f body="Detailed description" # Create issue with labels and assignees gh api repos/{owner}/{repo}/issues \ -f title="Enhancement request" \ -f body="Description" \ -f labels[]="enhancement" \ -f labels[]="good-first-issue" \ -f assignees[]="username1" ``` ### Update Issue **Endpoint:** `PATCH /repos/{owner}/{repo}/issues/{issue_number}` ```bash # Close issue gh api repos/{owner}/{repo}/issues/456 \ -X PATCH \ -f state="closed" # Update labels gh api repos/{owner}/{repo}/issues/456 \ -X PATCH \ -f labels[]="bug" \ -f labels[]="fixed" # Assign issue gh api repos/{owner}/{repo}/issues/456 \ -X PATCH \ -f assignees[]="username" ``` ### Add Comment to Issue **Endpoint:** `POST /repos/{owner}/{repo}/issues/{issue_number}/comments` ```bash # Add comment gh api repos/{owner}/{repo}/issues/456/comments \ -f body="This is a comment" ``` ## Repositories API ### Get Repository **Endpoint:** `GET /repos/{owner}/{repo}` ```bash # Get repository details gh api repos/{owner}/{repo} # Get specific fields gh api repos/{owner}/{repo} --jq '{name: .name, stars: .stargazers_count, forks: .forks_count}' ``` ### List Branches **Endpoint:** `GET /repos/{owner}/{repo}/branches` ```bash # List all branches gh api repos/{owner}/{repo}/branches # Get branch names only gh api repos/{owner}/{repo}/branches --jq '.[].name' ``` ### Get Branch **Endpoint:** `GET /repos/{owner}/{repo}/branches/{branch}` ```bash # Get branch details gh api repos/{owner}/{repo}/branches/main # Check if branch is protected gh api repos/{owner}/{repo}/branches/main --jq '.protected' ``` ### Get Branch Protection **Endpoint:** `GET /repos/{owner}/{repo}/branches/{branch}/protection` ```bash # Get protection rules gh api repos/{owner}/{repo}/branches/main/protection ``` ### List Commits **Endpoint:** `GET /repos/{owner}/{repo}/commits` ```bash # List recent commits gh api repos/{owner}/{repo}/commits # Filter by branch gh api repos/{owner}/{repo}/commits -f sha="feature-branch" # Filter by author gh api repos/{owner}/{repo}/commits -f author="username" # Filter by date range gh api repos/{owner}/{repo}/commits -f since="2024-01-01T00:00:00Z" ``` ### Get Commit **Endpoint:** `GET /repos/{owner}/{repo}/commits/{sha}` ```bash # Get commit details gh api repos/{owner}/{repo}/commits/abc123 # Get files changed in commit gh api repos/{owner}/{repo}/commits/abc123 --jq '.files[].filename' ``` ### Get Commit Status **Endpoint:** `GET /repos/{owner}/{repo}/commits/{sha}/status` ```bash # Get combined status for commit gh api repos/{owner}/{repo}/commits/abc123/status # Check if all checks passed gh api repos/{owner}/{repo}/commits/abc123/status --jq '.state' ``` ### List Collaborators **Endpoint:** `GET /repos/{owner}/{repo}/collaborators` ```bash # List all collaborators gh api repos/{owner}/{repo}/collaborators # Get collaborator permissions gh api repos/{owner}/{repo}/collaborators --jq '[.[] | {login: .login, permissions: .permissions}]' ``` ### Create Release **Endpoint:** `POST /repos/{owner}/{repo}/releases` ```bash # Create release gh api repos/{owner}/{repo}/releases \ -f tag_name="v1.0.0" \ -f name="Release v1.0.0" \ -f body="Release notes here" \ -F draft=false \ -F prerelease=false # Create draft release gh api repos/{owner}/{repo}/releases \ -f tag_name="v1.1.0" \ -f name="Release v1.1.0" \ -f body="Release notes" \ -F draft=true ``` ### List Releases **Endpoint:** `GET /repos/{owner}/{repo}/releases` ```bash # List all releases gh api repos/{owner}/{repo}/releases # Get latest release gh api repos/{owner}/{repo}/releases/latest ``` ## Actions/Workflows API ### List Workflows **Endpoint:** `GET /repos/{owner}/{repo}/actions/workflows` ```bash # List all workflows gh api repos/{owner}/{repo}/actions/workflows # Get workflow names gh api repos/{owner}/{repo}/actions/workflows --jq '.workflows[].name' ``` ### Get Workflow **Endpoint:** `GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}` ```bash # Get workflow by ID gh api repos/{owner}/{repo}/actions/workflows/12345 # Get workflow by filename gh api repos/{owner}/{repo}/actions/workflows/ci.yml ``` ### List Workflow Runs **Endpoint:** `GET /repos/{owner}/{repo}/actions/runs` ```bash # List all runs gh api repos/{owner}/{repo}/actions/runs # Filter by workflow gh api repos/{owner}/{repo}/actions/runs -f workflow_id=12345 # Filter by branch gh api repos/{owner}/{repo}/actions/runs -f branch="main" # Filter by status gh api repos/{owner}/{repo}/actions/runs -f status="completed" # Filter by conclusion gh api repos/{owner}/{repo}/actions/runs -f conclusion="success" ``` **Status values:** `queued`, `in_progress`, `completed` **Conclusion values:** `success`, `failure`, `cancelled`, `skipped`, `timed_out`, `action_required` ### Get Workflow Run **Endpoint:** `GET /repos/{owner}/{repo}/actions/runs/{run_id}` ```bash # Get run details gh api repos/{owner}/{repo}/actions/runs/123456 # Check run status gh api repos/{owner}/{repo}/actions/runs/123456 --jq '.status, .conclusion' ``` ### Trigger Workflow **Endpoint:** `POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches` ```bash # Trigger workflow on branch gh api repos/{owner}/{repo}/actions/workflows/ci.yml/dispatches \ -f ref="main" # Trigger with inputs gh api repos/{owner}/{repo}/actions/workflows/deploy.yml/dispatches \ -f ref="main" \ -f inputs[environment]="production" \ -f inputs[version]="v1.0.0" ``` ### Cancel Workflow Run **Endpoint:** `POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel` ```bash # Cancel run gh api repos/{owner}/{repo}/actions/runs/123456/cancel -X POST ``` ### Rerun Workflow **Endpoint:** `POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun` ```bash # Rerun all jobs gh api repos/{owner}/{repo}/actions/runs/123456/rerun -X POST # Rerun failed jobs only gh api repos/{owner}/{repo}/actions/runs/123456/rerun-failed-jobs -X POST ``` ### Download Workflow Logs **Endpoint:** `GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs` ```bash # Download logs (returns zip archive) gh api repos/{owner}/{repo}/actions/runs/123456/logs > logs.zip ``` ## Search API ### Search Repositories **Endpoint:** `GET /search/repositories` ```bash # Search repositories gh api search/repositories -f q="topic:spring-boot language:java" # Search with filters gh api search/repositories -f q="stars:>1000 language:python" ``` ### Search Code **Endpoint:** `GET /search/code` ```bash # Search code gh api search/code -f q="addClass repo:owner/repo" # Search in specific path gh api search/code -f q="function path:src/ repo:owner/repo" ``` ### Search Issues and PRs **Endpoint:** `GET /search/issues` ```bash # Search issues gh api search/issues -f q="is:issue is:open label:bug repo:owner/repo" # Search PRs gh api search/issues -f q="is:pr is:merged author:username" ``` ## GraphQL API ### Basic GraphQL Query ```bash # Execute GraphQL query gh api graphql -f query=' query { viewer { login name } } ' ``` ### Query Repository Information ```bash gh api graphql -f query=' query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { name description stargazerCount forkCount issues(states: OPEN) { totalCount } pullRequests(states: OPEN) { totalCount } } } ' -f owner="owner" -f name="repo" ``` ### Query PR with Reviews ```bash gh api graphql -f query=' query($owner: String!, $name: String!, $number: Int!) { repository(owner: $owner, name: $name) { pullRequest(number: $number) { title state author { login } reviews(first: 10) { nodes { state author { login } submittedAt } } commits(last: 1) { nodes { commit { statusCheckRollup { state } } } } } } } ' -f owner="owner" -f name="repo" -F number=123 ``` ### Query Multiple PRs with Pagination ```bash gh api graphql -f query=' query($owner: String!, $name: String!, $cursor: String) { repository(owner: $owner, name: $name) { pullRequests(first: 10, states: OPEN, after: $cursor) { pageInfo { hasNextPage endCursor } nodes { number title author { login } createdAt } } } } ' -f owner="owner" -f name="repo" ``` ## Rate Limiting ### Check Rate Limit **Endpoint:** `GET /rate_limit` ```bash # Check current rate limit gh api rate_limit # Check core API limit gh api rate_limit --jq '.resources.core' # Check GraphQL limit gh api rate_limit --jq '.resources.graphql' ``` **Rate limits:** - Authenticated: 5,000 requests/hour - GraphQL: 5,000 points/hour - Search: 30 requests/minute ### Rate Limit Headers Every API response includes rate limit headers: - `X-RateLimit-Limit`: Total requests allowed - `X-RateLimit-Remaining`: Requests remaining - `X-RateLimit-Reset`: Unix timestamp when limit resets ## Webhooks ### List Webhooks **Endpoint:** `GET /repos/{owner}/{repo}/hooks` ```bash # List repository webhooks gh api repos/{owner}/{repo}/hooks ``` ### Create Webhook **Endpoint:** `POST /repos/{owner}/{repo}/hooks` ```bash # Create webhook gh api repos/{owner}/{repo}/hooks \ -f name="web" \ -f config[url]="https://example.com/webhook" \ -f config[content_type]="json" \ -f events[]="push" \ -f events[]="pull_request" ``` ### Test Webhook **Endpoint:** `POST /repos/{owner}/{repo}/hooks/{hook_id}/tests` ```bash # Test webhook gh api repos/{owner}/{repo}/hooks/12345/tests -X POST ``` ## Pagination For endpoints returning lists, use pagination: ```bash # First page (default) gh api repos/{owner}/{repo}/issues # Specific page gh api repos/{owner}/{repo}/issues -f page=2 -f per_page=50 # Iterate through all pages for page in {1..10}; do gh api repos/{owner}/{repo}/issues -f page=$page -f per_page=100 done ``` **Link header:** Response includes `Link` header with `next`, `prev`, `first`, `last` URLs. ## Error Handling **Common HTTP status codes:** - `200 OK`: Success - `201 Created`: Resource created - `204 No Content`: Success with no response body - `400 Bad Request`: Invalid request - `401 Unauthorized`: Authentication required - `403 Forbidden`: Insufficient permissions or rate limited - `404 Not Found`: Resource doesn't exist - `422 Unprocessable Entity`: Validation failed **Error response format:** ```json { "message": "Validation Failed", "errors": [ { "resource": "PullRequest", "code": "custom", "message": "Error details" } ] } ``` ## Best Practices 1. **Use conditional requests:** Include `If-None-Match` header with ETag to save rate limit quota 2. **Paginate efficiently:** Use `per_page=100` (maximum) to minimize requests 3. **Use GraphQL for complex queries:** Fetch multiple related resources in single request 4. **Check rate limits proactively:** Monitor `X-RateLimit-Remaining` header 5. **Handle errors gracefully:** Implement retry logic with exponential backoff for 5xx errors 6. **Cache responses:** Cache GET responses when data doesn't change frequently 7. **Use webhooks:** Subscribe to events instead of polling ## Additional Resources - GitHub REST API documentation: https://docs.github.com/en/rest - GitHub GraphQL API documentation: https://docs.github.com/en/graphql - gh CLI manual: https://cli.github.com/manual/