Create your first key
A vk_ key authenticates each request from a package manager. The key is scoped to one project, which lives inside one tenant. To mint a key, you need the tenant and the project first. See Tenants, projects, keys for the model.
This page walks the admin through creating all three for a new developer. There are two paths: the dashboard UI (easier, what most operators do) and the JSON admin API (scriptable, useful for CI provisioning).
Path 1 — Dashboard UI
Section titled “Path 1 — Dashboard UI”- Sign in to the dashboard at
https://vg-admin.<your-domain>/admin/uiwith your admin credentials. - Create a tenant (one per customer). Click New organization, enter a slug + display name. The slug is the URL-safe identifier that shows up in audit log queries and ingress routing.
- Create a project inside that tenant. Open the tenant detail page → Projects tab → New project. The project is typically one-per-repo or one-per-pipeline.
- Mint a key. Open the project detail page → API keys tab → New key. Upwarden surfaces the
vk_…string once; copy it into your secret store immediately. You cannot retrieve it later — only revoke + re-mint.
Path 2 — JSON admin API
Section titled “Path 2 — JSON admin API”If you’re provisioning programmatically (CI/CD seeding a new customer, scripted migration, etc.), the same three steps map to three POST calls under /api/v1/admin/. Authenticate every call with x-upwarden-admin-token: $ADMIN_API_TOKEN.
# 1. Create the tenantcurl -X POST "https://vg-admin.<your-domain>/api/v1/admin/orgs" \ -H "x-upwarden-admin-token: $ADMIN_API_TOKEN" \ -H "content-type: application/json" \ -d '{ "slug": "acme", "displayName": "Acme Inc." }'
# 2. Create the project under that tenantcurl -X POST "https://vg-admin.<your-domain>/api/v1/admin/orgs/acme/projects" \ -H "x-upwarden-admin-token: $ADMIN_API_TOKEN" \ -H "content-type: application/json" \ -d '{ "name": "frontend-build" }'# → { "project": { "id": "…", "name": "frontend-build", … } }
# 3. Mint a key, bound to that project via project_id from step 2curl -X POST "https://vg-admin.<your-domain>/api/v1/admin/orgs/acme/api-keys" \ -H "x-upwarden-admin-token: $ADMIN_API_TOKEN" \ -H "content-type: application/json" \ -d '{ "name": "ci-bot", "project_id": "<id from step 2>" }'# → { "key": "vk_…", "id": "…", "last8": "…", "projectId": "…", "createdAt": "…" }After you have the key
Section titled “After you have the key”Hand the vk_… value to the developer; they wire it into the appropriate per-ecosystem config — .npmrc for npm/Bun/pnpm/Yarn, pip.conf for PyPI, ~/.cargo/config.toml for crates, etc. The Quickstart covers each ecosystem in two lines.
The key authenticates every install request from then on. The audit log stamps apiKeyId on every row, so when something goes wrong you can trace it to a specific key (and therefore a specific project and tenant) with one WHERE apiKeyId = ....
Rotation
Section titled “Rotation”Keys don’t expire automatically. To rotate:
- Mint a new key (same project, new name).
- Roll the new key into the developer’s environment / secret store.
- Wait until the audit log shows the old key has zero traffic.
- Revoke the old key (dashboard → API keys → Revoke, or
DELETE /api/v1/admin/orgs/<slug>/api-keys/<keyId>).
If a key leaks, skip the wait — revoke immediately and let the affected installs fail loudly until the developer rolls the new value in.
What’s next
Section titled “What’s next”- Quickstart — wire the key into a package manager.
- Tenants, projects, keys — the model your CI’s topology maps onto.
- Querying the audit log — find the traffic from a specific key.