Claw GRC
/Docs
🔑

Authentication

The Claw GRC API supports two authentication modes: Firebase JWT tokens for user-context requests (from the web app or your code), and long-lived API keys for service-to-service and agent integrations.

Authentication Modes

ModeUse CaseToken Format
Firebase JWTHuman user sessions from the web dashboard or your own app. Short-lived (1 hour). Auto-refreshed by the SDK.User sessions
API KeyService accounts, CI/CD pipelines, AI agents, MCP server. Long-lived. Revocable.Service accounts

Firebase JWT Flow

When a user signs in via the Claw GRC web app (or your own integration using the Firebase SDK), Firebase issues a short-lived ID token (JWT). This token is included in the Authorization header as a Bearer token.

The API Gateway validates Firebase JWTs using Google's public keys. Validation checks the token's signature, expiry, and audience claim. Upon successful validation:

  1. The Firebase uid is resolved to a Claw GRC user ID and org ID
  2. The request is annotated with X-User-ID and X-Org-ID headers
  3. The request is forwarded to the appropriate backend service
firebase-auth-example.jsjavascript
import { getAuth } from 'firebase/auth';

const auth = getAuth();
const user = auth.currentUser;

if (user) {
  // Get the Firebase ID token (auto-refreshes every hour)
  const idToken = await user.getIdToken();
  
  const response = await fetch('https://api.clawgrc.com/api/v1/frameworks', {
    headers: {
      'Authorization': `Bearer ${idToken}`,
      'Content-Type': 'application/json',
    },
  });
  
  const frameworks = await response.json();
}

Firebase tokens expire after 1 hour

Firebase JWTs have a 1-hour TTL. Use user.getIdToken(true) to force a refresh, or rely on the Firebase SDK's automatic refresh mechanism. Don't cache tokens across requests — call getIdToken() before each API call.

API Keys

API keys are long-lived credentials for non-human callers — CI/CD pipelines, service accounts, AI agents, and the MCP server. API keys start with cgrc_live_ (production) or cgrc_test_ (test environment).

Generating an API key

  1. Navigate to Dashboard → Settings → API Keys
  2. Click Generate New Key
  3. Enter a descriptive name (e.g., "CI/CD pipeline", "Optimus agent")
  4. Select the permission scopes
  5. Optionally set an expiry date (max 1 year; never-expire is available for internal service accounts)
  6. Copy the key immediately — it won't be shown again

Store API keys securely

API keys are shown only once at creation time. Store them immediately in a secret manager (GCP Secret Manager, AWS Secrets Manager, HashiCorp Vault, or a .env file never committed to git). If you lose a key, revoke it and generate a new one.

Using an API key

# API keys are passed in the X-API-Key header
curl https://api.clawgrc.com/api/v1/frameworks   -H "X-API-Key: cgrc_live_abc123...xyz"

# The org is derived from the API key itself — no X-Org-ID header needed
# (JWT requests derive the org from the user's Firebase profile)

API key permission scopes

ScopeDescription
read:complianceRead frameworks, controls, evidence, policies, risks
write:complianceCreate and update controls, upload evidence, manage policies
read:securityRead assessments, findings, scan results
write:securityCreate findings, trigger scans, manage tickets
read:agentsView registered agents, trust scores, interaction logs
write:agentsRegister agents, submit interactions, update capabilities
read:reportsView and download generated reports
adminFull read/write access — use only for internal service accounts

Org Scoping with X-Org-ID

All Claw GRC data is scoped to an organization (org_id). The API enforces multi-tenant isolation at the database level using PostgreSQL Row-Level Security.

For Firebase JWT requests: the org is derived from the user's Firebase custom claims or looked up from the auth_identity_lookup table. The gateway injects org context automatically — you don't need to include it.

For API key requests: the org is derived from the API key itself. Each API key is scoped to a single organization at creation time. No separate X-Org-ID header is needed.

# API key requests — org scoping is derived from the key
curl https://api.clawgrc.com/api/v1/controls   -H "X-API-Key: cgrc_live_abc123..."

# JWT requests — org is derived from Firebase claims
curl https://api.clawgrc.com/api/v1/controls   -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Rate Limits

PlanRate LimitBurst
Starter120 requests/minute per org. Single API key.120 req/min
Growth600 requests/minute per org. Up to 10 API keys.600 req/min
Scale3,000 requests/minute per org. Unlimited API keys.3000 req/min
EnterpriseCustom rate limits and dedicated infrastructure.Custom

Rate limit headers are included in every response:

# Response headers
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 487
X-RateLimit-Reset: 1710420300
Retry-After: 43  # Only present when rate-limited (429 response)

Error Codes

HTTP StatusError CodeCause
400 Bad RequestVALIDATION_ERROR — Request body failed schema validation400
401 UnauthorizedINVALID_TOKEN — Bearer token is missing, malformed, or expired401
401 UnauthorizedREVOKED_KEY — API key has been revoked401
403 ForbiddenINSUFFICIENT_SCOPE — API key lacks required permission scope403
403 ForbiddenORG_MISMATCH — X-Org-ID doesn't match the key's authorized org403
404 Not FoundRESOURCE_NOT_FOUND — The requested resource doesn't exist in your org404
429 Too Many RequestsRATE_LIMIT_EXCEEDED — You've exceeded the rate limit. Check Retry-After header.429
500 Internal ErrorINTERNAL_ERROR — Unexpected server error. Contact support with request-id.500

Error response format

{
  "error": {
    "code": "INSUFFICIENT_SCOPE",
    "message": "This API key does not have the required scope: write:compliance",
    "request_id": "req_01J8X3...",
    "docs_url": "https://clawgrc.com/docs/api/authentication#error-codes"
  }
}

Include request_id when contacting support

Every API response includes a request_id in the response body and in the X-Request-ID header. Always include this when reporting API issues — it allows support to trace the exact request in our logs.

Development Mode

When the API Gateway is running with ENVIRONMENT=development, all authentication is bypassed. Every request is treated as authenticated with the default dev organization ID (00000000-0000-0000-0000-000000000001) and the owner role.

Never use development mode in production

The ENVIRONMENT=development flag disables all authentication and authorization checks. This is only for local development. Always set ENVIRONMENT=production in deployed environments.