API keys, service accounts and jobs endpoints
Programmatic management of credentials and reading of long-running asynchronous jobs.
Endpoint table
API keys
| Method | Path | Permission |
|---|---|---|
| POST | /platform/organizations/{organization_id}/api-keys | member:manage |
| GET | /platform/organizations/{organization_id}/api-keys | Session |
| GET | /platform/organizations/{organization_id}/api-keys/{key_id} | Session |
| PATCH | /platform/organizations/{organization_id}/api-keys/{key_id} | member:manage |
| POST | /platform/organizations/{organization_id}/api-keys/{key_id}/revoke | member:manage |
| POST | /platform/organizations/{organization_id}/api-keys/{key_id}/rotate | member:manage |
| GET | /platform/organizations/{organization_id}/api-keys/{key_id}/usage | Session |
Service accounts
| Method | Path | Permission |
|---|---|---|
| POST | /platform/organizations/{organization_id}/service-accounts | member:manage |
| GET | /platform/organizations/{organization_id}/service-accounts | Session |
| GET | /platform/organizations/{organization_id}/service-accounts/{sa_id} | Session |
| PATCH | /platform/organizations/{organization_id}/service-accounts/{sa_id} | member:manage |
Asynchronous jobs
| Method | Path | Permission |
|---|---|---|
| GET | /platform/organizations/{organization_id}/jobs | Session |
| GET | /platform/organizations/{organization_id}/jobs/{job_id} | Session |
API keys
POST /.../api-keys
Creates a new key. The full value (raw_key) appears only once in this response — save immediately.
Request body (ApiKeyCreateRequest):
{
"name": "CI pipeline",
"description": "SOC deploy pipeline",
"scopes": ["analysis:run", "projects:read", "cases:write"],
"expires_in_days": 365,
"project_id": "prj_01H…"
}
scopes[]— accepted values (see Authentication):projects:read,projects:write,rulesets:read,rulesets:write,analysis:run,cases:read,cases:write,reviews:read,reviews:write,versions:read,versions:write,admin:*. Unknown scopes →422.expires_in_days— 1 to 3650 (10 years).nullfor no expiration.project_id— optional; if set, the key only works on the given project.
Response 201 (ApiKeyCreatedResponse):
{
"key": {
"id": "key_01H…",
"name": "CI pipeline",
"description": "SOC deploy pipeline",
"organization_id": "org_01H…",
"project_id": "prj_01H…",
"scopes": ["analysis:run", "projects:read", "cases:write"],
"key_prefix": "rfk_01H2XA9C",
"is_active": true,
"last_used_at": null,
"expires_at": "2027-04-24T00:00:00Z",
"created_by": "usr_01H…",
"created_at": "2026-04-24T15:30:00Z",
"updated_at": "2026-04-24T15:30:00Z"
},
"raw_key": "rfk_01H2XA9CKEB7WZG8RMN2KPQV7_e6c4f2abcd…"
}
Emits webhook: api_key.created.
GET /.../api-keys
Lists the organization's keys.
Response 200: array of ApiKeyRecord (without raw_key).
GET /.../api-keys/{key_id}
Fetches a specific key.
PATCH /.../api-keys/{key_id}
Partial update (name, description, scopes). Does not allow re-generating the value — use rotate for that.
POST /.../api-keys/{key_id}/revoke
Revokes the key immediately. Irreversible.
Request body (ApiKeyRevokeRequest):
{ "reason": "Manually rotated after leak" }
Response 200: ApiKeyRecord with is_active=false. Emits webhook api_key.revoked.
POST /.../api-keys/{key_id}/rotate
Generates a new secret keeping the id and scopes. The old value stops being accepted immediately.
Response 200: ApiKeyCreatedResponse (with a new raw_key — save it!).
GET /.../api-keys/{key_id}/usage
Usage history for the key (last N calls). Useful to audit where the key is being used.
Response 200: array of ApiKeyUsageRecord:
[
{
"id": "usage_...",
"key_id": "key_01H…",
"endpoint": "/api/v1/analysis/validate",
"method": "POST",
"status_code": 200,
"duration_ms": 142.7,
"request_id": "…",
"ip_address": "203.0.113.10",
"user_agent": "curl/8.4",
"created_at": "2026-04-24T14:00:00Z"
}
]
Service accounts
A service account = identity of a system (not a human) with a role inside the organization. Used as the "owner" of resources created by automated integrations — audit trail stays clear.
POST /.../service-accounts
{
"name": "CI Bot",
"description": "Robot that publishes versions from Git",
"role": "engineer"
}
Response 201: ServiceAccountRecord with slug and role.
GET /.../service-accounts
Lists service accounts.
PATCH /.../service-accounts/{sa_id}
Updates name, description, role or is_active.
Asynchronous jobs
Long-running tasks (batch logtest, Git sync, pipeline poll, secret rotation) are queued as jobs and executed in the background. The client polls the state via the endpoints below.
GET /.../jobs
Lists the organization's jobs.
Response 200: array of JobRecord:
[
{
"id": "job_...",
"organization_id": "org_...",
"project_id": "prj_...",
"type": "batch_regression",
"status": "running",
"progress": 12,
"total": 50,
"created_by": "usr_...",
"started_at": "2026-04-24T15:00:00Z",
"completed_at": null,
"error_message": null,
"created_at": "2026-04-24T14:59:58Z",
"updated_at": "2026-04-24T15:01:12Z"
}
]
type ∈ import_export.
status ∈ cancelled.
GET /.../jobs/{job_id}
Returns JobResultRecord, which is JobRecord + a result field (dictionary with the task output when completed).
Recommended polling:
import time, httpx
def wait_for_job(client, org_id, job_id, timeout=600):
deadline = time.time() + timeout
while time.time() < deadline:
r = client.get(f"{base}/platform/organizations/{org_id}/jobs/{job_id}")
r.raise_for_status()
job = r.json()
if job["status"] in ("completed", "failed", "cancelled"):
return job
time.sleep(2)
raise TimeoutError("Job took too long")
Shared structures
ApiKeyRecord
{
"id": "string",
"name": "string",
"description": "string",
"organization_id": "string",
"project_id": "string|null",
"scopes": ["string"],
"key_prefix": "rfk_XXXXXXXX",
"is_active": true,
"last_used_at": "ISO 8601|null",
"expires_at": "ISO 8601|null",
"created_by": "string|null",
"created_at": "ISO 8601",
"updated_at": "ISO 8601"
}
key_prefix is the first 12 chars of raw_key. The full secret is never exposed outside the create/rotate moment.
ApiKeyUsageRecord
{
"id": "string",
"key_id": "string",
"endpoint": "string",
"method": "string",
"status_code": 200,
"duration_ms": 123.4,
"request_id": "string|null",
"ip_address": "string|null",
"user_agent": "string|null",
"created_at": "ISO 8601"
}
JobRecord
See above. JobResultRecord = JobRecord + result: object.
Related links
- Authentication — key usage, scopes and roles.
- API keys — operational guide
- Webhooks (endpoints)