REST API
All REST API endpoints use the base path /api/repos/:owner/:repo. Request and response bodies are JSON.
List Repositories
Section titled “List Repositories”GET /api/reposGET /api/repos/:ownerReturns all known repositories, optionally filtered by owner:
{ "repos": [ { "owner": "alice", "name": "project-a" }, { "owner": "alice", "name": "project-b" } ]}Repos are discovered from R2 object prefixes, so only repos with at least one commit appear.
Repository
Section titled “Repository”Get Metadata
Section titled “Get Metadata”GET /api/repos/:owner/:repoReturns repository metadata:
{ "owner": "alice", "name": "project-a", "description": "My project", "visibility": "public", "default_branch": "main", "created_at": "2025-01-01T00:00:00.000Z", "updated_at": "2025-06-01T00:00:00.000Z"}Update Metadata
Section titled “Update Metadata”PATCH /api/repos/:owner/:repo{ "description": "Updated description", "visibility": "private" }Updatable fields: description, visibility, default_branch.
Initialize
Section titled “Initialize”POST /api/repos/:owner/:repo/init{ "defaultBranch": "main" }Creates the repository with an empty HEAD pointing to the specified branch.
Read File
Section titled “Read File”GET /api/repos/:owner/:repo/files?ref=main&path=src/index.tsReturns the file content at the given ref and path:
{ "content": "console.log('hi')", "size": 17 }Binary files are returned with base64 encoding:
{ "content": "iVBOR...", "size": 1024, "encoding": "base64", "binary": true }List Files
Section titled “List Files”GET /api/repos/:owner/:repo/files?ref=mainLists entries at the root tree:
{ "files": [ { "path": "README.md", "mode": "100644", "type": "blob", "sha": "abc..." }, { "path": "src", "mode": "40000", "type": "tree", "sha": "def..." } ]}List All Files
Section titled “List All Files”GET /api/repos/:owner/:repo/files/all?ref=mainRecursively lists all files (blobs only):
{ "files": [ { "path": "README.md", "mode": "100644", "type": "blob", "sha": "abc..." }, { "path": "src/index.ts", "mode": "100644", "type": "blob", "sha": "ghi..." } ]}Commits
Section titled “Commits”Create Commit
Section titled “Create Commit”POST /api/repos/:owner/:repo/commits{ "ref": "main", "message": "Add feature", "author": "Alice", "email": "alice@example.com", "files": [ { "path": "feature.ts", "content": "export const x = 1;" }, { "path": "old-file.ts", "content": null } ], "timestamp": 1700000000}Set content to null to delete a file. Returns { "sha": "abc..." }.
Get Commit
Section titled “Get Commit”GET /api/repos/:owner/:repo/commits/:shaReturns structured data for a single commit:
{ "sha": "abc...", "tree": "def...", "parents": ["ghi..."], "author": "Alice", "authorEmail": "alice@example.com", "authorTimestamp": 1700000000, "committer": "Alice", "committerEmail": "alice@example.com", "committerTimestamp": 1700000000, "message": "Add feature\n"}GET /api/repos/:owner/:repo/log?ref=main&max=50Returns commit history walking from the given ref. Add &path=src/index.ts to filter to commits that changed a specific file:
GET /api/repos/:owner/:repo/log?ref=main&path=src/index.tsFull log response:
{ "commits": [ { "sha": "abc...", "tree": "def...", "parents": ["ghi..."], "author": "Alice", "authorEmail": "alice@example.com", "authorTimestamp": 1700000000, "committer": "Alice", "committerEmail": "alice@example.com", "committerTimestamp": 1700000000, "message": "Add feature\n" } ]}Branches
Section titled “Branches”List Branches
Section titled “List Branches”GET /api/repos/:owner/:repo/branches{ "branches": [ { "name": "main", "sha": "abc...", "isHead": true }, { "name": "feature", "sha": "def...", "isHead": false } ]}Create Branch
Section titled “Create Branch”POST /api/repos/:owner/:repo/branches{ "name": "feature", "startPoint": "main" }startPoint defaults to HEAD if omitted.
Delete Branch
Section titled “Delete Branch”DELETE /api/repos/:owner/:repo/branches/:nameCannot delete the currently checked-out branch.
Rename Branch
Section titled “Rename Branch”PATCH /api/repos/:owner/:repo/branches/:name{ "newName": "feature-v2" }Updates HEAD if it pointed to the old branch.
Checkout
Section titled “Checkout”Switch Branch
Section titled “Switch Branch”POST /api/repos/:owner/:repo/checkout{ "branch": "feature" }Detach HEAD
Section titled “Detach HEAD”POST /api/repos/:owner/:repo/detach-head{ "sha": "abc123..." }Sets HEAD to a specific commit SHA (detached HEAD state).
List Tags
Section titled “List Tags”GET /api/repos/:owner/:repo/tags{ "tags": [ { "name": "v1.0", "sha": "abc...", "type": "lightweight" }, { "name": "v2.0", "sha": "def...", "type": "annotated", "target": "ghi...", "tagger": "Alice", "message": "Release v2.0\n" } ]}Create Lightweight Tag
Section titled “Create Lightweight Tag”POST /api/repos/:owner/:repo/tags{ "name": "v1.0", "target": "main" }Create Annotated Tag
Section titled “Create Annotated Tag”POST /api/repos/:owner/:repo/tags{ "name": "v2.0", "target": "main", "tagger": "Alice", "email": "alice@example.com", "message": "Release v2.0"}If message is present, an annotated tag object is created. target resolves a ref or SHA to the commit being tagged (defaults to HEAD).
Delete Tag
Section titled “Delete Tag”DELETE /api/repos/:owner/:repo/tags/:nameGET /api/repos/:owner/:repo/diff?a=<ref>&b=<ref>GET /api/repos/:owner/:repo/diff?from=<ref>&to=<ref>Compares two refs. Both a/b and from/to parameter names are accepted. If b/to is omitted, diffs against the parent commit.
{ "entries": [ { "path": "feature.ts", "status": "added", "newSha": "abc..." }, { "path": "old.ts", "status": "deleted", "oldSha": "def..." }, { "path": "main.ts", "status": "modified", "oldSha": "ghi...", "newSha": "jkl..." } ]}Inline Diff Content
Section titled “Inline Diff Content”Add &content=true to include unified diff patches and size information:
GET /api/repos/:owner/:repo/diff?a=<ref>&b=<ref>&content=true{ "entries": [ { "path": "main.ts", "status": "modified", "oldSha": "ghi...", "newSha": "jkl...", "oldSize": 120, "newSize": 145, "patch": "--- a/main.ts\n+++ b/main.ts\n@@ -1,3 +1,5 @@\n..." }, { "path": "image.png", "status": "modified", "oldSha": "mno...", "newSha": "pqr...", "binary": true } ]}Binary files are detected automatically (null byte in first 8KB) and flagged with "binary": true instead of a patch. When PACK_WORKER is configured, diff computation fans out to the compute pool for large changesets.
GET /api/repos/:owner/:repo/grep?pattern=<regex>&ref=<ref>&context=<n>Searches blob content at the given ref using a regular expression. Returns matching lines with surrounding context.
| Parameter | Default | Description |
|---|---|---|
pattern (or q) | required | Regex pattern to search for |
ref | HEAD | Branch, tag, or commit SHA |
context | 2 | Lines of context before/after each match (max 10) |
{ "matches": [ { "path": "src/index.ts", "lines": [ { "num": 5, "text": "import { createHandler } from 'gitmode';", "match": true }, { "num": 6, "text": "", "match": false } ] } ]}When PACK_WORKER is configured, grep fans out to the compute pool for repos with many files.
POST /api/repos/:owner/:repo/merge{ "target": "main", "source": "feature", "author": "Alice", "email": "alice@example.com", "message": "Merge feature into main"}Returns the merge strategy used:
{ "sha": "abc...", "strategy": "fast-forward" }or for a three-way merge:
{ "sha": "abc...", "strategy": "merge" }Conflicts are resolved automatically (takes theirs for conflicting files).
Cherry-Pick
Section titled “Cherry-Pick”POST /api/repos/:owner/:repo/cherry-pick{ "commit": "<sha>", "target": "main", "author": "Alice", "email": "alice@example.com"}Applies the changes from the specified commit onto the target branch using three-way merge.
Revert
Section titled “Revert”POST /api/repos/:owner/:repo/revert{ "commit": "<sha>", "target": "main", "author": "Alice", "email": "alice@example.com"}Creates a new commit that undoes the changes introduced by the specified commit.
POST /api/repos/:owner/:repo/reset{ "ref": "main", "target": "<sha>" }Moves the branch ref to point at a different commit.
Rev-Parse
Section titled “Rev-Parse”GET /api/repos/:owner/:repo/rev-parse?ref=HEADResolves a ref to a commit SHA. Supports: branch names, tag names, HEAD, HEAD~N, HEAD^, HEAD^2, raw SHAs.
{ "sha": "abc..." }Contributors
Section titled “Contributors”GET /api/repos/:owner/:repo/contributorsAggregates author statistics from the commit index:
{ "contributors": [ { "name": "Alice <alice@example.com>", "commits": 42, "lastCommit": 1700000000 }, { "name": "Bob <bob@example.com>", "commits": 17, "lastCommit": 1699000000 } ]}GET /api/repos/:owner/:repo/stats?ref=mainReturns repository statistics:
{ "commits": 42, "branches": 3, "tags": 5, "files": 28, "size": 145920}size is total uncompressed file content in bytes.
Show Object
Section titled “Show Object”GET /api/repos/:owner/:repo/show?sha=<sha>Reads a raw git object:
{ "type": "commit", "size": 234, "content": "tree abc...\nparent ..." }For blob objects with binary content (null byte in first 8KB), the response includes base64 encoding:
{ "type": "blob", "size": 1024, "content": "iVBOR...", "encoding": "base64", "binary": true }