Skip to content

API Keys

Create keys interactively in the Forgecroft console under Settings → API keys.

To create a key programmatically:

POST /api-keys
{
"name": "CI/CD Pipeline",
"scope_type": "project",
"scope_id": "project-uuid",
"action_scope": "write"
}

Controls which resources the key can access:

Scope TypeAccess
orgAll resources in the organization
projectThe specified project and its Systems

Project-scoped keys require scope_id (the project UUID).

Controls the level of access:

Action ScopeCapabilities
readRead-only access within scope
writeRead + write (create and update resources, ingest evidence, evaluate changes)
adminFull access including member and key management

Fine-grained permissions for specific API operations:

CapabilityAllows
api_keys:readList and view API keys
api_keys:writeCreate and manage API keys
members:readView org members
members:writeManage org members
billing:readView billing status
evaluate:readEvaluate a change against Controls (the merge gate)
resolve:read / query:readRead the system map
controls:readRead Controls
evidence:readRead Evidence
propose:writeIngest evidence and propose graph changes

If no capability scopes are specified, the key is a legacy key with unrestricted capability access. Scoped keys must explicitly list each capability they need. Capability scopes go in the scopes array:

{
"name": "CI Gate",
"scope_type": "project",
"scope_id": "project-uuid",
"action_scope": "read",
"scopes": ["evaluate:read", "resolve:read"]
}

This key can evaluate changes and read the map, but cannot manage members, keys, or billing.

Use CaseScopes
CI merge gate (evaluate changes)["evaluate:read", "resolve:read"]
Evidence ingest pipeline["propose:write", "resolve:read"]
Read-only dashboard["resolve:read", "query:read", "controls:read"]
Key-management automation["api_keys:read", "api_keys:write"]

When a key has both an action scope and capability scopes, both must pass for a request to succeed:

  • action_scope: "admin" + scopes: ["api_keys:read"] = can only read API keys. The capability scopes restrict it despite the admin action scope.
  • action_scope: "read" + scopes: ["propose:write"] = cannot ingest. The action scope blocks write operations.

If scopes is empty (legacy key), only the action scope is checked.

API keys cannot create child keys with more permissions than they hold:

  • A scoped key can only create keys whose capability scopes are a subset of its own.
  • A legacy key (empty scopes) can create any type of child key.
  • A scoped key can never create a legacy (empty-scope) key, even if it holds broad scopes.
OperationEndpointNotes
CreatePOST /api-keysReturns raw key once
AuthenticateAuthorization: Bearer fc_live_...
SuspendPATCH /api-keys/{id} with {"suspended": true}Immediate rejection; reversible
ResumePATCH /api-keys/{id} with {"suspended": false}
DeleteDELETE /api-keys/{id}Permanent; cannot be undone

Suspended keys return a clear error message. Use suspension for temporary disabling without losing the key.

Expired keys return "invalid api key" (identical to a revoked key). Expiration is checked at request time, not proactively. Track expires_at in your key inventory and rotate before expiry.

Set expires_in_days at creation time. If omitted, the key never expires.

Principal TypeUse Case
orgService accounts owned by the organization (CI/CD, bots). Outlives any individual.
userKeys attributed to a specific person. Use when audit attribution matters.
teamKeys shared by a team for team-scoped tooling.

Non-admin callers can only create user-principal keys for themselves. Admins can create keys for any principal type.

Every key tracks last_used_at — the timestamp of the last successful request.

GET /api-keys

Review keys where last_used_at is null or older than 90 days. The 90-day threshold is a guideline: keys unused that long are likely orphaned from decommissioned pipelines or departed team members. Suspend them to confirm nothing breaks, then delete.

Only admins or the key creator can view a key’s full metadata via GET /api-keys/{id}.

To rotate a key without downtime:

  1. Create a new key with the same scopes
  2. Deploy the new key to your clients
  3. Monitor last_used_at on the old key until it goes stale
  4. Delete the old key
  1. Suspend immediatelyPATCH /api-keys/{id} with {"suspended": true}. Blocks the key within seconds.
  2. Audit usage — Check last_used_at and review recent activity for the affected key in the audit trail.
  3. Create a replacement — Issue a new key with the same scopes.
  4. Delete the leaked key — Once the replacement is deployed, permanently delete the old key.

Suspend first, investigate second. Suspension is instant and reversible; deletion is permanent.

EndpointDescription
POST /api-keysCreate an API key
GET /api-keysList all keys for the org (requires api_keys:read)
GET /api-keys/{id}Get a key’s metadata (admin or creator only)
PATCH /api-keys/{id}Suspend or unsuspend (requires api_keys:write)
DELETE /api-keys/{id}Revoke permanently (requires api_keys:write)
GET /whoamiVerify which key is currently authenticated