GitHub
Access the GitHub REST API with managed OAuth authentication. Manage repositories, issues, pull requests, commits, branches, users, and more.
Quick Start
CLI:
maton github repo list --sort updated
maton api '/github/user/repos?sort=updated&per_page=10'
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/github/user/repos?sort=updated&per_page=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://api.maton.ai/github/{native-api-path}
Maton proxies requests to api.github.com and automatically injects your OAuth token.
Installation
NPM:
npm install -g @maton-ai/cli
Homebrew:
brew install maton-ai/cli/maton
Authentication
CLI:
maton login # Opens browser for API key
maton login --interactive # Skip browser, paste API key directly
maton whoami # Show current auth state
Manual:
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
- Set your API key as
MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Connection Management
Manage your GitHub OAuth connections at https://api.maton.ai.
List Connections
CLI:
maton connection list github --status ACTIVE
maton api -X GET /connections -f app=github -f status=ACTIVE
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=github&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
CLI:
maton connection create github
maton api /connections -f app=github
Python:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'github'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
CLI:
maton connection view {connection_id}
maton api /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
CLI:
maton connection delete {connection_id}
maton api -X DELETE /connections/{connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple GitHub connections, specify which one to use:
CLI:
maton github user --connection {connection_id}
maton api /github/user --connection {connection_id}
Python:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/github/user')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always specify the connection to ensure requests go to the intended account.
Security & Permissions
- Access is scoped to repositories, issues, pull requests, commits, branches, and users within the connected GitHub account.
- All write operations require explicit user approval. Before executing any create, update, or delete call:
- Confirm the exact target (owner/repo, issue number, branch name) with the user.
- Verify the correct connection ID when multiple connections exist.
- State whether the action is reversible or destructive.
- Irreversible / high-risk operations (require extra caution):
- Deleting repositories, branches, or releases
- Force-pushing or rewriting history
- Merging pull requests (cannot be unmerged)
- Removing collaborators or transferring ownership
- Scope boundaries:
- Only operate on repositories the user explicitly names. Never enumerate or modify repositories outside the current task context.
- Organization-level actions (creating repos, managing members) require the user to confirm the target organization.
- Do not request or use OAuth scopes beyond what the current task requires.
API Reference
Users
Get Authenticated User
GET /github/user
Example:
maton github whoami
Get User by Username
GET /github/users/{username}
List Users
GET /github/users?since={user_id}&per_page=30
Repositories
List User Repositories
GET /github/user/repos?per_page=30&sort=updated
Query parameters: type (all, owner, public, private, member), sort (created, updated, pushed, full_name), direction (asc, desc), per_page, page
Example:
maton github repo list --sort updated
List Organization Repositories
GET /github/orgs/{org}/repos?per_page=30
Example:
maton github repo list {org}
Get Repository
GET /github/repos/{owner}/{repo}
Example:
maton github repo view --repo {owner}/{repo}
Create Repository (User)
POST /github/user/repos
Content-Type: application/json
{
"name": "my-new-repo",
"description": "A new repository",
"private": true,
"auto_init": true
}
Example:
maton github repo create my-new-repo --description "A new repository" --visibility private
Create Repository (Organization)
POST /github/orgs/{org}/repos
Content-Type: application/json
{
"name": "my-new-repo",
"description": "A new repository",
"private": true
}
Example:
maton github repo create {org}/my-new-repo --visibility private
Update Repository
PATCH /github/repos/{owner}/{repo}
Content-Type: application/json
{
"description": "Updated description",
"has_issues": true,
"has_wiki": false
}
Example:
maton github repo edit --repo {owner}/{repo} --description "Updated description" --enable-issues --enable-wiki=false
Repository Contents
List Contents
GET /github/repos/{owner}/{repo}/contents/{path}
Get File Contents
GET /github/repos/{owner}/{repo}/contents/{path}?ref={branch}
Create or Update File
PUT /github/repos/{owner}/{repo}/contents/{path}
Content-Type: application/json
{
"message": "Create new file",
"content": "SGVsbG8gV29ybGQh",
"branch": "main"
}
Note: content must be Base64 encoded.
Delete File
DELETE /github/repos/{owner}/{repo}/contents/{path}
Content-Type: application/json
{
"message": "Delete file",
"sha": "{file_sha}",
"branch": "main"
}
Branches
List Branches
GET /github/repos/{owner}/{repo}/branches?per_page=30
Get Branch
GET /github/repos/{owner}/{repo}/branches/{branch}
Rename Branch
POST /github/repos/{owner}/{repo}/branches/{branch}/rename
Content-Type: application/json
{
"new_name": "new-branch-name"
}
Merge Branches
POST /github/repos/{owner}/{repo}/merges
Content-Type: application/json
{
"base": "main",
"head": "feature-branch",
"commit_message": "Merge feature branch"
}
Commits
List Commits
GET /github/repos/{owner}/{repo}/commits?per_page=30
Query parameters: sha (branch name or commit SHA), path (file path), author, committer, since, until, per_page, page
Get Commit
GET /github/repos/{owner}/{repo}/commits/{ref}
Compare Two Commits
GET /github/repos/{owner}/{repo}/compare/{base}...{head}
Issues
List Repository Issues
GET /github/repos/{owner}/{repo}/issues?state=open&per_page=30
Query parameters: state (open, closed, all), labels, assignee, creator, mentioned, sort, direction, since, per_page, page
Example:
maton github issue list --repo {owner}/{repo} --state open
Get Issue
GET /github/repos/{owner}/{repo}/issues/{issue_number}
Example:
maton github issue view {issue_number} --repo {owner}/{repo}
Create Issue
POST /github/repos/{owner}/{repo}/issues
Content-Type: application/json
{
"title": "Found a bug",
"body": "Bug description here",
"labels": ["bug"],
"assignees": ["username"]
}
Example:
maton github issue create --repo {owner}/{repo} --title "Found a bug" --body "Bug description here" --label bug --assignee username
Update Issue
PATCH /github/repos/{owner}/{repo}/issues/{issue_number}
Content-Type: application/json
{
"state": "closed",
"state_reason": "completed"
}
Example:
maton github issue close {issue_number} --repo {owner}/{repo} --reason completed
Lock Issue
PUT /github/repos/{owner}/{repo}/issues/{issue_number}/lock
Content-Type: application/json
{
"lock_reason": "resolved"
}
Example:
maton github issue lock {issue_number} --repo {owner}/{repo} --reason resolved
Unlock Issue
DELETE /github/repos/{owner}/{repo}/issues/{issue_number}/lock
Example:
maton github issue unlock {issue_number} --repo {owner}/{repo}
Issue Comments
List Issue Comments
GET /github/repos/{owner}/{repo}/issues/{issue_number}/comments?per_page=30
Example:
maton github issue view {issue_number} --repo {owner}/{repo} --comments
Create Issue Comment
POST /github/repos/{owner}/{repo}/issues/{issue_number}/comments
Content-Type: application/json
{
"body": "This is a comment"
}
Example:
maton github issue comment {issue_number} --repo {owner}/{repo} --body "This is a comment"
Update Issue Comment
PATCH /github/repos/{owner}/{repo}/issues/comments/{comment_id}
Content-Type: application/json
{
"body": "Updated comment"
}
Delete Issue Comment
DELETE /github/repos/{owner}/{repo}/issues/comments/{comment_id}
Labels
List Labels
GET /github/repos/{owner}/{repo}/labels?per_page=30
Example:
maton github label list --repo {owner}/{repo}
Create Label
POST /github/repos/{owner}/{repo}/labels
Content-Type: application/json
{
"name": "priority:high",
"color": "ff0000",
"description": "High priority issues"
}
Example:
maton github label create "priority:high" --repo {owner}/{repo} --color ff0000 --description "High priority issues"
Milestones
List Milestones
GET /github/repos/{owner}/{repo}/milestones?state=open&per_page=30
Create Milestone
POST /github/repos/{owner}/{repo}/milestones
Content-Type: application/json
{
"title": "v1.0",
"state": "open",
"description": "First release",
"due_on": "2026-03-01T00:00:00Z"
}
Pull Requests
List Pull Requests
GET /github/repos/{owner}/{repo}/pulls?state=open&per_page=30
Query parameters: state (open, closed, all), head, base, sort, direction, per_page, page
Example:
maton github pr list --repo {owner}/{repo} --state open
Get Pull Request
GET /github/repos/{owner}/{repo}/pulls/{pull_number}
Example:
maton github pr view {pull_number} --repo {owner}/{repo}
Create Pull Request
POST /github/repos/{owner}/{repo}/pulls
Content-Type: application/json
{
"title": "New feature",
"body": "Description of changes",
"head": "feature-branch",
"base": "main",
"draft": false
}
Example:
maton github pr create --repo {owner}/{repo} --base main --head feature-branch --title "New feature" --body "Description of changes"
Update Pull Request
PATCH /github/repos/{owner}/{repo}/pulls/{pull_number}
Content-Type: application/json
{
"title": "Updated title",
"state": "closed"
}
Example:
maton github pr edit {pull_number} --repo {owner}/{repo} --title "Updated title"
List Pull Request Commits
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/commits?per_page=30
List Pull Request Files
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/files?per_page=30
Example:
maton github pr diff {pull_number} --repo {owner}/{repo}
Check If Merged
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/merge
Merge Pull Request
PUT /github/repos/{owner}/{repo}/pulls/{pull_number}/merge
Content-Type: application/json
{
"commit_title": "Merge pull request",
"merge_method": "squash"
}
Merge methods: merge, squash, rebase
Example:
maton github pr merge {pull_number} --repo {owner}/{repo} --squash --delete-branch
Pull Request Reviews
List Reviews
GET /github/repos/{owner}/{repo}/pulls/{pull_number}/reviews?per_page=30
Create Review
POST /github/repos/{owner}/{repo}/pulls/{pull_number}/reviews
Content-Type: application/json
{
"body": "Looks good!",
"event": "APPROVE"
}
Events: APPROVE, REQUEST_CHANGES, COMMENT
Example:
maton github pr review {pull_number} --repo {owner}/{repo} --approve --body "Looks good!"
Note: GitHub does not allow approving your own pull requests; --approve returns 422 Can not approve your own pull request in that case. Use --comment or --request-changes instead.
Search
Search Repositories
GET /github/search/repositories?q={query}&per_page=30
Example queries:
tetris+language:python- Repositories with "tetris" in Pythonreact+stars:>10000- Repositories with "react" and 10k+ stars
Example:
maton github repo search tetris --language python
Search Issues
GET /github/search/issues?q={query}&per_page=30
Example queries:
bug+is:open+is:issue- Open issues containing "bug"author:username+is:pr- Pull requests by author
Example:
maton github issue search "bug" --state open
Search Code
GET /github/search/code?q={query}&per_page=30
Example queries:
addClass+repo:facebook/react- Search for "addClass" in a specific repofunction+extension:js- JavaScript functions
Note: Code search may timeout on broad queries.
Search Users
GET /github/search/users?q={query}&per_page=30
Organizations
List User Organizations
GET /github/user/orgs?per_page=30
Note: Requires read:org scope.
Get Organization
GET /github/orgs/{org}
List Organization Members
GET /github/orgs/{org}/members?per_page=30
Rate Limit
Get Rate Limit
GET /github/rate_limit
Pagination
GitHub uses page-based pagination. The CLI automatically paginates with '--paginate'.
Example:
maton github repo list --paginate
Code Examples
CLI
# Get repos as JSON (full objects)
maton github repo list --json
# Project specific fields with jq
maton github repo list --json --jq '.[] | {name, full_name, private}'
# Filter — e.g., only public repos
maton github repo list --json --jq '.[] | select(.private == false) | .name'
# Extract a single field
maton github issue list --repo owner/repo --json --jq '.[].title'
JavaScript
const response = await fetch(
'https://api.maton.ai/github/repos/owner/repo/issues?state=open&per_page=10',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const issues = await response.json();
Python
import os
import requests
response = requests.get(
'https://api.maton.ai/github/repos/owner/repo/issues',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
params={'state': 'open', 'per_page': 10}
)
issues = response.json()
Notes
- Repository names are case-insensitive but the API preserves case
- Issue numbers and PR numbers share the same sequence per repository
- Content must be Base64 encoded when creating/updating files
- Rate limits: 5000 requests/hour for authenticated users, 30 searches/minute
- Search queries may timeout on very broad patterns
- Some endpoints require specific OAuth scopes (e.g.,
read:orgfor organization operations). If you receive a scope error, contact Maton support at support@maton.ai with the specific operations/APIs you need and your use-case - IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay not expand correctly in some shell environments
Error Handling
| Status | Meaning | |--------|---------| | 400 | Missing GitHub connection | | 401 | Invalid or missing Maton API key | | 403 | Forbidden - insufficient permissions or scope | | 404 | Resource not found | | 408 | Request timeout (common for complex searches) | | 422 | Validation failed | | 429 | Rate limited | | 4xx/5xx | Passthrough error from GitHub API |
Troubleshooting: API Key Issues
CLI:
- Check your auth state:
maton whoami
- Verify the API key is valid by listing connections:
maton connection list
Manual:
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
github. For example:
- Correct:
https://api.maton.ai/github/user - Incorrect:
https://api.maton.ai/api.github.com/user
Scan to contact