Virtual keys live under projects, so GET /api/v1/projects/{project_id}/virtual-keys
answers for one project at a time. A screen that has to name a key anywhere in
the organization — the picker in the MCP tool group dialog, for one — would
otherwise list the projects and then issue one request per project. In an
organization with hundreds of projects that is hundreds of requests to open one
dialog.
GET /api/v1/orgs/{org_id}/virtual-keys is that list in one request.
Request#
There are no query parameters. The organization id is the only input.
Response#
An array of virtual keys, oldest first. Each is the object
GET /api/v1/projects/{project_id}/virtual-keys returns, without any digest of a
secret: there is no key_hash, and none of the previous_* fields of a rotation.
Each carries its project_id; join it to
GET /api/v1/orgs/{org_id}/projects to name the project
and its team.
The secret is never part of a listing; it is shown once, when the key is minted.
Authorization#
The virtual_key capability’s read action, the one the per-project list takes,
decided for each key at its own project. The list holds exactly the keys the
per-project list would show the caller, project by project, so asking for the
whole organization widens nothing:
- an organization reader gets every key of the organization;
- a team reader gets the keys of that team’s projects;
- a project reader gets that project’s keys;
- an account with no role anywhere inside the organization is refused with
403, and an unauthenticated one with401. A caller with a role that reaches no key gets an empty array.
A superadmin or the deployment admin token reads every key.