---
title: "Find a project's vault by project_id/repo address, or list every vault in an org"
method: GET
path: "/vaults/v1"
tags: ["vault"]
---

# Find a project's vault by project_id/repo address, or list every vault in an org

`GET /vaults/v1`

## Request

- Base URL: `https://api.run402.com`
- URL: `https://api.run402.com/vaults/v1`
- Auth: one of:
  - API key in header `SIGN-IN-WITH-X`
  - HTTP bearer
  - HTTP bearer

THREE mutually-exclusive query forms; exactly one is required. (1) ?project_id= — the cold-restart lookup: an agent with no local state learns its repo_id from a project it is authorized on. (2) ?repo=<org-slug>/<name> (repo-first-onramp D6) — an alternative addressing form, resolved to a project_id before authorization runs so an unauthorized caller gets the same uniform 403 either way (authorize-before-reveal is unchanged); a slug in its release cooldown returns the typed SLUG_RELEASED refusal naming the successor slug, never a redirect. Forms (1) and (2) return the same vault record as GET /vaults/v1/{vault_id} and are never lifecycle-gated. (3) ?org_id=<uuid> (repo-surface-consolidation task 2.4) — the BULK vaults-by-org read: every vault in the org in one call, keyset-paginated over (created_at, repo_id) via ?cursor=&limit=. Kills two recorded gaps in one route: `repos list`'s client-side N+1 (list the org's projects, then read each one's vault status sequentially) and repo-first-onramp 6.1 (no bulk read existed, so repo_name needed a second call per row). Auth is ORG MEMBERSHIP (any active member, viewer role or above; platform admin also passes) rather than the project-scoped gitvault.writer bundle forms (1)/(2) use — a grant key is project-scoped and has no "list every vault in this org" concept, so a grant key is not accepted for this form. A nonexistent org_id and a real org the caller is not a member of return the identical 403 (authorize-before-reveal, unchanged). Response shape: { vaults: [{ repo_id, project_id, project_name, repo_name (address-form from internal.repo_names, null when unclaimed), org_slug (null when unclaimed), vault_policy, newest_generation, source_bytes (the BILLED per-vault figure, VAULT_BILLED_BYTES_SQL — never the raw ledger accumulator), genesis_admitted_at, created_at }], has_more, next_cursor }. Filters to live projects (deleted_at IS NULL AND archived_at IS NULL) — a deleted project's vault still counts against pooled storage forever (see the project-delete response), but does not resurface in this listing surface.

## Query parameters

- `project_id` string
- `repo` string
- `org_id` string, uuid
- `limit` integer
- `cursor` string

## Headers

- `SIGN-IN-WITH-X` string, required

## Response `200`

With project_id or repo: the vault record (see GET /vaults/v1/{vault_id}). With org_id: { vaults: [{repo_id, project_id, project_name, repo_name, org_slug, vault_policy, newest_generation, source_bytes, genesis_admitted_at, created_at}], has_more, next_cursor }.

- union
  - object: project_id / repo form: a vault record.
  - object: org_id form: a page of the org's vaults.
    - `vaults` object[]
      - `repo_id` string
      - `project_id` string
      - `project_name` string, nullable
      - `repo_name` string, nullable: Address-form name from internal.repo_names; null when unclaimed.
      - `org_slug` string, nullable: Null when unclaimed.
      - `vault_policy` 'required' | 'grandfathered', nullable
      - `storage_profile` 'managed' | 'byo': vault-byo-primary-bucket (D220). The bulk list carries this ONLY — `byo_destination` stays a single-vault-view field (GET /vaults/v1/{vault_id}).
      - `newest_generation` string, nullable
      - `source_bytes` string: The BILLED per-vault figure (floored), never the raw ledger accumulator.
      - `genesis_admitted_at` string, date-time, nullable
      - `created_at` string, date-time
    - `has_more` boolean
    - `next_cursor` string, nullable

## Other responses

- `403`: Not authorized. project_id/repo forms: VAULT_ACCESS_DENIED. org_id form: FORBIDDEN (not an active member of the org) — a nonexistent org_id and a real org the caller isn't a member of are indistinguishable.
- `404`: The project has no vault yet (project_id/repo forms only)
- `409`: The slug is released and in cooldown, naming the successor (SLUG_RELEASED)

---

[API](https://skmtc.dev/run402/apis/run402-api.md) · [All operations](https://skmtc.dev/run402/apis/run402-api/llms.txt) · [OpenAPI document](https://skmtc.dev/run402/apis/run402-api/revisions/893607557f50?raw)
