Skip to content
OpenRelay is in early access, and the /v1 API is stable. New capabilities ship in the changelog.
GuidesGet started

Authentication

Authenticate every request with an OpenRelay API key (or_…) sent as a Bearer token. Create, rotate, and revoke keys from the dashboard or the API.

The OpenRelay API authenticates requests with an API key. Each key is bound to a single organization, and what it may do is set by its owner's role and its own restrictions (Permissions), or by its scopes in an organization that has not enabled permissions yet. Send it as a bearer token on every request:

curl https://api.openrelay.inc/v1/me \
  -H "Authorization: Bearer or_your_api_key"

New API keys are prefixed with or_; keys issued earlier start with vl_ and still work. Treat them like passwords.

The easy way: orl auth login

Using the orl CLI? Run orl auth login, paste the key once, and orl keeps it in your OS keyring and reads your organization from it. No headers to set. See CLI Authentication.

Keep keys secret

Never commit API keys to source control, embed them in client-side code, or share them in screenshots. Use environment variables or a secrets manager. If a key leaks, revoke it immediately and issue a new one.

Create an API key

From the dashboard

Go to Account → API Keys in the dashboard, create a key, and copy it. The plaintext value is shown once: store it somewhere safe.

Or via the API

With permissions enabled, only a signed-in session creates keys. Non-playground keys belong to the organization and have a fixed permission ceiling (Permissions). Without them, a key with clusters:write can mint more, and omitting scopes creates a read-and-write key (Legacy scopes). The plaintext key is returned once in the response and never again:

curl -X POST https://api.openrelay.inc/v1/orgs/{orgId}/api-keys/create \
  -H "Authorization: Bearer or_existing_key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "ci-pipeline" }'
{
  "id": "key_…",
  "name": "ci-pipeline",
  "key": "or_…",          // plaintext: shown once
  "keyPrefix": "or_abc12",
  "organizationId": "b3f9…"
}

The response includes organizationId, the org the key is bound to. Store it with the key: org-scoped endpoints take it in the path. To cap what the key may spend on inference, add a budget (Key budgets).

See Create an API key in the reference.

Using your key

Pass the key in the Authorization header as Bearer or_… on every request. Requests without a valid key receive 401 Unauthorized; a key that lacks the required scope (or targets another org) receives 403 Forbidden.

Set it once in your shell
export OPENRELAY_API_KEY="or_your_api_key"

curl https://api.openrelay.inc/v1/orgs/$ORG_ID/vms \
  -H "Authorization: Bearer $OPENRELAY_API_KEY"

Find your organization id

Org-scoped endpoints take your organization id in the path (/v1/orgs/{orgId}/...). Every API key belongs to exactly one organization, so the id is never ambiguous. Three ways to get it:

  1. Dashboard. Settings shows Organization ID under API access with a copy button. It is also shown in the reveal dialog when you create a key, and returned as organizationId in the create-key response.

  2. API. Call GET /v1/whoami with any valid key. It requires no scopes and works for every or_ key:

    curl https://api.openrelay.inc/v1/whoami \
      -H "Authorization: Bearer $OPENRELAY_API_KEY"
    {
      "principalType": "api_key",
      "organizationId": "b3f9c2a1-8d4e-4f6a-9c0b-2e7d5a1f3b8c",
      "organizationName": "Acme",
      "scopes": ["clusters:read", "clusters:write"]
    }
  3. CLI. orl account whoami prints the same information for the key you logged in with.

The organization id is an identifier, not a secret. It is safe to put in scripts, config files, and support requests.

Legacy scopes

In an organization that has not enabled permissions, and for keys created before it did, two scopes decide what a key can do on the control-plane API:

ScopeGrants
clusters:readRead access to the organization: VMs, pods, dedicated endpoints and their monitoring, usage, and the rest.
clusters:writeWrite access to the organization: create, restart, stop, and terminate VMs and pods, and create or revoke API keys.

A read-only key gets clusters:read. A key that manages VMs gets clusters:read and clusters:write. The dashboard offers these two as Read only and Read & write.

In an organization with permissions enabled, an API key can revoke only itself.

vms:read and vms:write are accepted for compatibility but grant nothing on their own: VM access comes from the clusters:* scopes. Creating a key with vms:write but not clusters:write (or vms:read but not clusters:read) returns 400.

Scopes do not gate the inference API: every active key in the organization can call it and spend the organization's balance, whatever its scopes. The inference scope is accepted but changes nothing today. The one inference restriction is inference:endpoint:<id>: a key carrying one or more of these can call only the listed dedicated endpoints, and any other model returns 404. It narrows that key; it does not stop other keys in the organization from calling the endpoint.

A control-plane request that exceeds a key's scopes returns 403. Check a key's scopes with GET /v1/whoami before debugging further.

Once your organization enables permissions, these keys keep their scopes, with four changes: they can no longer create keys (only a signed-in session can), an inference:endpoint:<id> key gets 403 model_not_allowed for other models instead of 404, your organization's guardrails and policies apply to them, and their restrictions cannot be edited. Each key keeps the restrictions it was created with; replace it to change them. A key created from then on is an organization key. A request that sends scopes gets an organization key whose ceiling matches them (Permissions).

Rotating and revoking

  • Rotate by creating a new key, deploying it, then revoking the old one.
  • Revoke instantly with DELETE /v1/orgs/{orgId}/api-keys/{id} or from the dashboard. Revocation takes effect within seconds.

Two ways to authenticate

This reference documents API key auth (or_…), which is what you'll use for automation and SDKs. The dashboard itself uses short-lived user session tokens: you don't need those to build on the API.

On this page