Platform

Access Control

VectorAxis organises everything into organizations and workspaces, and controls who can do what with roles. People and applications act through platform API keys (va_…), and each key’s scope and role decide exactly which features and actions it can reach. This page covers the model end-to-end: the hierarchy, the roles, how to create a key for each role, the full permission matrix, and the developer API for every resource.

The hierarchy

An organization is the billing & identity boundary. Inside it, workspaces are isolated environments (think dev and prod, or one per team or customer), and every resource lives in a workspace.

text
Organization
  ├─ Workspace A  (dev)
  └─ Workspace B  (prod)
       ├─ Virtual keys
       ├─ Prompts
       ├─ Routing configs
       └─ Guardrails
Two kinds of key: don’t mix them up
KeyWhat it is
va_… platform API keyYour identity & permissions. Authenticates to the management and inference APIs and decides what you may do. Carries a scope + role. This page.
vk-… virtual keyA safe stand-in for a provider credential, used as the api_key on inference requests. Holds no management permissions. See Virtual Keys.
Dashboard users sign in with a Cognito session (Google or email/password); that session is used for the console. For machine-to-machine and API access, use a va_… platform key as Authorization: Bearer va_…. Inference endpoints additionally accept a virtual key directly. (Not to be confused with the PLATFORM credit mode for virtual keys; see Platform Keys.)
Scope & roles: the two dials

When you create a platform key (or invite a person) you choose a scope (how wide it reaches) and a role (how much it can do within that reach).

ScopeReachesCarries a…
orgThe whole organization: every workspace and all org-level settings.an organization role (owner / admin / member)
workspaceA single workspace and the resources inside it.a workspace role (admin / member)
RoleIn plain terms
owner orgEverything an admin can do, plus money & lifecycle: subscriptions, credits, and deleting the organization.
admin orgRuns the org: manage workspaces, members, and platform keys; full control of every workspace’s resources.
member orgRead-only at the org level. Has no access to a workspace unless separately added to it.
admin workspaceFull control of one workspace: create & manage its keys, prompts, configs, guardrails, and members.
member workspaceCan view a workspace’s resources and make inference calls, but can’t create or change them.
Org admins are workspace admins everywhere. An owner or org admin automatically has admin rights in every workspace, with no need to be added to each. An org member, by contrast, gets no workspace access until they’re explicitly added to a workspace with a workspace role.
Creating a platform key in the dashboard

Open API Keys and choose Create key. You’ll set:

  • Name. A label so you can recognise the key later (e.g. “CI pipeline”, “Eng workspace admin”).
  • Scope. org for an organization-wide key, or workspace to confine it to one workspace.
  • Role. admin or member. For an org-scoped key that level applies across every workspace; for a workspace key it applies within that one workspace. This is what grants the permissions in the matrix below. (A key never carries the org owner role; owner is a person-only membership role for billing & lifecycle.)
  • Expiry (optional). A date after which the key stops working.
The raw key is shown once. On create you get the full va_… secret back a single time, so copy it then. Afterwards only a 4-character hint is stored, so it can never be retrieved again. Lost it? Revoke and create a new one. Only an org admin (or, for a workspace-scoped key, that workspace’s admin) can create or revoke keys.

What each role can do

full = create, edit, and delete · view = read & use only · — = no access.

Inside a workspace

These act on resources that live in a workspace. Org owners and admins have admin here in every workspace automatically.

Feature / actionWorkspace adminWorkspace member
Virtual keys: create / edit / deletefull—
Virtual keys: view & usefullview
Prompts: create / edit / delete / publishfull—
Prompts: view & runfullview
Routing configs: create / edit / deletefull—
Routing configs: viewfullview
Guardrails: create / edit / delete / enablefull—
Guardrails: viewfullview
Workspace members: invite / change role / removefull—
Workspace members: viewfullview
Logs & analytics: viewfullview
Make inference calls (chat, prompts)fullfull
The classic example: a workspace member can read a prompt and call it, but cannot create or edit one: that takes a workspace admin. The same split applies to virtual keys, routing configs, and guardrails.
Across the organization
Feature / actionOrg ownerOrg adminOrg member
Workspaces: createfullfull—
Workspaces: view (list)fullfullview
Org members: invite / change role / removefullfull—
Org members: viewfullfullview
Platform API keys: create / revokefullfull—
Platform API keys: view (list)fullfullview
Logs: exportfullfull—
Billing & subscription: viewfullfullview
Credits: buy / withdraw / auto-rechargefull——
Subscription: change plan / checkout / portalfull——
Delete the organizationfull——
Money is owner-only. Anything that spends or moves money (buying or withdrawing credits, changing the subscription) is restricted to org owners, even though admins run everything else. A workspace-scoped key’s admin can also create/revoke keys and edit/delete its own workspace, but can’t touch org-level settings.

Developer API reference

Authenticate every call with Authorization: Bearer va_…. Management endpoints live under /v1. Each resource lists its endpoints with the role required, then the create payload and response. Required fields are marked *. For field-by-field detail, see each resource’s own page: virtual keys, routing configs, guardrails.

Virtual keys
MethodPathWho can call it
POST/v1/virtual-keysWorkspace admin
GET/v1/virtual-keysWorkspace member
GET/v1/virtual-keys/{slug}Workspace member
PUT/v1/virtual-keys/{slug}Workspace admin
DELETE/v1/virtual-keys/{slug}Workspace admin
POST/v1/virtual-keys/{slug}/disableWorkspace admin
POST/v1/virtual-keys/{slug}/enableWorkspace admin

Create payload * = required:

json
{
  "name": "OpenAI Production",            // *
  "organization": "acme",                 // *
  "workspace_id": "<workspace-uuid>",
  "credential_mode": "BYOK",              // BYOK | PLATFORM
  "credentials": [
    { "provider": "OPENAI", "key": "sk-..." }
  ],
  "model_allowlist": ["gpt-4o", "gpt-4o-mini"],
  "rate_limit_rpm": 100,
  "credit_limit_usd": 50.0,
  "credit_reset_policy": "MONTHLY",
  "expires_at": "2026-12-31T00:00:00Z"
}

Create response. The slug is what you use as an api key:

json
{ "slug": "vk-1a2b3c4d5e6f7a8b", "key_hint": "...abcd" }
Routing configs
MethodPathWho can call it
POST/v1/configsWorkspace admin
GET/v1/configsWorkspace member
GET/v1/configs/{slug}Workspace member
PUT/v1/configs/{slug}Workspace admin
DELETE/v1/configs/{slug}Workspace admin
POST/v1/configs/validateAny member
GET/v1/configs/{slug}/audit-logWorkspace member
GET/v1/configs/{slug}/analyticsWorkspace member
json
{
  "name": "Premium router",               // *
  "organization": "acme",                 // *
  "workspace_id": "<workspace-uuid>",
  "strategy_mode": "FALLBACK",            // * SINGLE | LOADBALANCE | FALLBACK | CONDITIONAL
  "on_status_codes": [429, 500, 502, 503, 504],
  "targets": [                            // *
    { "name": "primary", "virtual_key_slug": "vk-1a2b3c4d5e6f7a8b" },
    { "name": "backup",  "virtual_key_slug": "vk-c7d4e1f2a3b95a8b" }
  ]
}

Response is the full config detail, including its slug. Reference it on requests with x-config.

Prompts
MethodPathWho can call it
POST/v1/promptsWorkspace admin
GET/v1/promptsWorkspace member
GET/v1/prompts/{slug}Workspace member
PUT/v1/prompts/{slug}Workspace admin
DELETE/v1/prompts/{slug}Workspace admin
POST/v1/prompts/{slug}/versionsWorkspace admin
GET/v1/prompts/{slug}/versionsWorkspace member
POST/v1/prompts/{slug}/versions/{n}/publishWorkspace admin

Create a prompt (the container), then add a version with the actual messages:

json
// POST /v1/prompts
{ "name": "Summarize Article", "description": "Summarizes an article",
  "organization": "acme", "workspace_id": "<workspace-uuid>" }   // name & organization required

// POST /v1/prompts/{slug}/versions
{ "messages": [
    { "role": "system", "content": "You summarize articles." },
    { "role": "user",   "content": "Summarize: {{article}}" }
  ],
  "model": "gpt-4o-mini", "temperature": 0.3 }

Run a published prompt at POST /v1/prompts/{slug}/completions (authenticated by a virtual key or routing config, like any inference call).

Guardrails
MethodPathWho can call it
POST/v1/guardrailsWorkspace admin
GET/v1/guardrailsWorkspace member
GET/v1/guardrails/{slug}Workspace member
PUT/v1/guardrails/{slug}Workspace admin
DELETE/v1/guardrails/{slug}Workspace admin
POST/v1/guardrails/{slug}/enableWorkspace admin
POST/v1/guardrails/{slug}/disableWorkspace admin
json
{
  "name": "Safety policy",                // *
  "organization": "acme",                 // *
  "workspace_id": "<workspace-uuid>",
  "enabled": true,
  "checks": [                             // * one or more checks
    { "type": "PII_DETECTOR", "target": "BOTH", "action": "REDACT" },
    { "type": "banned_words", "target": "INPUT", "action": "BLOCK",
      "config": { "words": ["foo", "bar"] } }
  ]
}

Bind guardrails to the virtual key so every request made with it is checked without the caller sending anything, or apply one per request with x-guardrail: <slug> (which adds to the key’s, never replaces them). See the guardrails page for every validator and its config.

Workspaces
MethodPathWho can call it
POST/v1/workspacesOrg admin
GET/v1/workspacesOrg member
GET/v1/workspaces/{slug}Workspace member
PUT/v1/workspaces/{slug}Workspace admin
DELETE/v1/workspaces/{slug}Workspace admin
json
{ "name": "Engineering", "organization": "acme",   // name & organization required
  "slug": "eng", "description": "Eng team workspace" }
json
{ "id": "<uuid>", "organization": "acme", "slug": "eng",
  "name": "Engineering", "created_at": "...", "updated_at": "..." }
Members
MethodPathWho can call it
GET/v1/organizations/{org}/membersOrg member
POST/v1/organizations/{org}/membersOrg admin
PUT/v1/organizations/{org}/members/{userId}Org admin
DELETE/v1/organizations/{org}/members/{userId}Org admin
GET/v1/workspaces/{slug}/membersWorkspace member
POST/v1/workspaces/{slug}/membersWorkspace admin
PUT/v1/workspaces/{slug}/members/{userId}Workspace admin
DELETE/v1/workspaces/{slug}/members/{userId}Workspace admin

Invite to the org (an org member needs a workspace to land in):

json
// POST /v1/organizations/{org}/members
{ "email": "[email protected]", "role": "member",   // email & role required
  "workspace_id": "<workspace-uuid>", "workspace_role": "member" }

// POST /v1/workspaces/{slug}/members
{ "email": "[email protected]", "role": "admin" }    // email & role required

You can invite by email before the person has ever signed in; the membership reconciles to their account on first login.

Platform API keys
MethodPathWho can call it
POST/v1/api-keysOrg admin, or workspace admin (workspace-scoped)
GET/v1/api-keysOrg member
DELETE/v1/api-keys/{keyId}Org admin, or that workspace’s admin
json
{
  "name": "CI pipeline",                  // *
  "organization": "acme",                 // *
  "scope": "workspace",                   // * org | workspace
  "role": "admin",                        // * admin | member
  "workspace_id": "<workspace-uuid>",     // required for workspace scope
  "expires_at": "2026-12-31T00:00:00Z"
}

Create response. raw_key is shown only once:

json
{ "key": { "id": "<uuid>", "name": "CI pipeline", "scope": "workspace",
           "role": "admin", "key_hint": "...wxyz", "status": "ACTIVE" },
  "raw_key": "va_DA3saInUNRHzl19hHC9p42..." }
Billing & credits
MethodPathWho can call it
GET/v1/billing/subscriptionOrg member
GET/v1/billing/creditsOrg member
GET/v1/billing/credits/transactionsOrg member
GET/v1/billing/entitlementsOrg member
POST/v1/billing/credits/purchaseOrg owner
POST/v1/billing/credits/withdrawOrg owner
PUT/v1/billing/credits/auto-rechargeOrg owner
POST/v1/billing/checkoutOrg owner
POST/v1/billing/subscription/changeOrg owner
POST/v1/billing/portalOrg owner
json
// POST /v1/billing/credits/purchase  (and /withdraw)
{ "amount_usd": 100.0 }   // amount required
Logs & analytics (read-only)
MethodPathWho can call it
GET/v1/logsMember
GET/v1/logs/{id}Workspace member
GET/v1/analytics/summaryMember
GET/v1/analytics/timeseriesMember
GET/v1/analytics/breakdownMember
POST/v1/logs/exportOrg admin
GET/v1/logs/export/{jobId}/downloadOrg admin

Scope a read to one workspace with ?workspace_id=…. Org members must scope to a workspace they belong to; org admins can read across the whole org. More on the logs page.

Quick start: create an org admin key to set up workspaces and invite people, then hand each team a workspace-scoped key: admin for the people who build keys, prompts and configs, member for those who only need to call the APIs.
NVIDIA Inception Program member

VectorAxis is built by GK Labs, a member of NVIDIA Inception.