BlueForge Docs

API Keys

Manage per-project API keys. Standard keys are created by the tenant; scoped and admin keys require elevated privileges. Plaintext is returned exactly once on creation.

Endpoint

MethodPathAuthIdempotent
GET
/api/platform/projects/:id/keys
tenant Beareryes
POST
/api/platform/projects/:id/keys
tenant Bearerno (plaintext returned once)
POST
/api/platform/projects/:id/keys/scoped
admin Bearerno
POST
/api/platform/projects/:id/keys/:keyId/rotate
admin Bearerno
DELETE
/api/platform/projects/:id/keys/:keyId
admin Beareryes (204)

Parameters

NameTypeRequiredDefaultNotes
id
stringyespath parameter; project ID
name
stringyes*human label; visible in dashboard
permissions
objectnopermission manifest for the key
keyId
stringyes**path parameter for rotate/delete
scopes
string[]yes***permission scopes; body of scoped endpoint
ttlSeconds
numbernotime-to-live in seconds; scoped endpoint only

*Required for POST

/keys
(standard create). **Required for rotate and delete endpoints. ***Required for POST
/keys/scoped
.

Response

// GET /keys — List (metadata only)
{
  keys: Array<{
    id: string
    name: string
    key_prefix: string        // e.g. "bf_pk_..."
    permissions: Record<string, unknown> | null
    created_at: string
    expires_at: string | null
    revoked_at: string | null
  }>
}

// POST /keys — Create (plaintext returned ONCE)
{
  key: string                 // full plaintext key, e.g. "bf_pk_..."
  apiKey: {
    id: string
    name: string
    key_prefix: string
    permissions: Record<string, unknown> | null
    created_at: string
  }
  warning: string             // "Store this key securely — it will not be shown again"
}

// POST /keys/scoped — Create scoped key (admin Bearer)
{
  id: string
  token: string               // full plaintext token
  permissions: string[]
  expiresAt: string            // ISO 8601 or null if no TTL
}

// POST /keys/:keyId/rotate — Rotate key (admin Bearer)
{
  id: string
  token: string               // new plaintext token
  permissions: string[]
  expiresAt: string | null
}

// DELETE /keys/:keyId — Delete key (admin Bearer)
// HTTP 204 No Content (no body)

Examples

# List keys (metadata only)
curl https://api.blueforge.studio/api/platform/projects/prj_xxx/keys \
  -H "Authorization: Bearer $BF_TENANT_KEY"

# Create a standard key
curl -X POST https://api.blueforge.studio/api/platform/projects/prj_xxx/keys \
  -H "Authorization: Bearer $BF_TENANT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "ci-deploy"}'

# Create a scoped key (admin)
curl -X POST https://api.blueforge.studio/api/platform/projects/prj_xxx/keys/scoped \
  -H "Authorization: Bearer $BF_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scopes": ["read", "write"], "ttlSeconds": 3600}'

# Rotate a key (admin)
curl -X POST https://api.blueforge.studio/api/platform/projects/prj_xxx/keys/key_abc/rotate \
  -H "Authorization: Bearer $BF_ADMIN_KEY"

# Delete a key (admin) — returns 204
curl -X DELETE https://api.blueforge.studio/api/platform/projects/prj_xxx/keys/key_abc \
  -H "Authorization: Bearer $BF_ADMIN_KEY"
import { Client } from "@blueforge/client"

// List keys
const { keys } = await client.projects.keys.list("prj_xxx")

// Create key
const { key, warning } = await client.projects.keys.create("prj_xxx", { name: "ci-deploy" })
console.log("Save immediately:", key)
console.log(warning)

// Create scoped key (admin token required)
const scoped = await client.projects.keys.createScoped("prj_xxx", {
  scopes: ["read", "write"],
  ttlSeconds: 3600
})

// Rotate (admin token required)
const rotated = await client.projects.keys.rotate("prj_xxx", "key_abc")

// Delete (admin token required)
await client.projects.keys.delete("prj_xxx", "key_abc")

Pitfalls

  • Plaintext key is returned once on create. Store it in your secret manager immediately — it cannot be retrieved again.
  • There is no separate rotate endpoint for standard keys. The recommended rotation workflow is: create a new key, switch all consumers to it, then DELETE the old key.
  • The scoped key and rotate endpoints require admin Bearer authentication, not tenant Bearer.
  • DELETE returns HTTP 204 with no response body. This is idempotent — subsequent DELETE calls on the same keyId also return 204.

See also

  • projects.create — Create a new platform project (keys are provisioned on creation)
  • Key permissions framework is managed via the API Keys package; see
    @blueforge/api-keys
    for advanced permission manifests

Tested against

  • @blueforge/platform-api: 2.4.1
  • Last verified: 2026-07-15