Skip to main content

Repositories

Repository endpoints cover lifecycle operations: creating new storage, reading metadata, and coordinating upstream mirrors.

Create repository POST

Creates a new repository in your organization, with optional links to an external mirror.
POST /api/v1/repos
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "default_branch": "main",  // Optional, defaults to "main"
  "base_repo": {             // Optional, for GitHub sync
    "provider": "github",
    "owner": "org-name",
    "name": "repo-name",
    "default_branch": "main"
  }
}
Request Body Fields
ParameterTypeDescription
default_branchOptionalDefault branch name for the Code Storage repository (defaults to “main”)
base_repoOptionalConfiguration for syncing with an external repository (e.g., GitHub)
JWT Requirements
  • Requires the repo:write scope
Response
{
  "id": "team/project-alpha",
  "created_at": "2024-01-15T10:30:00Z"
}
Error Responses
  • 401 Unauthorized - Invalid JWT or missing repo:write scope
  • 409 Conflict - Repository already exists

Pull from upstream POST

Triggers a sync from the configured upstream repository (e.g., GitHub) for repositories with GitHub sync enabled.
POST /api/v1/repos/pull-upstream
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "ref": "main",      // Optional: specific ref to sync
  "after": "abc123"   // Optional: sync commits after this SHA
}
Request Body Fields
ParameterTypeDescription
refOptionalSpecific ref to sync from upstream
afterOptionalOnly sync commits after this SHA
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:write scope
Response
{
  "message": "Repository sync initiated successfully"
}
Notes
  • Returns 202 Accepted - sync is initiated asynchronously
  • Only works for repositories that have an upstream configured via base_repo during creation
  • See GitHub Sync guide for setup details
  • The SDK provides repo.pullUpstream() for this operation
Error Responses
  • 403 Forbidden - Invalid JWT or missing git:write scope
  • 404 Not Found - Repository doesn’t exist
  • 400 Bad Request - Repository has no upstream configured
  • 500 Internal Server Error - Sync service unavailable

Branches

Branch endpoints help you explore parallel lines of work and compare them against the default branch.

List branches GET

Retrieve branches in a repository with pagination.
GET /api/v1/repos/branches?cursor=CURSOR&limit=20
Authorization: Bearer YOUR_JWT_TOKEN
Parameters
ParameterTypeDescription
cursorOptionalPagination cursor from previous response
limitOptionalMaximum number of branches to return (default: 20)
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:read scope
Response
{
  "branches": [
    {
      "cursor": "b_123abc",
      "name": "main",
      "head_sha": "a1b2c3d4e5f6...",
      "created_at": "2024-01-15T10:30:00Z"
    },
    {
      "cursor": "b_456def",
      "name": "feature/auth",
      "head_sha": "f6e5d4c3b2a1...",
      "created_at": "2024-01-16T14:20:00Z"
    }
  ],
  "next_cursor": "b_456def",
  "has_more": true
}
Notes
  • The cursor field is an opaque pagination token for each branch
  • The next_cursor value should be used for fetching the next page
  • Branches are ordered by creation time
Error Responses
  • 401 Unauthorized - Invalid JWT or missing git:read scope

Get branch diff GET

Compares a feature branch to its base so you can review every change before merging.
GET /api/v1/repos/branches/diff?branch=BRANCH_NAME&base=BASE_BRANCH&ephemeral=true&ephemeral_base=false
Authorization: Bearer YOUR_JWT_TOKEN
Parameters
ParameterTypeDescription
branchRequiredThe branch name to get the diff for
baseOptionalBase branch to compare against (defaults to repository’s default branch)
ephemeralOptionalWhen true, resolves the branch ref under refs/namespaces/ephemeral/refs/heads/<branch>
ephemeral_baseOptionalWhen true, resolves the base ref under refs/namespaces/ephemeral/refs/heads/<base>
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:read scope
Response
{
  "branch": "feature/new-feature",
  "base": "main",
  "stats": {
    "files": 5,
    "additions": 120,
    "deletions": 30,
    "changes": 150
  },
  "files": [
    {
      "path": "src/feature.go",
      "state": "A",
      "old_path": "",
      "bytes": 2048,
      "is_eof": true,
      "raw": "diff --git a/src/feature.go b/src/feature.go\nnew file mode 100644\nindex 0000000..abc123\n--- /dev/null\n+++ b/src/feature.go\n@@ -0,0 +1,50 @@\n+package main\n+\n+func NewFeature() {\n+    // Implementation\n+}\n"
    },
    {
      "path": "src/main.go",
      "state": "M",
      "old_path": "",
      "bytes": 1024,
      "is_eof": true,
      "raw": "diff --git a/src/main.go b/src/main.go\nindex abc123..def456 100644\n--- a/src/main.go\n+++ b/src/main.go\n@@ -10,6 +10,8 @@\n+    feature := NewFeature()\n+    feature.Run()\n"
    }
  ],
  "filtered_files": [
    {
      "path": "go.sum",
      "state": "M",
      "old_path": "",
      "bytes": 50000,
      "is_eof": true
    }
  ]
}
Notes
  • Shows all changes in the branch compared to the base branch
  • If base is not specified, compares against the repository’s default branch (usually “main”)
  • Uses three-dot diff notation internally (base…branch) to show changes since branch diverged
  • Large files and binary files are included in filtered_files without diff content
  • Useful for reviewing all changes in a feature branch before merging
  • For more about ephemeral branches, see the Ephemeral branches guide
Error Responses
  • 404 Not Found - Branch or base branch doesn’t exist
  • 401 Unauthorized - Invalid JWT or missing git:read scope
  • 400 Bad Request - Missing branch parameter or invalid ephemeral/ephemeral_base value

Commits

Commit endpoints surface history so you can audit changes, inspect metadata, and pull down diffs when you need to troubleshoot a release.

List commits GET

Retrieve commit history for a branch with pagination.
GET /api/v1/repos/commits?branch=main&cursor=CURSOR&limit=20
Authorization: Bearer YOUR_JWT_TOKEN
Parameters
ParameterTypeDescription
branchOptionalBranch name (defaults to repository’s default branch)
cursorOptionalPagination cursor from previous response
limitOptionalMaximum number of commits to return (default: 20)
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:read scope
Response
{
  "commits": [
    {
      "sha": "b003fc78805954584e1ee364a4ad39d7c79e819a",
      "message": "fix: resolve scrolling issue in dashboard",
      "author_name": "Jane Doe",
      "author_email": "[email protected]",
      "committer_name": "Jane Doe",
      "committer_email": "[email protected]",
      "date": "2024-01-15T14:32:18Z"
    },
    {
      "sha": "a4d39d7c79e819ab003fc78805954584e1ee36",
      "message": "feat: add user authentication",
      "author_name": "John Smith",
      "author_email": "[email protected]",
      "committer_name": "John Smith",
      "committer_email": "[email protected]",
      "date": "2024-01-14T10:15:00Z"
    }
  ],
  "next_cursor": "20",
  "has_more": true
}
Notes
  • The cursor represents the number of commits to skip
  • Commits are ordered by commit date (newest first)
  • If branch is not specified, uses the repository’s default branch
Error Responses
  • 404 Not Found - Branch doesn’t exist (includes branch name in error)
  • 401 Unauthorized - Invalid JWT or missing git:read scope
  • 400 Bad Request - Invalid cursor format

Get commit diff GET

Streams the full diff for a commit to help you review file-level changes.
GET /api/v1/repos/diff?sha=COMMIT_SHA&baseSha=BASE_COMMIT_SHA
Authorization: Bearer YOUR_JWT_TOKEN
Parameters
ParameterTypeDescription
shaRequiredThe full commit SHA to get the diff for
baseShaOptionalBase commit SHA to compare against. If not specified, compares against the commit’s parent(s)
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:read scope
Response
{
  "sha": "b003fc78805954584e1ee364a4ad39d7c79e819a",
  "stats": {
    "files": 3,
    "additions": 50,
    "deletions": 10,
    "changes": 60
  },
  "files": [
    {
      "path": "src/main.go",
      "state": "M",
      "old_path": "",
      "bytes": 2048,
      "is_eof": true,
      "raw": "diff --git a/src/main.go b/src/main.go\nindex abc123..def456 100644\n--- a/src/main.go\n+++ b/src/main.go\n@@ -10,6 +10,8 @@\n+func newFunction() {\n+    // New implementation\n+}\n"
    },
    {
      "path": "README.md",
      "state": "A",
      "old_path": "",
      "bytes": 512,
      "is_eof": true,
      "raw": "diff --git a/README.md b/README.md\nnew file mode 100644\nindex 0000000..abc123\n--- /dev/null\n+++ b/README.md\n@@ -0,0 +1,5 @@\n+# Project Title\n+\n+Description of the project\n"
    }
  ],
  "filtered_files": [
    {
      "path": "package-lock.json",
      "state": "M",
      "old_path": "",
      "bytes": 50000,
      "is_eof": true
    }
  ]
}
Notes
  • The diff includes both file-level changes and line-by-line diffs
  • When baseSha is not provided, the diff shows changes from the commit’s parent(s)
  • When baseSha is provided, the diff shows changes between the base commit and the target commit (useful for comparing specific commits)
  • Large files (>500KB) or files with too many changes (>2000 lines) are included in filtered_files without diff content
  • Binary files and lock files are automatically filtered
  • The is_eof field indicates whether the file ends with a newline
  • Git status codes: A (added), M (modified), D (deleted), R (renamed), C (copied), T (type changed)
Error Responses
  • 404 Not Found - Commit doesn’t exist
  • 401 Unauthorized - Invalid JWT or missing git:read scope
  • 400 Bad Request - Missing or invalid SHA parameter

Create commit POST

Create a commit by streaming file contents as newline-delimited JSON.
POST /api/v1/repos/commit-pack
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/x-ndjson
Request format The body is newline-delimited JSON. Send metadata first, followed by one or more blob chunks.
{"metadata":{"target_branch":"main","expected_head_sha":"d34db33fd34db33fd34db33fd34db33f","commit_message":"Update docs","author":{"name":"Docs Bot","email":"[email protected]"},"files":[{"path":"docs/changelog.md","operation":"upsert","content_id":"blob-1","mode":"100644"},{"path":"docs/legacy.txt","operation":"delete","content_id":"blob-2"}]}}
{"blob_chunk":{"content_id":"blob-1","data":"IyBWZXJzaW9uIDIuMS4wCi0gcmVmcmVzaCBkb2NzCg==","eof":true}}
{"blob_chunk":{"content_id":"blob-2","data":"","eof":true}}
Request Body Fields
ParameterTypeDescription
target_branchRequiredBranch name (for example main)
commit_messageRequiredThe commit message
authorRequiredObject with name, email, and optional ISO 8601 date
filesRequiredArray of file operations (see below)
expected_head_shaOptionalCommit SHA that must match the branch tip before writing; omit to fast-forward unconditionally
base_branchOptionalSource branch to copy when target_branch does not exist. If you also provide expected_head_sha, it must match the source branch head; otherwise the branch is created from the latest base branch commit
committerOptionalObject with name, email, and optional ISO 8601 date
File operations
  • path (required): Repository-relative path; leading slashes are stripped
  • operation: upsert (default) to add or replace content, delete to remove a file
  • content_id (required): Identifier that blob chunks reference
  • mode (optional): File mode such as 100644 or 100755
  • For delete operations, omit blob chunks—only the metadata entry is required
Blob chunks
  • Each line after the metadata must contain a blob_chunk object
  • content_id ties the chunk to a file operation
  • data is base64 encoded; decoded chunks must be 4 MiB or smaller
  • Use multiple blob_chunk messages per file for streaming; mark the last chunk with "eof": true
  • Empty files should send an EOF chunk with an empty base64 string
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:write scope
Response
{
  "commit": {
    "commit_sha": "8f12c3bd0f4ff7bfb7267e7a61b3c4a8712a10b2",
    "tree_sha": "b9532c5d5be50d88e2f45d7c229566b2f1f99731",
    "target_branch": "main",
    "pack_bytes": 5421,
    "blob_count": 2
  },
  "result": {
    "branch": "main",
    "old_sha": "c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2",
    "new_sha": "8f12c3bd0f4ff7bfb7267e7a61b3c4a8712a10b2",
    "success": true,
    "status": "ok",
    "message": ""
  }
}
Notes
  • Successful requests return 201 Created; validation errors return 4xx codes with error details
  • Use the SDK’s repo.createCommit() helper for streaming, chunking, and authentication automatically
  • The target_branch must already exist unless you include base_branch, in which case the service creates the target branch from that source branch when it is missing
  • If you passed an expected_head_sha, the service verifies it matches the source branch head before creating the new branch
  • Repositories with no refs can still omit expected_head_sha to seed their default branch
  • Pair expected_head_sha with a commit SHA to enforce fast-forward semantics during migrations or CI jobs
  • result.old_sha is always a 40-character hex string reflecting the previous tip; it is 0000000000000000000000000000000000000000 when the target branch did not previously exist
Error Responses
  • 401 Unauthorized - Invalid JWT or missing git:write scope
  • 400 Bad Request - Invalid request format, missing required fields, or blob chunk validation errors
  • 409 Conflict - Expected head SHA doesn’t match current branch tip
  • 404 Not Found - Base branch doesn’t exist (when creating new target branch)

Create commit from diff POST

Create a commit by streaming a Git patch instead of individual file blobs.
POST /api/v1/repos/diff-commit
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/x-ndjson
Request format Like commit-pack, the payload is newline-delimited JSON. Send a metadata object first, followed by one or more diff_chunk entries.
{"metadata":{"target_branch":"main","expected_head_sha":"d34db33fd34db33fd34db33fd34db33f","commit_message":"Apply generated patch","author":{"name":"Diff Bot","email":"[email protected]"}}}
{"diff_chunk":{"data":"ZGlmZiAtLWdpdCAuLi4=","eof":false}}
{"diff_chunk":{"data":"K25ldyBmaWxlIG1vZGUgMTAwNjQ0\n","eof":true}}
Request Body Fields
ParameterTypeDescription
target_branchRequiredDestination branch
commit_messageRequiredCommit message
authorRequiredObject with name, email, and optional ISO 8601 timestamp
expected_head_shaOptionalGuard ensuring the branch tip matches before applying the patch
base_branchOptionalSeed when the target branch does not exist yet
committerOptionalObject with name, email, and optional ISO 8601 timestamp
ephemeralOptionalSame semantics as commit-pack
ephemeral_baseOptionalSame semantics as commit-pack
Diff chunks
  • diff_chunk.data contains base64-encoded diff bytes; decoded payloads must be ≤ 4 MiB
  • Chunks are streamed sequentially; set "eof": true on the final chunk
  • The combined diff must be compatible with git apply --cached --binary (include file headers, mode lines, and hunk metadata)
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:write scope
Response The service returns the same schema as commit-pack responses. Notes
  • result.success is false when the diff cannot be applied (for example, conflicts or empty diffs) and status reflects the mapped reason (conflict, precondition_failed, etc.)
Error Responses
  • 404 Not Found - Branch doesn’t exist
  • 401 Unauthorized - Invalid JWT or missing git:write scope
  • 400 Bad Request - Invalid request format or diff cannot be applied

Files

File endpoints give you flexible read access so you can power directory listings or stream individual blobs straight into your application.

List files GET

Enumerates every file at the requested reference to help you build navigation or quick comparisons.
GET /api/v1/repos/files?ref=BRANCH_OR_SHA
Authorization: Bearer YOUR_JWT_TOKEN
Parameters
ParameterTypeDescription
refOptionalBranch name or commit SHA. If not specified, uses the repository’s default branch
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:read scope
Response
{
  "paths": ["README.md", "package.json", "src/index.js", "src/utils/helper.js"],
  "ref": "main"
}
Notes
  • Returns all files in the repository at the specified ref
  • Directories are not included in the list, only files
  • File paths are relative to the repository root
  • If no ref is specified, the repository’s default branch is used (typically main or master)
  • paths: Array of file paths in the repository
  • ref: The resolved reference (branch name or commit SHA) that was used
Error Responses
  • 404 Not Found - Reference doesn’t exist
  • 401 Unauthorized - Invalid JWT or missing git:read scope

Get file content GET

Streams the bytes for a single file at any branch, tag, or commit.
GET /api/v1/repos/file?path=FILE_PATH&ref=BRANCH_OR_SHA
Authorization: Bearer YOUR_JWT_TOKEN
Parameters
ParameterTypeDescription
pathRequiredThe path to the file to read
refOptionalBranch name or commit SHA. If not specified, uses the repository’s default branch
JWT Requirements
  • The JWT must include the repository in the repo claim
  • Requires git:read scope
Notes
  • Returns raw file bytes as streaming response
  • If no ref is specified, the repository’s default branch is used (typically main)
Error Responses
  • 404 Not Found - File or reference doesn’t exist
  • 401 Unauthorized - Invalid JWT or missing git:read scope
  • 400 Bad Request - Missing path parameter or invalid file path