Authentication and API keys
Send Authorization: Bearer followed by the workspace-bound secret on each request. Session cookies are not machine credentials. Current creator membership, role/action, data access and plan still apply. Organization membership alone does not grant workspace evidence access.
Scope and lifetime
Read, write and delete are separate scopes. Choose only the operations you need; read does not imply write and write does not imply delete. The available expiration choices come from the app contract: 30 days, 60 days, 90 days, 1 year, No expiry.
Secrets appear once. Metadata inventory contains fingerprints, never secrets/hashes. Owner/admin Workspace Settings handles issuance, rotation and revocation; read-only inventory does not grant management permission. Revocation is immediate. Equivalent rotation preserves scopes, creator and original expiry, with a 24-hour overlap for the old key unless revoked sooner. Deploy the replacement before the overlap ends.
A sw_test_ label does not create a sandbox: it reaches the same workspace and permissions. Use a separately controlled staging workspace for tests. The docs never executes business API requests or stores a credential.
Read API-key metadata
Operation: apiKeys.list · GET /settings/api-keys
Inspect workspace API-key prefixes, lifecycle status, expiry and exact scope strings for inventory and rotation monitoring. Requires workspace.manage and the API-key metadata read scope. The response never contains a complete secret or stored hash and cannot create, rotate or revoke a key. Browser management remains separately session-authorized. Returns the configured key list without pagination. Preserve null, unavailable and partial evidence, source provenance, confidence qualifiers and currency units; absent evidence is not zero. Dates are civil dates in the supplied IANA zone. No individual performance ranking is returned. Requires a current workspace member, this operation's exact key scope and current creator permission. Invalid filters return 400; missing or foreign resources return 404; missing permission or an effective plan restriction returns 403. Revoked or expired keys return 401; throttled requests return 429 with Retry-After.
Required key scope: api-keys:read. Current creator action: workspace.manage. Eligible plans: free, starter, growth, scale; legacy contracts: free, entry, growth. stable contract. These badges do not override current role, evidence window, quotas or target ownership.
Success statuses: 200. The JSON response is the saved/read representation. Synthetic examples below show shape, not customer evidence.
Synthetic response:
View schema or synthetic response
{
"canManage": false,
"keys": [
{
"createdAt": "2026-10-01T06:54:37.910Z",
"createdBy": "Synthetic API owner",
"environment": "test",
"expiresAt": null,
"graceUntil": null,
"id": "00000000-0000-4000-8000-000000000008",
"lastUsedAt": "2026-10-01T06:54:38.817Z",
"name": "Synthetic read contract key",
"prefix": "sw_test_EXAMPLE…",
"profileId": null,
"revokedAt": null,
"rotatedFrom": null,
"scopes": [
"command-center:read",
"forensics:read",
"scope-creep:read",
"invoice-defense:read",
"ai-economics:read",
"report-confidence:read",
"cost-model:read",
"data-sources:read",
"audit-trail:read",
"clients:read",
"usage-billing:read",
"api-keys:read"
],
"status": "active"
}
]
}
Use IDs and versions from your own preceding responses. Replace the synthetic UUIDs, dates and names in these independent examples. Set SCOPEWORTH_API_BASE and SCOPEWORTH_API_KEY only on your server.
cURL
curl --request GET "$SCOPEWORTH_API_BASE/organizations/example-org/workspaces/example-workspace/settings/api-keys" \
--header "Authorization: Bearer $SCOPEWORTH_API_KEY"JavaScript fetch
// Run on your server. API_BASE ends in /api/v1 (combined host) or /v1 (verified cell).
const response = await fetch(process.env.SCOPEWORTH_API_BASE + "/organizations/example-org/workspaces/example-workspace/settings/api-keys", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.SCOPEWORTH_API_KEY}`
},
});
if (!response.ok) throw new Error(`ScopeWorth refused request: ${response.status}`);
const result = await response.json();Python requests
import os, requests
headers = {"Authorization":"Bearer " + os.environ["SCOPEWORTH_API_KEY"]}
response = requests.request("GET", os.environ["SCOPEWORTH_API_BASE"] + "/organizations/example-org/workspaces/example-workspace/settings/api-keys", headers=headers, timeout=30)
response.raise_for_status()
result = response.json()For refusals, follow error recovery. A scope or plan badge is eligibility, not proof of authorization or available evidence. Read current directory IDs and versions before correcting a request. Keep an idempotency key for one unchanged mutation attempt; never blindly retry uncertain external work.
Mutation attempts
Send exactly one Idempotency-Key header, using a new UUID for each new intended mutation. Retain it with the exact method/path/payload. Identical successful requests can replay within the 24-hour receipt window; changed input under the same key returns 409 idempotency_conflict. Current authentication, permission, plan and target checks still apply to replay.
A stale-version conflict requires a fresh read and an explicit decision about the edit. The changed payload is a new attempt with a new key. operation_in_progress means external work may already run or persist. Do not mint another key to repeat a provider call blindly. Inspect existing outputs and retain the request ID for reconciliation. After receipt retention ends, the old key is not proof that repeating a mutation is safe. See error recovery.