Files
2025-11-29 18:18:18 +08:00

17 KiB

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
  2. Pull Requests API
  3. Issues API
  4. Repositories API
  5. Actions/Workflows API
  6. Search API
  7. GraphQL API
  8. Rate Limiting
  9. Webhooks

Authentication

All API calls via gh api automatically use the authenticated token from gh auth login.

# 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

# 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}

# 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

# 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}

# 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

# 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

# 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

# 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

# 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

# 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

# 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

# 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}

# 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

# 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}

# 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

# 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}

# 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

# Get protection rules
gh api repos/{owner}/{repo}/branches/main/protection

List Commits

Endpoint: GET /repos/{owner}/{repo}/commits

# 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}

# 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

# 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

# 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

# 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

# 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

# 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}

# 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

# 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}

# 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

# 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

# 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

# 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

# Download logs (returns zip archive)
gh api repos/{owner}/{repo}/actions/runs/123456/logs > logs.zip

Search API

Search Repositories

Endpoint: GET /search/repositories

# 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

# 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

# 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

# Execute GraphQL query
gh api graphql -f query='
  query {
    viewer {
      login
      name
    }
  }
'

Query Repository Information

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

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

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

# 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

# List repository webhooks
gh api repos/{owner}/{repo}/hooks

Create Webhook

Endpoint: POST /repos/{owner}/{repo}/hooks

# 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

# Test webhook
gh api repos/{owner}/{repo}/hooks/12345/tests -X POST

Pagination

For endpoints returning lists, use pagination:

# 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:

{
  "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