GitHub
Access the GitHub REST API with managed OAuth authentication. Manage repositories, issues, pull requests, commits, branches, users, and more.
Quick Start
bash1# Get authenticated user 2python <<'EOF' 3import urllib.request, os, json 4req = urllib.request.Request('https://gateway.maton.ai/github/user') 5req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') 6print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) 7EOF
Base URL
https://gateway.maton.ai/github/{native-api-path}
Replace {native-api-path} with the actual GitHub API endpoint path. The gateway proxies requests to api.github.com and automatically injects your OAuth token.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
bash1export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your GitHub OAuth connections at https://ctrl.maton.ai.
List Connections
bash1python <<'EOF' 2import urllib.request, os, json 3req = urllib.request.Request('https://ctrl.maton.ai/connections?app=github&status=ACTIVE') 4req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') 5print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) 6EOF
Create Connection
bash1python <<'EOF' 2import urllib.request, os, json 3data = json.dumps({'app': 'github'}).encode() 4req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') 5req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') 6req.add_header('Content-Type', 'application/json') 7print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) 8EOF
Get Connection
bash1python <<'EOF' 2import urllib.request, os, json 3req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') 4req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') 5print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) 6EOF
Response:
json1{ 2 "connection": { 3 "connection_id": "83e7c665-60f6-4a64-816c-5e287ea8982f", 4 "status": "ACTIVE", 5 "creation_time": "2026-02-06T03:00:43.860014Z", 6 "last_updated_time": "2026-02-06T03:01:06.027323Z", 7 "url": "https://connect.maton.ai/?session_token=...", 8 "app": "github", 9 "metadata": {} 10 } 11}
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
bash1python <<'EOF' 2import urllib.request, os, json 3req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') 4req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') 5print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) 6EOF
Specifying Connection
If you have multiple GitHub connections, specify which one to use with the Maton-Connection header:
bash1python <<'EOF' 2import urllib.request, os, json 3req = urllib.request.Request('https://gateway.maton.ai/github/user') 4req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') 5req.add_header('Maton-Connection', '83e7c665-60f6-4a64-816c-5e287ea8982f') 6print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) 7EOF
If omitted, the gateway uses the default (oldest) active connection.
API Reference
Users
Get Authenticated User
bash1GET /github/user
Get User by Username
bash1GET /github/users/{username}
List Users
bash1GET /github/users?since={user_id}&per_page=30
Repositories
List User Repositories
bash1GET /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
List Organization Repositories
bash1GET /github/orgs/{org}/repos?per_page=30
Get Repository
bash1GET /github/repos/{owner}/{repo}
Create Repository (User)
bash1POST /github/user/repos 2Content-Type: application/json 3 4{ 5 "name": "my-new-repo", 6 "description": "A new repository", 7 "private": true, 8 "auto_init": true 9}
Create Repository (Organization)
bash1POST /github/orgs/{org}/repos 2Content-Type: application/json 3 4{ 5 "name": "my-new-repo", 6 "description": "A new repository", 7 "private": true 8}
Update Repository
bash1PATCH /github/repos/{owner}/{repo} 2Content-Type: application/json 3 4{ 5 "description": "Updated description", 6 "has_issues": true, 7 "has_wiki": false 8}
Delete Repository
bash1DELETE /github/repos/{owner}/{repo}
Repository Contents
List Contents
bash1GET /github/repos/{owner}/{repo}/contents/{path}
Get File Contents
bash1GET /github/repos/{owner}/{repo}/contents/{path}?ref={branch}
Create or Update File
bash1PUT /github/repos/{owner}/{repo}/contents/{path} 2Content-Type: application/json 3 4{ 5 "message": "Create new file", 6 "content": "SGVsbG8gV29ybGQh", 7 "branch": "main" 8}
Note: content must be Base64 encoded.
Delete File
bash1DELETE /github/repos/{owner}/{repo}/contents/{path} 2Content-Type: application/json 3 4{ 5 "message": "Delete file", 6 "sha": "{file_sha}", 7 "branch": "main" 8}
Branches
List Branches
bash1GET /github/repos/{owner}/{repo}/branches?per_page=30
Get Branch
bash1GET /github/repos/{owner}/{repo}/branches/{branch}
Rename Branch
bash1POST /github/repos/{owner}/{repo}/branches/{branch}/rename 2Content-Type: application/json 3 4{ 5 "new_name": "new-branch-name" 6}
Merge Branches
bash1POST /github/repos/{owner}/{repo}/merges 2Content-Type: application/json 3 4{ 5 "base": "main", 6 "head": "feature-branch", 7 "commit_message": "Merge feature branch" 8}
Commits
List Commits
bash1GET /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
bash1GET /github/repos/{owner}/{repo}/commits/{ref}
Compare Two Commits
bash1GET /github/repos/{owner}/{repo}/compare/{base}...{head}
Issues
List Repository Issues
bash1GET /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
Get Issue
bash1GET /github/repos/{owner}/{repo}/issues/{issue_number}
Create Issue
bash1POST /github/repos/{owner}/{repo}/issues 2Content-Type: application/json 3 4{ 5 "title": "Found a bug", 6 "body": "Bug description here", 7 "labels": ["bug"], 8 "assignees": ["username"] 9}
Update Issue
bash1PATCH /github/repos/{owner}/{repo}/issues/{issue_number} 2Content-Type: application/json 3 4{ 5 "state": "closed", 6 "state_reason": "completed" 7}
Lock Issue
bash1PUT /github/repos/{owner}/{repo}/issues/{issue_number}/lock 2Content-Type: application/json 3 4{ 5 "lock_reason": "resolved" 6}
Unlock Issue
bash1DELETE /github/repos/{owner}/{repo}/issues/{issue_number}/lock
Issue Comments
List Issue Comments
bash1GET /github/repos/{owner}/{repo}/issues/{issue_number}/comments?per_page=30
Create Issue Comment
bash1POST /github/repos/{owner}/{repo}/issues/{issue_number}/comments 2Content-Type: application/json 3 4{ 5 "body": "This is a comment" 6}
Update Issue Comment
bash1PATCH /github/repos/{owner}/{repo}/issues/comments/{comment_id} 2Content-Type: application/json 3 4{ 5 "body": "Updated comment" 6}
Delete Issue Comment
bash1DELETE /github/repos/{owner}/{repo}/issues/comments/{comment_id}
Labels
List Labels
bash1GET /github/repos/{owner}/{repo}/labels?per_page=30
Create Label
bash1POST /github/repos/{owner}/{repo}/labels 2Content-Type: application/json 3 4{ 5 "name": "priority:high", 6 "color": "ff0000", 7 "description": "High priority issues" 8}
Milestones
List Milestones
bash1GET /github/repos/{owner}/{repo}/milestones?state=open&per_page=30
Create Milestone
bash1POST /github/repos/{owner}/{repo}/milestones 2Content-Type: application/json 3 4{ 5 "title": "v1.0", 6 "state": "open", 7 "description": "First release", 8 "due_on": "2026-03-01T00:00:00Z" 9}
Pull Requests
List Pull Requests
bash1GET /github/repos/{owner}/{repo}/pulls?state=open&per_page=30
Query parameters: state (open, closed, all), head, base, sort, direction, per_page, page
Get Pull Request
bash1GET /github/repos/{owner}/{repo}/pulls/{pull_number}
Create Pull Request
bash1POST /github/repos/{owner}/{repo}/pulls 2Content-Type: application/json 3 4{ 5 "title": "New feature", 6 "body": "Description of changes", 7 "head": "feature-branch", 8 "base": "main", 9 "draft": false 10}
Update Pull Request
bash1PATCH /github/repos/{owner}/{repo}/pulls/{pull_number} 2Content-Type: application/json 3 4{ 5 "title": "Updated title", 6 "state": "closed" 7}
List Pull Request Commits
bash1GET /github/repos/{owner}/{repo}/pulls/{pull_number}/commits?per_page=30
List Pull Request Files
bash1GET /github/repos/{owner}/{repo}/pulls/{pull_number}/files?per_page=30
Check If Merged
bash1GET /github/repos/{owner}/{repo}/pulls/{pull_number}/merge
Merge Pull Request
bash1PUT /github/repos/{owner}/{repo}/pulls/{pull_number}/merge 2Content-Type: application/json 3 4{ 5 "commit_title": "Merge pull request", 6 "merge_method": "squash" 7}
Merge methods: merge, squash, rebase
Pull Request Reviews
List Reviews
bash1GET /github/repos/{owner}/{repo}/pulls/{pull_number}/reviews?per_page=30
Create Review
bash1POST /github/repos/{owner}/{repo}/pulls/{pull_number}/reviews 2Content-Type: application/json 3 4{ 5 "body": "Looks good!", 6 "event": "APPROVE" 7}
Events: APPROVE, REQUEST_CHANGES, COMMENT
Search
Search Repositories
bash1GET /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
Search Issues
bash1GET /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
Search Code
bash1GET /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
bash1GET /github/search/users?q={query}&per_page=30
Organizations
List User Organizations
bash1GET /github/user/orgs?per_page=30
Note: Requires read:org scope.
Get Organization
bash1GET /github/orgs/{org}
List Organization Members
bash1GET /github/orgs/{org}/members?per_page=30
Rate Limit
Get Rate Limit
bash1GET /github/rate_limit
Response:
json1{ 2 "rate": { 3 "limit": 5000, 4 "remaining": 4979, 5 "reset": 1707200000 6 }, 7 "resources": { 8 "core": { "limit": 5000, "remaining": 4979 }, 9 "search": { "limit": 30, "remaining": 28 } 10 } 11}
Pagination
GitHub uses page-based and link-based pagination:
bash1GET /github/repos/{owner}/{repo}/issues?per_page=30&page=2
Response headers include pagination links:
Link: <url>; rel="next", <url>; rel="last"
Common pagination parameters:
per_page: Results per page (max 100, default 30)page: Page number (default 1)
Some endpoints use cursor-based pagination with since parameter (e.g., listing users).
Code Examples
JavaScript
javascript1const response = await fetch( 2 'https://gateway.maton.ai/github/repos/owner/repo/issues?state=open&per_page=10', 3 { 4 headers: { 5 'Authorization': `Bearer ${process.env.MATON_API_KEY}` 6 } 7 } 8); 9const issues = await response.json();
Python
python1import os 2import requests 3 4response = requests.get( 5 'https://gateway.maton.ai/github/repos/owner/repo/issues', 6 headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}, 7 params={'state': 'open', 'per_page': 10} 8) 9issues = 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
- Check that the
MATON_API_KEYenvironment variable is set:
bash1echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
bash1python <<'EOF' 2import urllib.request, os, json 3req = urllib.request.Request('https://ctrl.maton.ai/connections') 4req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') 5print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) 6EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
github. For example:
- Correct:
https://gateway.maton.ai/github/user - Incorrect:
https://gateway.maton.ai/api.github.com/user