Authentifizierung und scoped API-Keys

Scoped API-Keys (§1.5) - wie Sie Keys erstellen, der Katalog mit 27 Scopes, Scope-Hierarchie, Rotation und der /whoami-Endpoint zur Introspektion.

8 Min. Lesezeit
authenticationapi-keysscopes

Jede Anfrage an die CodeCourier-REST-API authentifiziert sich mit einem scoped Projekt-API-Key. Jeder Key trägt eine explizite Allow-Liste von einem oder mehreren Scopes (siehe Katalog unten). Der Server lehnt Anfragen, deren Scope auf dem Key nicht vorhanden ist, mit einer Antwort 403 SCOPE_DENIED im v2-Error-Envelope ab (siehe Fehler).

Einen Key erstellen

Im Dashboard: Projekteinstellungen → API-Keys → Generieren. Geben Sie dem Key einen Namen (z. B. ci-pipeline) und aktivieren Sie die benötigten Scopes. Das vollständige Secret wird genau einmal angezeigt - kopieren Sie es sofort in Ihren Secret-Manager.

Programmatische Erstellung:

curl

curl -X POST https://<your-deployment>.convex.site/api/v1/project/api-keys/generate \
  -H "Authorization: Bearer cc_live_<owner-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ci-pipeline",
    "scopes": ["runs:read", "runs:write", "workflows:read"]
  }'

TypeScript (fetch)

const res = await fetch(
  "https://<your-deployment>.convex.site/api/v1/project/api-keys/generate",
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.CC_OWNER_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "ci-pipeline",
      scopes: ["runs:read", "runs:write", "workflows:read"],
    }),
  }
);
const { data } = await res.json();
console.log(data.key); // cc_live_... - shown once

Python (requests)

import os, requests

res = requests.post(
    "https://<your-deployment>.convex.site/api/v1/project/api-keys/generate",
    headers={
        "Authorization": f"Bearer {os.environ['CC_OWNER_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "name": "ci-pipeline",
        "scopes": ["runs:read", "runs:write", "workflows:read"],
    },
)
print(res.json()["data"]["key"])  # shown once

Der Katalog mit 27 Scopes

Scopes folgen dem Muster resource:action. read umfasst list + get; write umfasst create + update + delete.

  • Projects: projects:read, projects:write
  • Workflows: workflows:read, workflows:write
  • Runs: runs:read, runs:write, runs:cancel
  • Personas: personas:read, personas:write
  • Issues: issues:read, issues:write
  • Sandboxes: sandboxes:read, sandboxes:write, sandboxes:exec
  • Contexts: contexts:read, contexts:write
  • Assets: assets:read, assets:write
  • Learnings: learnings:read, learnings:write
  • Cost Rates: cost-rates:read, cost-rates:write
  • Recurring Tasks: recurring-tasks:read, recurring-tasks:write
  • Webhooks: webhooks:read, webhooks:write
  • Team: team:read, team:write
  • Meta: * (Vollzugriff - sparsam einsetzen)

Scope-Hierarchie

  • * erfüllt jede Scope-Prüfung. Reservieren Sie diesen Scope für Owner-Level-Automatisierungen.
  • resource:write impliziert nicht resource:read. Vergeben Sie beide ausdrücklich, wenn der Aufrufer vor dem Mutieren listen muss.
  • Vor §1.5 erstellte Legacy-Keys wurden mit * übernommen - auditieren und über /whoami verschärfen.

/whoami - Key-Introspektion

GET /api/v1/whoami liefert die Identität und die aktiven Scopes des aktuellen Keys zurück. Nützlich für CI-Preflight-Checks.

curl

curl https://<your-deployment>.convex.site/api/v1/whoami \
  -H "Authorization: Bearer cc_live_..."

TypeScript

const r = await fetch(
  "https://<your-deployment>.convex.site/api/v1/whoami",
  { headers: { "Authorization": `Bearer ${key}` } }
);
const { data } = await r.json();
// { keyId, projectId, name, scopes: [...], createdAt, lastUsedAt }
if (!data.scopes.includes("runs:write")) throw new Error("scope missing");

Python

import requests
r = requests.get(
    "https://<your-deployment>.convex.site/api/v1/whoami",
    headers={"Authorization": f"Bearer {key}"},
)
data = r.json()["data"]
assert "runs:write" in data["scopes"], "scope missing"

Rotation

  1. Erzeugen Sie einen neuen Key mit denselben (oder strengeren) Scopes.
  2. Rollen Sie den neuen Key in Ihre Runtime aus; warten Sie einen vollständigen Anfragezyklus ab.
  3. POST /api/v1/project/api-keys/revoke auf dem alten Key ausführen.
  4. Bestätigen Sie, dass der widerrufene Key 401 unauthorized zurückgibt.

Auditieren Sie die Nutzung über lastUsedAt - Keys, die 90+ Tage ungenutzt sind, sollten widerrufen werden.

Verwandt