- user
- metadata
- repo
- pull request
- branches
- revision and tags
- actions runners
- releases
- branch protection
- rulesets
- rule suites
- have fun
[!TIP]
[!NOTE|label:headers]
-H "Accept: application/vnd.github.v3+json"
-H "Authorization: token <TOKEN>"
-H "Authorization: Bearer <TOKEN>"
-H "Content-Type: application/json"
-H "Time-Zone: Europe/Amsterdam"
-H "X-GitHub-Api-Version: 2022-11-28"
user
get username from token
$ curl -s -H "Authorization: token <TOKEN>" https://api.github.com/user | jq -r .login
# or
$ curl -s -H "Authorization: Bearer <TOKEN>" https://api.github.com/user | jq -r .login
metadata
$ curl -sL https://api.github.com/meta | jq -r '.ssh_keys | .[]'
$ curl -sL https://api.github.com/meta | jq -r '.ssh_keys | .[]' | sed -e 's/^/github.com /' >> ~/.ssh/know_hosts
repo
list all repos and permissions
[!TIP]
- list all repos:
GET /user/repos
- list repos in special
/ : GET /orgs/<ORG>/repos
$ curl -sS -g -H "Authorization: Bearer <TOKEN>" \ -H "Accept: application/vnd.github+json" 'https://api.github.com/user/repos?per_page=100&type=all' | jq -r '.[] | select(.permissions != null) | ( if p.admin then "ADMIN" elif p.maintain then "MAINTAIN" elif p.push then "WRITE" elif p.triage then "TRIAGE" elif p.pull then "READ" else "NONE" end ) + "\t" + .html_url' | sort
- list all repos:
get repo info
[!TIP]
GET /repos/{owner}/{repo}
# i.e.: $ curl -fsSL https://api.github.com/repos/marslo/ibook
get repo contributors
[!TIP]
GET /repos/{owner}/{repo}/contributors
# i.e.: $ curl -fsSL https://api.github.com/repos/marslo/ibook/contributors
pull request
get pull request info
[!TIP]
GET /repos/{owner}/{repo}/pulls/{pull_number}
# i.e.: $ curl -fsSL https://api.github.com/repos/marslo/ibook/pulls/1
get comments of a pull request
[!TIP]
GET /repos/{owner}/{repo}/issues/{issue_number}/comments
# i.e.: $ curl -fsSL https://api.github.com/repos/marslo/ibook/issues/1/comments
branches
get branches
[!TIP]
GET /repos/{owner}/{repo}/branches
# i.e.:
$ curl -fsSL https://api.github.com/repos/marslo/ibook/branches
get details of a branch
[!TIP]
GET /repos/{owner}/{repo}/branches/{branch}
# i.e.:
$ curl -fsSL https://api.github.com/repos/marslo/ibook/branches/main
revision and tags
get commits
[!TIP|label:API]
GET /repos/{owner}/{repo}/commits
$ curl -fsSL https://api.github.com/repos/<OWNER>/<REPO>/commits
# i.e.:
$ curl -fsSL https://api.github.com/repos/marslo/ibook/commits
post commit status
[!TIP|label:API]
POST repos/${OWNER}/${REPO}/statuses/${sha}
$ curl -X POST -H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/${OWNER}/${REPO}/statuses/${SHA} \
-d '{
"state": "success",
"target_url": "https://ci.example.com/build/status/123",
"description": "All tests passed",
"context": "ci/build"
}'
get HEAD of branch
[!TIP|label:API]
GET /repos/{owner}/{repo}/git/refs/heads/{branch}
$ curl -fsSL https://api.github.com/repos/<OWNER>/<REPO>/git/refs/heads/<BRANCH>
# i.e.:
$ curl -fsSL https://api.github.com/repos/marslo/ibook/git/refs/heads/marslo --jq .object.sha
$ gh api "repos/<OWNER>/<REPO>/refs/heads/<BRANCH>"
# i.e.:
$ gh api "repos/marslo/ibook/git/refs/heads/marslo" --jq .object.sha
get revision info
[!TIP|label:API]
GET /repos/{owner}/{repo}/commits/{sha}
$ gh api repos/{owner}/{repo}/commits/{sha}
# i.e.:
$ gh api repos/${OWNER}/${REPO}/commits/{sha} \
--jq '[
"revision: \(.sha)",
"author: \(.commit.author.name) <\(.commit.author.email)> - \(.commit.author.date)",
"committer: \(.commit.committer.name) <\(.commit.committer.email)> - \(.commit.committer.date)",
{message: (.commit.message | split("\n")) }
]'
actions runners
list workflow runs
[!TIP|label:API]
GET /repos/{owner}/{repo}/actions/runs
$ curl -fsSL https://api.github.com/repos/<OWNER>/<REPO>/actions/runs # i.e.: $ curl -fsSL https://api.github.com/repos/marslo/ibook/actions/runs
get workflow run logs
[!TIP|label:API]
GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs
$ curl -fsSL https://api.github.com/repos/<OWNER>/<REPO>/actions/runs/<RUN_ID>/logs # i.e.: $ curl -fsSL https://api.github.com/repos/marslo/ibook/actions/runs/1234567890/logs
trigger workflow run
[!TIP|label:API]
POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches
# i.e.: $ curl -X POST -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: token ghp_v**********************************n" \ https://api.github.com/repos/marslo/ibook/actions/workflows/ci.yml/dispatches \ -d '{"ref":"main"}'
releases
release version
$ curl --silent 'https://api.github.com/repos/<owner>/<repo>/releases/latest' | jq -r .tag_name
# i.e.:
$ curl --silent 'https://api.github.com/repos/sharkdp/bat/releases/latest' | jq -r .tag_name
branch protection
[!NOTE|label:references:]
get branch protection
[!TIP|label:API]
GET /repos/{owner}/{repo}/branches/{branch}/protection
$ gh api "repos/${OWNER}/${REPO}/branches/${BRANCH}/protection"
init branch protection
$ lock=true
$ jq -n --argjson lock "${lock}" '{
required_status_checks: null,
required_pull_request_reviews: null,
restrictions: null,
enforce_admins: $lock,
lock_branch: $lock
}' |
gh api -X PUT -H "Accept: application/vnd.github+json" \
"repos/${OWNER}/${REPO}/branches/${BRANCH}/protection" --input -
update lock_branch status
[!TIP|label:jq tricy]
$ jq -n '.var1=true | .var2=false' { "var1": true, "var2": false }
$ lock=true # or false
# read current settings
$ base=$(gh api -H "Accept: application/vnd.github+json" "repos/${OWNER}/${REPO}/branches/${BRANCH}/protection")
# update lock_branch and enforce_admins only, and keep other settings unchanged ( dyanamically get keys and values )
$ jq -n \
--argjson base "$base" \
--argjson lock "$lock" '
(
$base
| del( .url )
| with_entries(
if ( .value | type=="object" and has("enabled") )
then { key: .key, value: (.value.enabled // false) }
else .
end
)
)
| .lock_branch = $lock
| .enforce_admins = $lock
| .required_status_checks = $base.required_status_checks
| .required_pull_request_reviews = $base.required_pull_request_reviews
| .restrictions = $base.restrictions
' |
gh api -X PUT -H "Accept: application/vnd.github+json" \
"repos/${OWNER}/${REPO}/branches/${BRANCH}/protection" --input -
[!TIP|label:jq tricy] $ jq -n '{var1:true, var2:false}' { "var1": true, "var2": false }
$ lock=true # or false
# read current settings
$ base=$(gh api -H "Accept: application/vnd.github+json" "repos/${OWNER}/${REPO}/branches/${BRANCH}/protection")
# update lock_branch and enforce_admins only
$ jq -n \
--argjson base "${base}" \
--argjson lock "${lock}" \
'{
required_status_checks: $base.required_status_checks,
required_pull_request_reviews: $base.required_pull_request_reviews,
restrictions: $base.restrictions,
enforce_admins: $lock,
lock_branch: $lock,
required_linear_history: ( $base.required_linear_history.enabled // false ),
allow_force_pushes: ( $base.allow_force_pushes.enabled // false ),
allow_deletions: ( $base.allow_deletions.enabled // false ),
block_creations: ( $base.block_creations.enabled // false ),
required_conversation_resolution: ( $base.required_conversation_resolution.enabled // false ),
allow_fork_syncing: ( $base.allow_fork_syncing.enabled // false )
}' |
gh api -X PUT \
-H "Accept: application/vnd.github+json" \
"repos/${OWNER}/${REPO}/branches/${BRANCH}/protection" --input -
rulesets
[!NOTE|label:references:]
list all rulesets
$ gh api "repos/{owner}/{repo}/rulesets"
# or: list id and name
$ gh api "repos/{owner}/{repo}/rulesets" | jq -r '.[] | (.id|tostring) + ": " + .name'
7288536: BranchDeleteRule
7288533: BranchNamingRule
7288566: PRRuleSet
update ruleset
[!NOTE|label:references:]
- this is to add new branch into exclude list of ruleset
- API:
get current rulesets
[!TIP|label:API]
GET /repos/{owner}/{repo}/rulesets/{ruleset_id}
$ gh api \ -H 'Accept: application/vnd.github+json' \ -H 'X-GitHub-Api-Version: 2022-11-28' \ "/repos/${OWNER}/${REPO}/rulesets/${RULESET_ID}" > ruleset.org.json
create new ruleset json
$ branch='refs/heads/devel' $ jq --arg ref "${BRANCH}" '{ name, target, enforcement, bypass_actors, rules, conditions: { ref_name: { include: ( .conditions.ref_name.include // ["~ALL"] ), exclude: ( (.conditions.ref_name.exclude // []) + [$ref] | unique ) } } }' "ruleset" > "ruleset.new.json"
update ruleset
[!TIP|label:API]
PUT /repos/{owner}/{repo}/rulesets/{ruleset_id}
$ gh api -X PUT \ -H 'Accept: application/vnd.github+json' \ -H 'X-GitHub-Api-Version: 2022-11-28' \ "/repos/${OWNER}/${REPO}/rulesets/${RULSET_ID}" \ --input "ruleset.new.json"
rulsets update history
[!NOTE|label:references:]
rule suites
[!NOTE|label:references:]
list failure rule suites
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/${OWNER}/${REPO}/rulesets/rule-suites?ref=refs/heads/${BRANCH}&time_period=week"
# or
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/${OWNER}/${REPO}/rulesets/rule-suites?ref=refs/heads/${BRANCH}&time_period=week" \
--jq '.[] | {id, ref, pushed_at, actor_name, result}'
{
"actor_name": "username",
"id": 1445681219,
"pushed_at": "2025-09-17T16:23:14-07:00",
"ref": "refs/heads/devel",
"result": "pass"
}
{
"actor_name": "username",
"id": 1445649205,
"pushed_at": "2025-09-17T16:10:30-07:00",
"ref": "refs/heads/devel",
"result": "fail"
}
{
"actor_name": "username",
"id": 1445570037,
"pushed_at": "2025-09-17T15:44:01-07:00",
"ref": "refs/heads/devel",
"result": "fail"
}
check failure evaluations
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' "/repos/${OWNER}/${REPO}/rulesets/rule-suites/${RULE_SUITE_ID}"
# or list only failure evaluations
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/${OWNER}/${REPO}/rulesets/rule-suites/${RULE_SUITE_ID}" \
--jq '.rule_evaluations[] | select(.result=="fail")'
# or
$ gh api -H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/${OWNER}/${REPO}/rulesets/rule-suites/${RULE_SUITE_ID}" \
--jq '{ref, result, failed_rules: (.rule_evaluations | map(select(.result=="fail")))}'
{
"details": "Cannot create ref due to creations being restricted.",
"enforcement": "active",
"result": "fail",
"rule_source": {
"id": 7288533,
"name": "BranchNamingRule",
"type": "ruleset"
},
"rule_type": "creation"
}
{
"details": "2 of 2 required status checks are expected.",
"enforcement": "active",
"result": "fail",
"rule_source": {
"id": 7288566,
"name": "PRRuleSet",
"type": "ruleset"
},
"rule_type": "required_status_checks"
}
have fun
emoji
$ curl -fsSL -XGET https://api.github.com/emojis
zen
$ curl -fsSL -XGET https://api.github.com/zen
octocat
$ curl -fsSL -XGET https://api.github.com/octocat
rate limit
$ curl -fsSL -XGET https://api.github.com/rate_limit