Vetrix Docs

Repositories

Reference for the repository endpoints under /api/v1/repos: creating, reading, updating, and administering repositories along with their visibility tier, collaborators, branches, tags, and file contents.

Resource overview

A repository is identified by its owner username and name. The collection lives at /api/v1/repos, and every per-repository operation hangs off /api/v1/repos/{owner}/{repo}/.... This page covers:

  • the repository record — list, fetch, create, update, delete;
  • visibility — the public / internal / private tier that gates who can read a repository;
  • collaborators — the per-repository access list and effective permissions;
  • branches and tags — listing git refs and creating or deleting them;
  • contents, raw bytes, and blame — reading files and directory listings at a ref;
  • transfer — moving a repository to another owner (an instance-administration operation).

Resources that read as part of a repository but are documented elsewhere: merge requests on merges.md, issues on issues.md, pipelines and CI/CD on cicd.md, and packages under registry.

Visibility tiers

Every repository has one of three visibility tiers, which decides who may read it:

Tier Who can read
public Anyone, including unauthenticated callers.
internal Any authenticated user on the instance.
private The owner, instance administrators, and collaborators that hold repository read access.

Read endpoints enforce this tier. A private repository the caller may not read returns 404 Not Found — never 403 — so its existence is not disclosed; see the 404-not-403 rule in errors.md. internal and public repositories are visible to the audiences their tier defines.

The visibility field is the canonical representation. The boolean is_private is a deprecated shim that equals visibility == "private"; it is still accepted on write and emitted on read, but new integrations should use visibility.

Auth & scopes

See conventions.md for the accepted credential types and how scopes are enforced. Read endpoints on public repositories need no credential; all other access carries a bearer token. The operations on this page require:

Operation OAuth2 scope PAT scope
Read read:repo repo:read
Write write:repo repo:write
Administer admin:repo repo:admin

Scope is enforced additively with the underlying access check, so the per-caller authorization noted on each endpoint below still applies. Two operations are narrower than the scope table suggests:

  • Updating repository metadata and deleting a repository are restricted to the owner or an instance administrator. A collaborator with write access can push refs but cannot rename, re-tier, or delete the repository.
  • Repository transfer is an instance-administration operation; it requires an administrator holding the admin:repo_transfer admin scope and is gated behind the transfer.enabled setting.

Endpoints

Method Path Summary
GET /api/v1/repos List repositories the caller can see
GET /api/v1/repos/{owner}/{repo} Fetch a repository
POST /api/v1/repos Create a repository
PATCH /api/v1/repos/{owner}/{repo} Update a repository
DELETE /api/v1/repos/{owner}/{repo} Delete a repository
GET /api/v1/repos/{owner}/{repo}/contents/{path} Read a file or directory listing at a ref
GET /api/v1/repos/{owner}/{repo}/raw/{ref}/{path} Download raw file bytes
GET /api/v1/repos/{owner}/{repo}/blame/{ref}/{path} Line-by-line blame for a file
GET /api/v1/repos/{owner}/{repo}/branches List branches (paginated)
POST /api/v1/repos/{owner}/{repo}/branches Create a branch
DELETE /api/v1/repos/{owner}/{repo}/branches/{branch} Delete a branch
GET /api/v1/repos/{owner}/{repo}/tags List tags (paginated)
POST /api/v1/repos/{owner}/{repo}/tags Create a tag
DELETE /api/v1/repos/{owner}/{repo}/tags/{tag} Delete a tag
GET /api/v1/repos/{owner}/{repo}/collaborators List collaborators
PUT /api/v1/repos/{owner}/{repo}/collaborators/{user} Add or update a collaborator
GET /api/v1/repos/{owner}/{repo}/collaborators/{user}/permissions Inspect a collaborator's effective permissions
DELETE /api/v1/repos/{owner}/{repo}/collaborators/{user} Remove a collaborator
POST /api/v1/admin/repos/{owner}/{repo}/transfer/preflight Preview a repository transfer
POST /api/v1/admin/repos/{owner}/{repo}/transfer Start a repository transfer
GET /api/v1/admin/transfers List repository transfers (paginated)
GET /api/v1/admin/transfers/{id} Fetch one repository transfer

GET /api/v1/repos

List repositories visible to the caller, most recently updated first. Unauthenticated callers see public repositories only; authenticated callers also see internal repositories. This endpoint returns a plain JSON array (not the page envelope) and is capped server-side.

Query parameters

Name Type Default Description
mine boolean false When true, return only repositories owned by the caller (requires authentication). Capped at 100.
owner string Restrict the listing to one owner's repositories visible to the caller. Capped at 50.

With neither parameter the listing is the instance-wide visible set, capped at 50.

Response

[
  {
    "id": "9f1c2e7a-...",
    "owner": "alice",
    "owner_id": "3b8e...",
    "name": "widgets",
    "description": "Widget service",
    "is_private": false,
    "visibility": "public",
    "default_branch": "main",
    "clone_url_http": "https://api.gitvetrix.com/alice/widgets.git",
    "clone_url_ssh": "git@gitvetrix.com:alice/widgets.git",
    "created_at": "2026-01-04T12:00:00Z",
    "updated_at": "2026-02-19T09:31:00Z"
  }
]

Status codes

Status When
200 OK Listing returned.
401 Unauthorized mine=true without a valid session.

Example

curl -H "Authorization: Bearer <token>" \
  "https://api.gitvetrix.com/api/v1/repos?mine=true"

GET /api/v1/repos/{owner}/{repo}

Fetch a single repository's metadata. Subject to the visibility tier.

Path parameters

Name Type Description
owner string Owner username.
repo string Repository name.

Response

{
  "id": "9f1c2e7a-...",
  "owner": "alice",
  "owner_id": "3b8e...",
  "name": "widgets",
  "description": "Widget service",
  "is_private": false,
  "visibility": "public",
  "default_branch": "main",
  "issue_code": "WIDG",
  "clone_url_http": "https://api.gitvetrix.com/alice/widgets.git",
  "clone_url_ssh": "git@gitvetrix.com:alice/widgets.git",
  "stars_count": 12,
  "starred": false,
  "forks_count": 0,
  "watchers_count": 3,
  "watching": false,
  "open_issues_count": 5,
  "open_prs_count": 1,
  "created_at": "2026-01-04T12:00:00Z",
  "updated_at": "2026-02-19T09:31:00Z"
}

Key fields: visibility is the canonical tier and is_private its deprecated mirror; issue_code is the per-repository project key used to number issues; clone_url_http and clone_url_ssh are rendered from the instance's configured external URLs; starred and watching reflect the calling user's own state and are always false for anonymous callers.

The response carries an ETag and Cache-Control: private, must-revalidate, max-age=0. A request whose If-None-Match matches the current entity is answered 304 Not Modified with no body.

Status codes

Status When
200 OK Repository returned.
304 Not Modified If-None-Match matches the current ETag.
404 Not Found Repository does not exist, or is private and not readable — see Errors.

Example

curl https://api.gitvetrix.com/api/v1/repos/alice/widgets

POST /api/v1/repos

Create a repository owned by the authenticated user.

Request body

Field Type Required Description
name string yes Repository name.
description string no Free-text description.
visibility string no public, internal, or private.
is_private boolean no Deprecated shim: true maps to private, false to public. Ignored when visibility is set.
default_branch string no Initial branch name. Defaults to main.

Visibility is secure-by-default: when neither visibility nor is_private is supplied the repository is created private. An explicit visibility always wins over is_private.

{
  "name": "widgets",
  "description": "Widget service",
  "visibility": "internal",
  "default_branch": "main"
}

Response

201 Created with the repository record (the same shape as the fetch response above).

Status codes

Status When
201 Created Repository created.
400 Bad Request Invalid body, or name is missing.
401 Unauthorized No valid session.
409 Conflict A repository with that name already exists for the owner.

Example

curl -X POST -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"widgets","visibility":"internal"}' \
  https://api.gitvetrix.com/api/v1/repos

PATCH /api/v1/repos/{owner}/{repo}

Update repository metadata. Restricted to the owner or an instance administrator. Every field is optional; only the fields supplied are changed.

Path parameters

Name Type Description
owner string Owner username.
repo string Repository name.

Request body

Field Type Description
name string New name. Renaming moves the repository's storage in lockstep.
description string New description.
visibility string public, internal, or private.
is_private boolean Deprecated shim; derives visibility when visibility is absent.
default_branch string New default branch.
issue_code string Project key: 2–10 uppercase alphanumerics starting with a letter, or empty to clear.
{
  "visibility": "private",
  "issue_code": "WIDG"
}

Response

200 OK with the updated repository record.

Status codes

Status When
200 OK Repository updated.
400 Bad Request Invalid body, an unrecognized visibility, or a malformed issue_code.
401 Unauthorized No valid session.
403 Forbidden Caller is neither the owner nor an instance administrator.
404 Not Found Repository does not exist, or is private and not readable.
409 Conflict The new name is already in use, or the issue_code is already taken by another repository. A name collision returns { "error": "name_in_use", "existing_repo_id": "<uuid>" }.

Example

curl -X PATCH -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"visibility":"private"}' \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets

DELETE /api/v1/repos/{owner}/{repo}

Delete a repository and its git storage. Restricted to the owner or an instance administrator. The request body must confirm the full owner/repo slug exactly (case-sensitive) to guard against deleting the wrong repository.

Path parameters

Name Type Description
owner string Owner username.
repo string Repository name.

Request body

{ "confirmation": "alice/widgets" }

Status codes

Status When
204 No Content Repository deleted.
400 Bad Request Body missing, or confirmation does not equal <owner>/<repo> exactly.
401 Unauthorized No valid session.
403 Forbidden Caller is neither the owner nor an instance administrator.
404 Not Found Repository does not exist, or is private and not readable.

Example

curl -X DELETE -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"confirmation":"alice/widgets"}' \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets

GET /api/v1/repos/{owner}/{repo}/contents/{path}

Read what lives at path in the repository at a ref. A directory returns a JSON array of entries; a file returns a single blob object. Omit path (or use the bare /contents form) to read the repository root.

Path parameters

Name Type Description
owner string Owner username.
repo string Repository name.
path string Path within the tree. Empty for the repository root.

Query parameters

Name Type Default Description
ref string HEAD Branch, tag, or commit SHA to read from.

Response

A directory listing:

[
  {
    "name": "README.md",
    "path": "README.md",
    "type": "file",
    "size": 1024,
    "mode": "100644",
    "last_commit_message": "Add README",
    "last_commit_date": "2026-02-19T09:31:00Z"
  }
]

A file blob:

{
  "path": "README.md",
  "encoding": "utf-8",
  "content": "# Widgets\n...",
  "is_binary": false,
  "lang": "markdown",
  "size": 1024
}

The response carries an ETag; a matching If-None-Match is answered 304 Not Modified.

Status codes

Status When
200 OK Directory listing or file blob returned.
304 Not Modified If-None-Match matches the current ETag.
404 Not Found Repository not readable, or no such path at the ref.

Example

curl "https://api.gitvetrix.com/api/v1/repos/alice/widgets/contents/src?ref=main"

GET /api/v1/repos/{owner}/{repo}/raw/{ref}/{path}

Serve a file's raw bytes with a content type derived from its extension. Binary files are sent with Content-Disposition: attachment; X-Content-Type-Options: nosniff is always set.

Path parameters

Name Type Description
owner string Owner username.
repo string Repository name.
ref string Branch, tag, or commit SHA.
path string File path within the tree.

Status codes

Status When
200 OK File bytes returned.
404 Not Found Repository not readable, or no such file at the ref.

Example

curl https://api.gitvetrix.com/api/v1/repos/alice/widgets/raw/main/README.md

GET /api/v1/repos/{owner}/{repo}/blame/{ref}/{path}

Return per-line blame for a file: each line with the commit and author that last changed it.

Path parameters

Name Type Description
owner string Owner username.
repo string Repository name.
ref string Branch, tag, or commit SHA.
path string File path within the tree.

Response

[
  {
    "line_number": 1,
    "content": "# Widgets",
    "sha": "a1b2c3d4...",
    "author_name": "Alice",
    "author_email": "alice@example.com",
    "author_date": "2026-01-04T12:00:00Z"
  }
]

Status codes

Status When
200 OK Blame returned.
404 Not Found Repository not readable, or the file or ref does not exist.

Example

curl https://api.gitvetrix.com/api/v1/repos/alice/widgets/blame/main/README.md

GET /api/v1/repos/{owner}/{repo}/branches

List branches, paginated. Subject to the visibility tier: a private repository requires read access (401 for anonymous callers; 404 for an authenticated non-member), and an internal repository requires authentication.

Query parameters

Name Type Default Description
page integer 1 See Pagination.
per_page integer 25 Items per page, clamped to a maximum of 100.
include_divergence boolean false When true, compute each branch's ahead/behind counts relative to the default branch. The default listing leaves these at 0.
sort string One of name, last_commit_at, ahead, behind.
order string asc asc or desc. Only honored alongside sort.

Response

{
  "items": [
    {
      "name": "main",
      "commit_sha": "a1b2c3d4...",
      "commit_message": "Add README",
      "commit_author": "Alice",
      "commit_date": "2026-02-19T09:31:00Z",
      "is_default": true,
      "is_protected": true,
      "ahead_count": 0,
      "behind_count": 0
    }
  ],
  "total": 7,
  "page": 1,
  "per_page": 25
}

ahead_count and behind_count are 0 unless include_divergence=true. The response carries an ETag derived from the branch tips; a matching If-None-Match is answered 304 Not Modified.

Status codes

Status When
200 OK Page returned.
304 Not Modified If-None-Match matches the current ETag.
400 Bad Request Invalid sort or order.
401 Unauthorized Anonymous request against a private repository.
404 Not Found Repository not readable.

Example

curl "https://api.gitvetrix.com/api/v1/repos/alice/widgets/branches?per_page=50"

POST /api/v1/repos/{owner}/{repo}/branches

Create a branch. Requires repository write access.

Request body

Field Type Required Description
name string yes New branch name.
base_ref string no Branch or commit SHA to branch from. Defaults to the repository's default branch.
{ "name": "feature/x", "base_ref": "main" }

Response

{ "name": "feature/x", "base_ref": "main" }

Status codes

Status When
201 Created Branch created.
400 Bad Request Invalid body, missing name, or an invalid base ref.
401 Unauthorized No valid session.
403 Forbidden Caller lacks write access.
404 Not Found Repository not readable.

Example

curl -X POST -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"feature/x","base_ref":"main"}' \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets/branches

DELETE /api/v1/repos/{owner}/{repo}/branches/{branch}

Delete a branch. Requires repository write access. The default branch cannot be deleted, and a branch matching a protected-branch rule is refused. Open merge requests that target the branch are closed as a side effect. Percent-encode / in branch names as %2F.

Path parameters

Name Type Description
owner string Owner username.
repo string Repository name.
branch string Branch name (the path after /branches/).

Status codes

Status When
204 No Content Branch deleted.
400 Bad Request The branch is the repository's default branch.
401 Unauthorized No valid session.
403 Forbidden Caller lacks write access, or the branch is protected.
404 Not Found Repository or branch not found.
429 Too Many Requests The per-actor branch-delete rate limit was exceeded — see Rate limits.
503 Service Unavailable The audit record for the deletion could not be written. The audit row is committed before the branch is dropped, so a failed write refuses the delete rather than letting it succeed unaudited.

Example

curl -X DELETE -H "Authorization: Bearer <token>" \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets/branches/feature%2Fx

GET /api/v1/repos/{owner}/{repo}/tags

List tags, paginated. Subject to the same visibility enforcement as the branch list.

Query parameters

Name Type Default Description
page integer 1 See Pagination.
per_page integer 25 Items per page, clamped to a maximum of 100.

Response

{
  "items": [
    {
      "name": "v1.0.0",
      "commit_sha": "a1b2c3d4...",
      "message": "Release 1.0.0",
      "tagger_name": "Alice",
      "tagger_email": "alice@example.com",
      "tagged_at": "2026-01-04T12:00:00Z",
      "is_annotated": true
    }
  ],
  "total": 3,
  "page": 1,
  "per_page": 25
}

Status codes

Status When
200 OK Page returned.
401 Unauthorized Anonymous request against a private repository.
404 Not Found Repository not readable.

Example

curl "https://api.gitvetrix.com/api/v1/repos/alice/widgets/tags"

POST /api/v1/repos/{owner}/{repo}/tags

Create a tag. Requires repository write access. An empty message creates a lightweight tag; a non-empty message creates an annotated tag.

Request body

Field Type Required Description
name string yes Tag name.
ref string no Branch, commit SHA, or existing tag to point at. Defaults to the default branch.
message string no Annotation message. Empty for a lightweight tag.
{ "name": "v1.0.0", "ref": "main", "message": "Release 1.0.0" }

Response

{ "name": "v1.0.0", "ref": "main" }

Status codes

Status When
201 Created Tag created.
400 Bad Request Invalid body, missing name, or an invalid ref.
401 Unauthorized No valid session.
403 Forbidden Caller lacks write access.
404 Not Found Repository not readable.
409 Conflict A tag with that name already exists.

Example

curl -X POST -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"v1.0.0","ref":"main","message":"Release 1.0.0"}' \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets/tags

DELETE /api/v1/repos/{owner}/{repo}/tags/{tag}

Delete a tag. Requires repository write access. Percent-encode / in tag names as %2F.

Path parameters

Name Type Description
owner string Owner username.
repo string Repository name.
tag string Tag name (the path after /tags/).

Status codes

Status When
204 No Content Tag deleted.
401 Unauthorized No valid session.
403 Forbidden Caller lacks write access.
404 Not Found Repository or tag not found.

Example

curl -X DELETE -H "Authorization: Bearer <token>" \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets/tags/v1.0.0

GET /api/v1/repos/{owner}/{repo}/collaborators

List a repository's collaborators with their role and effective permissions. Requires repository read access; a private repository resolves membership-only, so an authenticated non-member receives 404. Returns a JSON array.

Response

[
  {
    "user": {
      "id": "3b8e...",
      "username": "bob",
      "display_name": "Bob",
      "avatar_url": "/user-content/.../avatar.jpg"
    },
    "role": "write",
    "permissions": ["repo:read", "repo:write"],
    "created_at": "2026-02-01T08:00:00Z"
  }
]

The short role names are read, triage, write, maintain, and admin.

Status codes

Status When
200 OK Collaborator list returned.
404 Not Found Repository not readable.

Example

curl -H "Authorization: Bearer <token>" \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets/collaborators

PUT /api/v1/repos/{owner}/{repo}/collaborators/{user}

Add a collaborator or change an existing one's role. Permitted to the repository owner, an instance administrator, a collaborator holding the admin role on the repository, or a caller with the repo_roles admin scope.

Supply either an explicit role (with optional permissions) or a role_template_id to snapshot a role template's permissions onto the collaborator.

Path parameters

Name Type Description
user string Username of the collaborator to add or update.

Request body

Field Type Description
role string Role to assign: read, triage, write, maintain, admin, or a custom role.
permissions string[] Explicit permission list for a custom role.
role_template_id string UUID of a role template to snapshot. Mutually exclusive with role.
{ "role": "write" }

Status codes

Status When
204 No Content Collaborator added or updated.
400 Bad Request Invalid JSON, an unknown role, or a malformed role_template_id.
401 Unauthorized No valid session.
403 Forbidden Caller may not manage collaborators, or the role template belongs to another repository.
404 Not Found Repository, target user, or role template not found.
503 Service Unavailable A role_template_id was supplied but role templates are not configured on this deployment.

Example

curl -X PUT -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"role":"write"}' \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets/collaborators/bob

GET /api/v1/repos/{owner}/{repo}/collaborators/{user}/permissions

Return one collaborator's resolved access. Requires repository read access.

Path parameters

Name Type Description
user string Collaborator username.

Response

{
  "role": "repo_write",
  "permissions": ["repo:read", "repo:write"],
  "source": "role",
  "role_template_id": "f0e1..."
}

source is role, template, or custom. role_template_id is present only when the access was snapshotted from a role template.

Status codes

Status When
200 OK Effective permissions returned.
404 Not Found Repository not readable, the user does not exist, or the user is not a collaborator.

Example

curl -H "Authorization: Bearer <token>" \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets/collaborators/bob/permissions

DELETE /api/v1/repos/{owner}/{repo}/collaborators/{user}

Remove a collaborator. Restricted to the repository owner or an instance administrator.

Path parameters

Name Type Description
user string Collaborator username.

Status codes

Status When
204 No Content Collaborator removed.
401 Unauthorized No valid session.
403 Forbidden Caller is neither the owner nor an instance administrator.
404 Not Found Repository or target user not found.

Example

curl -X DELETE -H "Authorization: Bearer <token>" \
  https://api.gitvetrix.com/api/v1/repos/alice/widgets/collaborators/bob

POST /api/v1/admin/repos/{owner}/{repo}/transfer/preflight

Preview a repository transfer to another owner without changing anything. Instance-administration: requires an administrator with the repo_transfer admin scope, and returns 404 when the transfer.enabled setting is off.

Request body

{ "target_username": "carol" }

Response

{
  "target_exists": true,
  "source_exists": true,
  "name_collision_at_target": false,
  "collaborators_to_drop": [],
  "group_grants_to_drop": []
}

collaborators_to_drop and group_grants_to_drop list the access entries that the transfer would remove. in_flight_transfer and existing_colliding_repo_id appear only when relevant.

Status codes

Status When
200 OK Preflight result returned.
400 Bad Request Missing or unknown body fields, or an empty target_username.
401 Unauthorized No valid session.
404 Not Found Source repository or target user not found, or the feature is disabled.
409 Conflict The repository name already exists under the target owner.
412 Precondition Failed A precondition is unmet, such as no configured backup destination.
403 Forbidden Caller lacks the admin:repo_transfer admin scope.

Example

curl -X POST -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"target_username":"carol"}' \
  https://api.gitvetrix.com/api/v1/admin/repos/alice/widgets/transfer/preflight

POST /api/v1/admin/repos/{owner}/{repo}/transfer

Start a repository transfer. The work runs asynchronously; the response returns the transfer's id and initial state, and progress is observed through the transfer history endpoints. Requires the admin:repo_transfer admin scope and the transfer.enabled setting. confirm_repo_name must match the repository name.

Request body

{ "target_username": "carol", "confirm_repo_name": "widgets" }

Response

{ "transfer_id": "d4c3...", "state": "queued" }

Status codes

Status When
202 Accepted Transfer started; poll the history endpoints for terminal state.
400 Bad Request Missing or unknown body fields, or confirm_repo_name does not match.
401 Unauthorized No valid session.
404 Not Found Source repository or target user not found, or the feature is disabled.
409 Conflict A transfer for the same source repository is already in flight.
403 Forbidden Caller lacks the admin:repo_transfer admin scope.

Example

curl -X POST -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"target_username":"carol","confirm_repo_name":"widgets"}' \
  https://api.gitvetrix.com/api/v1/admin/repos/alice/widgets/transfer

GET /api/v1/admin/transfers

List repository transfers, most recent first, paginated. Requires the admin:repo_transfer admin scope and the transfer.enabled setting.

Query parameters

Name Type Default Description
page integer 1 See Pagination.
per_page integer 25 Items per page, clamped to a maximum of 100.
target_user string Filter by target owner username (case-insensitive). An unknown username yields an empty page.
state string Filter by transfer state. A malformed value returns 400.

Response

{
  "items": [
    {
      "transfer_id": "d4c3...",
      "source_user_id": "3b8e...",
      "target_user_id": "7a21...",
      "source_repo_id": "9f1c...",
      "state": "completed",
      "created_at": "2026-02-19T09:31:00Z",
      "completed_at": "2026-02-19T09:33:00Z"
    }
  ],
  "total": 1,
  "page": 1,
  "per_page": 25
}

Status codes

Status When
200 OK Page returned.
400 Bad Request Invalid state.
404 Not Found The feature is disabled.
403 Forbidden Caller lacks the admin:repo_transfer admin scope.

Example

curl -H "Authorization: Bearer <token>" \
  "https://api.gitvetrix.com/api/v1/admin/transfers?state=completed"

GET /api/v1/admin/transfers/{id}

Fetch one transfer's full record, including backup paths and the manifest summary. Requires the admin:repo_transfer admin scope and the transfer.enabled setting.

Path parameters

Name Type Description
id string UUID of the transfer.

Status codes

Status When
200 OK Transfer returned.
400 Bad Request The id is not a valid UUID.
404 Not Found No transfer with that id, or the feature is disabled.
403 Forbidden Caller lacks the admin:repo_transfer admin scope.

Example

curl -H "Authorization: Bearer <token>" \
  https://api.gitvetrix.com/api/v1/admin/transfers/d4c3...

Errors

These endpoints use the shared error envelope and status-code conventions in errors.md, including the 404-not-403 rule that hides private repositories. Codes and bodies specific to this resource:

  • A repository rename collision returns 409 with the structured body { "error": "name_in_use", "existing_repo_id": "<uuid>" }.
  • Transfer endpoints classify failures with stable error_code values, among them source_repo_not_found, target_user_not_found, name_collision_at_target, in_flight_transfer, and a 412 for an unmet precondition such as a missing backup destination. When the transfer.enabled setting is off, every transfer route answers 404.

Rate limits

These endpoints are metered under the standard scopes described in rate-limits.md: read operations under api.read and create/update/delete operations under api.write. None are metered as api.expensive.

Branch deletion carries an additional per-actor budget on top of api.write: a caller is capped at a fixed number of branch deletions per rolling window (default 30 per 5 minutes), and exceeding it returns 429 with the standard rate-limit headers.