{"openapi":"3.0.3","info":{"title":"OrbitGit API","version":"1.0.0","description":"Manage git repositories hosted on OrbitGit: list, create, read, edit, commit, merge, and delete repositories and files. Authenticate with an OrbitGit device token (obg_…) as a Bearer token."},"servers":[{"url":"https://orbitgit.com/api/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"OrbitGit device token (obg_…)"}},"schemas":{"Error":{"type":"object","properties":{"ok":{"type":"boolean","example":false},"error":{"type":"string"}}},"Repository":{"type":"object","properties":{"owner":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"visibility":{"type":"string","enum":["private","public"]},"defaultBranch":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}},"CommitFile":{"type":"object","required":["path","content"],"properties":{"path":{"type":"string","description":"File path inside the repository"},"content":{"type":"string","description":"Full new file content (UTF-8)"}}}}},"paths":{"/repos/{owner}/{name}/builds":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"get":{"operationId":"getBuilds","summary":"Owner-only build configuration and run history; no job credentials are returned","responses":{"200":{"description":"Config and recent runs"},"403":{"description":"Owner access required"}}}},"/repos/{owner}/{name}/builds/config":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"put":{"operationId":"configureBuilds","summary":"Configure customer-owned GitHub or Depot runners and optional Docker image builds","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["githubOwner","githubRepo"],"properties":{"githubOwner":{"type":"string"},"githubRepo":{"type":"string"},"provider":{"type":"string","enum":["github","depot"],"default":"github"},"enabled":{"type":"boolean","default":false},"onPush":{"type":"boolean","default":true},"branch":{"type":"string","default":"main"},"workflow":{"type":"string","default":"orbitgit-build.yml"},"workflowRef":{"type":"string","default":"main"},"command":{"type":"string","maxLength":20000},"artifacts":{"type":"string","default":"dist/*"},"docker":{"type":"boolean"},"dockerfile":{"type":"string","default":"Dockerfile"},"dockerContext":{"type":"string","default":"."},"depotProject":{"type":"string"},"timeoutMinutes":{"type":"integer","minimum":1,"maximum":60,"default":30}}}}}},"responses":{"200":{"description":"Validated configuration; enable only after installing the workflow"},"400":{"description":"Invalid setup or GitHub access"}}}},"/repos/{owner}/{name}/builds/runs":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"post":{"operationId":"startBuild","summary":"Queue a manual build pinned to the configured OrbitGit branch commit","responses":{"202":{"description":"Queued run or visible dispatch error"},"400":{"description":"Builds must be enabled and branch must exist"}}}},"/repos/{owner}/{name}/builds/workflow":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"get":{"operationId":"downloadBuildWorkflow","summary":"Generate the customer-owned GitHub Actions workflow with scoped OIDC checkout and draft artifact upload","responses":{"200":{"description":"Workflow YAML","content":{"text/yaml":{"schema":{"type":"string"}}}}}}},"/repos/{owner}/{name}/builds/runs/{runId}/refresh":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"runId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"operationId":"refreshBuildStatus","summary":"Reconcile a run with GitHub provider status","responses":{"200":{"description":"Updated run"}}}},"/repos/{owner}/{name}/builds/runs/{runId}/cancel":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"runId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"operationId":"cancelBuild","summary":"Cancel the provider run and revoke its scoped OrbitGit credentials","responses":{"200":{"description":"Cancelled run"}}}},"/repos/{owner}/{name}/releases":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"get":{"operationId":"listReleases","summary":"Owner-only release drafts, publications, and unlisted link","responses":{"200":{"description":"Releases and optional shareToken"},"403":{"description":"Owner access required"}}},"post":{"operationId":"createRelease","summary":"Create a private release draft; repository visibility is unchanged","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["version"],"properties":{"version":{"type":"string","maxLength":64},"title":{"type":"string","maxLength":200},"notes":{"type":"string","maxLength":20000}}}}}},"responses":{"201":{"description":"Draft with release id"},"409":{"description":"Version exists"}}}},"/repos/{owner}/{name}/releases/share":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"post":{"operationId":"shareReleases","summary":"Enable an unlisted link for published artifacts and a stable latest.json feed","responses":{"200":{"description":"shareToken for /releases/{shareToken}; anyone with this link can download published artifacts"}}},"delete":{"operationId":"revokeReleaseLink","summary":"Immediately revoke release downloads and update feed; reenabling creates a new token","responses":{"200":{"description":"Revoked"}}}},"/repos/{owner}/{name}/releases/{releaseId}/assets":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"operationId":"createReleaseAsset","summary":"Declare a draft artifact upload, stored in the owner storage","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","size"],"properties":{"name":{"type":"string","maxLength":180},"size":{"type":"integer","minimum":1,"maximum":536870912}}}}}},"responses":{"201":{"description":"Asset id and number of 8 MiB chunks; the last chunk uses the remaining bytes"}}}},"/repos/{owner}/{name}/releases/{releaseId}/assets/{assetId}/chunks/{index}":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"assetId","in":"path","required":true,"schema":{"type":"string"}},{"name":"index","in":"path","required":true,"schema":{"type":"integer","minimum":0}}],"put":{"operationId":"uploadReleaseChunk","summary":"Upload an exactly sized binary chunk to an incomplete draft asset","requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Uploaded chunk"},"409":{"description":"Asset completed or release published"},"413":{"description":"Chunk size mismatch"}}}},"/repos/{owner}/{name}/releases/{releaseId}/assets/{assetId}/complete":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"assetId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"operationId":"completeReleaseUpload","summary":"Verify every chunk and its complete SHA-256; freeze the asset","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sha256"],"properties":{"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}}}}}},"responses":{"200":{"description":"Verified asset"},"400":{"description":"Incomplete upload or checksum mismatch"}}}},"/repos/{owner}/{name}/releases/{releaseId}/assets/{assetId}/{filename}":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}},{"name":"assetId","in":"path","required":true,"schema":{"type":"string"}},{"name":"filename","in":"path","required":true,"schema":{"type":"string"}}],"get":{"operationId":"downloadOwnerReleaseAsset","summary":"Owner-only download of a verified draft or published artifact; sharing is not required","responses":{"200":{"description":"Artifact bytes"},"206":{"description":"Byte range"},"403":{"description":"Owner access required"},"404":{"description":"Artifact absent or incomplete"}}},"head":{"operationId":"headOwnerReleaseAsset","summary":"Owner-only artifact metadata without downloading bytes","responses":{"200":{"description":"Size and checksum headers"}}}},"/repos/{owner}/{name}/releases/{releaseId}/publish":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"operationId":"publishRelease","summary":"Publish a verified immutable release; existing unlisted link receives this new latest version","responses":{"200":{"description":"Published release"},"400":{"description":"Uploads must be complete"}}}},"/repos/{owner}/{name}/releases/{releaseId}":{"parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"operationId":"deleteRelease","summary":"Delete a draft or published release and its artifact chunks","responses":{"200":{"description":"Deleted"}}}},"/health":{"get":{"operationId":"getHealth","summary":"Service, auth provider, and storage backend status","security":[],"responses":{"200":{"description":"Service status"}}}},"/me":{"get":{"operationId":"getMe","summary":"Current authenticated user","responses":{"200":{"description":"Session user"},"401":{"description":"Unauthorized"}}}},"/repos":{"get":{"operationId":"listRepos","summary":"List repositories visible to the caller","responses":{"200":{"description":"Repositories"}}},"post":{"operationId":"createRepo","summary":"Create a repository","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"visibility":{"type":"string","enum":["private","public"]},"seedReadme":{"type":"boolean"}}}}}},"responses":{"201":{"description":"Created repository"},"401":{"description":"Unauthorized"}}}},"/storage":{"get":{"operationId":"getStorageProfile","summary":"Get the bring-your-own storage profile (s3, webdav, or sftp)","responses":{"200":{"description":"Storage profile or null"},"401":{"description":"Unauthorized"}}},"put":{"operationId":"saveStorageProfile","summary":"Create or update the bring-your-own storage profile","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["s3","webdav","sftp"],"default":"s3"},"bucket":{"type":"string","description":"s3 only"},"endpoint":{"type":"string","description":"s3 only, https URL"},"region":{"type":"string","description":"s3 only"},"accessKeyId":{"type":"string","description":"s3 only"},"url":{"type":"string","description":"webdav only, https URL"},"host":{"type":"string","description":"sftp only"},"port":{"type":"integer","description":"sftp only, default 22"},"username":{"type":"string","description":"webdav/sftp user"},"secret":{"type":"string","description":"s3 secret key / webdav or sftp password. Omit to keep the saved one."},"privateKey":{"type":"string","description":"sftp only, PEM block. Omit to keep the saved one."},"prefix":{"type":"string","description":"s3 key prefix / webdav or sftp root folder"}}}}}},"responses":{"200":{"description":"Saved profile"},"401":{"description":"Unauthorized"}}},"delete":{"operationId":"deleteStorageProfile","summary":"Remove the bring-your-own storage profile","responses":{"200":{"description":"Deleted"},"401":{"description":"Unauthorized"}}}},"/cache":{"get":{"operationId":"getCacheProfile","summary":"Get the bring-your-own cache profile (Redis/Dragonfly)","responses":{"200":{"description":"Cache profile or null"},"401":{"description":"Unauthorized"}}},"put":{"operationId":"saveCacheProfile","summary":"Create or update the bring-your-own cache profile","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["host"],"properties":{"host":{"type":"string"},"port":{"type":"integer","default":6379},"tls":{"type":"boolean","default":false},"username":{"type":"string"},"password":{"type":"string","description":"Omit to keep the saved one."},"db":{"type":"integer","default":0},"prefix":{"type":"string","description":"Key prefix inside the cache server"},"ttlSeconds":{"type":"integer","default":300}}}}}},"responses":{"200":{"description":"Saved profile"},"401":{"description":"Unauthorized"}}},"delete":{"operationId":"deleteCacheProfile","summary":"Remove the bring-your-own cache profile (repos fall back to the built-in cache)","responses":{"200":{"description":"Deleted"},"401":{"description":"Unauthorized"}}}},"/repos/{owner}/{name}":{"get":{"operationId":"getRepo","summary":"Get one repository","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository"},"404":{"description":"Not found"}}},"delete":{"operationId":"deleteRepo","summary":"Delete a repository","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"401":{"description":"Unauthorized"}}}},"/repos/{owner}/{name}/branches":{"get":{"operationId":"listBranches","summary":"List branches","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Branches"}}}},"/repos/{owner}/{name}/tree":{"get":{"operationId":"listTree","summary":"List a directory of the repository tree","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"ref","in":"query","schema":{"type":"string"},"description":"Branch or commit"},{"name":"path","in":"query","schema":{"type":"string"},"description":"Directory path (default root)"}],"responses":{"200":{"description":"Tree entries"}}}},"/repos/{owner}/{name}/files":{"get":{"operationId":"listFiles","summary":"List all file paths on a ref","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"ref","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"File paths"}}},"delete":{"operationId":"deleteFile","summary":"Delete a file (creates a commit)","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"path","in":"query","required":true,"schema":{"type":"string"}},{"name":"ref","in":"query","schema":{"type":"string"},"description":"Branch (default main)"}],"responses":{"200":{"description":"Delete commit"},"401":{"description":"Unauthorized"}}}},"/repos/{owner}/{name}/blob":{"get":{"operationId":"readFile","summary":"Read a file’s content","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"path","in":"query","required":true,"schema":{"type":"string"}},{"name":"ref","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"File content"}}}},"/repos/{owner}/{name}/commits":{"get":{"operationId":"listCommits","summary":"List commits on a ref","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"ref","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}}],"responses":{"200":{"description":"Commits"}}},"post":{"operationId":"commitFiles","summary":"Create or update files with one commit (edit/update/change)","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["files"],"properties":{"branch":{"type":"string","default":"main"},"message":{"type":"string"},"files":{"type":"array","items":{"$ref":"#/components/schemas/CommitFile"}}}}}}},"responses":{"201":{"description":"New commit"},"401":{"description":"Unauthorized"}}}},"/repos/{owner}/{name}/commits/{oid}":{"get":{"operationId":"readCommitDiff","summary":"Read a commit with its diff","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"oid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Commit diff"}}}},"/repos/{owner}/{name}/merge-check":{"get":{"operationId":"checkMerge","summary":"Check whether head can merge into base","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"base","in":"query","schema":{"type":"string"}},{"name":"head","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Merge check"}}}},"/repos/{owner}/{name}/merge":{"post":{"operationId":"mergeBranches","summary":"Merge head into base","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["head"],"properties":{"base":{"type":"string"},"head":{"type":"string"},"message":{"type":"string"}}}}}},"responses":{"200":{"description":"Merge result"},"409":{"description":"Merge blocked"}}}},"/repos/{owner}/{name}/github/status":{"get":{"operationId":"githubSyncStatus","summary":"GitHub mirror sync status","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sync status"}}}},"/repos/{owner}/{name}/github/pull":{"post":{"operationId":"githubPull","summary":"Pull (resync) the repository from its linked GitHub repo","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Pulled"},"409":{"description":"Conflicts"}}}},"/repos/{owner}/{name}/github/create":{"post":{"operationId":"githubCreate","summary":"Create a GitHub repository for an OrbitGit-only repo and push all branches to it","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"GitHub repository name (default: same as the OrbitGit repo)"},"private":{"type":"boolean","description":"GitHub visibility (default: mirrors the OrbitGit repo)"},"token":{"type":"string","description":"GitHub token with repo creation scope; defaults to the saved one"}}}}}},"responses":{"201":{"description":"Created GitHub repository and pushed branches"},"401":{"description":"Unauthorized"}}}},"/repos/{owner}/{name}/github/push":{"post":{"operationId":"githubPush","summary":"Push the repository to its linked GitHub repo","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Pushed"}}}},"/repos/{owner}/{name}/secrets":{"get":{"operationId":"listSecrets","summary":"List vaulted .env secrets for a repository","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"download","in":"query","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Secrets"},"401":{"description":"Unauthorized"}}},"put":{"operationId":"writeSecret","summary":"Create or update a vaulted secret file","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string"},"content":{"type":"string"}}}}}},"responses":{"200":{"description":"Saved"},"401":{"description":"Unauthorized"}}}},"/repos/{owner}/{name}/secrets/{file}":{"get":{"operationId":"readSecret","summary":"Read one vaulted secret file","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"file","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Secret content"}}},"delete":{"operationId":"deleteSecret","summary":"Delete one vaulted secret file","parameters":[{"name":"owner","in":"path","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"file","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"}}}}}}