Docs
Search docs

Get repository details

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

getRepository

Returns the repository metadata and projected view snapshot. Authentication is optional; anonymous callers can only resolve public repositories.

Authentication is not described for this operation in the spec — that does not mean it is public. Check tokens and scopes.

curl

curl -X GET 'https://neosource.dev/api/repos/OWNER/REPO'

fetch

fetch("https://neosource.dev/api/repos/OWNER/REPO", {
  method: "GET",
});

Path parameters

ownerrequired

Repository owner or organization slug.

string

reporequired

Repository name.

string

Responses

200Repository details

application/json

RepoDetailResponse

all of
  • RepoResponse

    object

    activity_at

    integer | nullint64

    When the repo last changed, as the owner list sorts and shows it (ms since the epoch): the later of `updated_at` (a settings write) and its last push. Present only on `GET /api/owners/{handle}/repos` rows, whose statement reads it; absent (not `null`) everywhere else. Set only through [`RepoResponse::with_activity_at`].

    allowed_merge_methodsrequired

    array

    Which merge methods this repo permits at all. Never empty, and always in a canonical order (`merge` before `squash`) — it is a set, so the server normalises the order on write rather than echoing the order it was sent.

    created_atrequired

    integerint64

    created_byrequired

    string

    default_branchrequired

    string

    default_merge_methodrequired
    MergeMethod
    delete_branch_on_mergerequired

    boolean

    Whether merging a PR against this repo also deletes its source branch. `true` on a repo nobody has configured — see the settings route for why this one defaults on where the merge-method fields default to today's behaviour.

    descriptionrequired

    string

    mirror_source_url

    string | null

    mirror_status
    ownerrequired

    string

    parent
    one of
    primary_language

    string | null

    The default branch's primary language: the language with the most code lines in the stored breakdown (ADR 0105, ADR 0187). Absent until a fill under the current classification policy has run, and for a repo with no code. An open vocabulary (tokei's names), like `LanguageStat::name`.

    repo_idrequired

    string

    slugrequired

    string

    star_count

    integer | nullint64

    All-time star count. Present on exactly four routes — `GET /api/user/stars`, `GET /api/users/{handle}/stars`, `GET /api/repos?sort=trending` and `GET /api/owners/{handle}/repos` — whose store reads carry the count in the same statement. Absent (not `null`) everywhere else, including the default `GET /api/repos`: the repo detail's `stats.star_count` is the per-repo source. Set only through [`RepoResponse::with_star_count`].

    statusrequired
    RepoStatusOutput
    updated_atrequired

    integerint64

    versionrequired

    integerint32

    visibilityrequired
    RepoVisibilityInput
    workspace_idrequired

    string

  • object

    issue_policyrequired

    RepoIssuePolicy

    object

    Lightweight issue policy carried by repository detail so ordinary issue pages do not have to probe provider-specific integration endpoints.

    can_createrequired

    boolean

    Whether the API accepts native repo-bound issue creation.

    import_in_progressrequired

    boolean

    Whether imported issue metadata is currently being backfilled. Consumers that need live counters may conditionally query the provider status endpoint while this is true.

    sourcerequired
    RepoIssueSource
    languages
    one of
    • RepoLanguages

      object

      The breakdown as it rides [`crate::repo::RepoDetailResponse`]. Deliberately narrower than [`RepoLanguagesResponse`]: no `ref`, no `tree_oid`. Those exist so a standalone endpoint can say *which* answer it returned; on the detail response the repo and its default branch are already named, and the tree OID is a staleness gate the client has no use for.

      languagesrequired

      array

      The [`MAX_LANGUAGES`] largest, `code` descending then `name` ascending.

      other_coderequired

      integerint64

      Total `code` across the languages folded out by the cap, 0 if none.

      other_languagesrequired

      integerint32

      How many were folded. 0 is the flag a client renders no bucket on.

      total_coderequired

      integerint64

      Denominator across EVERY language, folded tail included.

      truncatedrequired

      boolean

      `true` when the walk hit its byte-inflation cap (ADR 0105 §7): a partial but honest count, never silently complete.

    • null

    mirror
    one of
    • RepoMirrorSummary

      object

      Upstream this repo is mirrored to (push-only). Surfaced on the overview "About" panel so a repo connected to GitHub/GitLab advertises it. The URL is credential-stripped before it reaches the wire.

      kindrequired
      RepoMirrorKind
      urlrequired

      string

    • null

    ref_policyrequired

    RepoRefPolicy

    object

    Lightweight ref-authority summary carried by repository detail so the SPA can decide whether to mount the GitHub authority context without probing `/github-relationship` on native repositories.

    sourcerequired
    RepoIssueSource
    statsrequired

    RepoStats

    object

    Whole-repo aggregate counts for the overview "About" panel. `star_count` is served count-on-read from the `repo_stars` join table; the commit/ contributor counts come from the commit-log projection.

    contributor_countrequired

    integerint64

    open_issue_countrequired

    integerint64

    Non-terminal issues on this repo (Issues tab badge).

    open_pr_countrequired

    integerint64

    Open pull requests on this repo (Pull requests tab badge).

    star_countrequired

    integerint64

    total_commitsrequired

    integerint64

    viewrequired

    ViewResponse

    object

    headsrequired

    array

    items

    string

    summaryrequired

    string

    versionrequired

    integerint64

    viewer_can_adminrequired

    boolean

    Whether the caller may administer this repo: the same `RepoAction::Admin` decision every settings route (`ExtractRepoAdmin`) enforces, asked once here so the SPA can hide the Settings tab without probing an admin route. A **UX hint only**, exactly like `OrgResponse::viewer_role` — every settings route still makes its own pass. Always `false` for anonymous callers.

    viewer_can_writerequired

    boolean

    Whether the caller may write to this repo: the same `RepoAction::Write` decision `ExtractRepoWrite` enforces. Asked because the settings area is NOT uniformly admin-gated — repo labels (`api/neosource-api-routes-collab/src/labels.rs`) and test quarantine (`api/neosource-api-routes-ci/src/quarantine.rs`) take `ExtractRepoWrite` — so a viewer with write but not admin still reaches those two pages. A **UX hint only**, like [`Self::viewer_can_admin`]; every route still makes its own pass. Always `false` for anonymous callers.

    viewer_has_starredrequired

    boolean

    Whether the authenticated caller has starred this repo. Always `false` for anonymous callers.

Standard errors

Bodies documented once for the whole API — see standard errors.

  • 400Bad Request — one of: invalid_input
  • 403Forbidden — one of: forbidden
  • 404Not Found — one of: not_found
  • 423Locked — one of: busy
  • 429Rate limited — retry after the `Retry-After` header
  • 500Internal server error
  • 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
  • 504Gateway timeout — the request exceeded the server's handling budget

Schemas

Referenced above. Listed here rather than expanded inline, so the same definition is not repeated at every level.

MergeMethod

string

How a pull request's commits land on its target branch. A repo carries two settings over this enum (`migrations/20260820120000_repo_merge_methods.sql`): the set it *permits* (`RepoRecord::allowed_merge_methods`, never empty) and the one the merge path reaches for when the request names none (`RepoRecord::default_merge_method`, always a member of that set — enforced by the settings route, which is the only place both columns are visible at once). `Default` is [`MergeMethod::Merge`] to match the column default, which is itself the pre-existing behaviour of every repo: before this setting existed, a merge always minted a two-parent commit. `Rebase` is deliberately absent rather than merely unimplemented — it replays N commits, can conflict per commit, and rewrites the SHAs the stacked-PR re-parent invariant leans on (`plans/archive/pr-merge-methods-2026-08.md` §"Not doing"). Adding it later is one `ALTER TYPE merge_method ADD VALUE` plus an arm here, which is why the stored shape is an enum array and not a pair of booleans.

"merge""squash"

RepoMirrorStatus

object

[`RepoResponse::mirror_status`]: how current a `_mirror` repository is.

last_synced_at

integer | nullint64

When the daily refresh last synced from the upstream (ms since the epoch); absent before the first sync.

latest_ci
one of
  • CommitStatusState

    string

    State of a single commit status, GitHub-shaped. `Error` is distinct from `Failure` on individual statuses (infrastructure/tooling breakage vs. a real red result) but the combined rollup folds both into `Failure`.

    "pending""success""failure""error"

  • null

RepoParentInfo

object

Summary of a fork's parent repository.

repo_idrequired

string

RepoStatusOutput

string

Repo lifecycle state surfaced by the API. Mirrors `RepoStatus`. See ADR 0012 §2.

"creating""ready""importing""import_failed"

RepoVisibilityInput

string

"public""internal""private"

RepoIssueSource

string

Where repository issue content is sourced from.

"native""github"

RepoLanguageStat

object

One language's line counts across the default branch's tip tree.

blanksrequired

integerint64

Blank lines.

coderequired

integerint64

Lines that are neither blank nor a comment.

commentsrequired

integerint64

Comment lines.

filesrequired

integerint64

Files that classified as this language. Zero for a language that only appears embedded in another (JavaScript inside an HTML `<script>`) — its lines count, but the enclosing file is one file of its own kind.

namerequired

string

tokei's language name (`Rust`, `TypeScript`, `Cpp`, …). A deliberately **open vocabulary**, not a closed-set enum: tokei owns ~150 names upstream and adds to them, and mirroring that table is the alternative ADR 0105 §Rejected already rejected.

RepoMirrorKind

string

Mirror target host kind. Mirrors `MirrorTargetKind`.

"github""gitlab""generic"