Who is this for? Organization Admins and security engineers who need to connect external tools, SIEM pipelines, ticketing systems, or custom automations to ContraForce without using a human user account.
Prerequisites
- Organization Admin role, or the
org:service-accounts:manageAPI scope on an existing credential - A clear understanding of the API scopes the integration needs — start with the minimum and expand as required
How Authorization Works
Authorization for service accounts is driven by API scopes on each credential. Scopes are the single source of truth for what a credential is allowed to do.- Scopes decide what — each scope (for example,
incidents:read) authorizes a specific class of API action. - Cross-workspace by default — v2 endpoints that span workspaces (such as
POST /api/v2/incidents/across-workspaces) run as scope-authorized calls and return data from every workspace the service account can see in one request. There is no need to target a single workspace per call. - Multiple credentials per account — a single service account can carry several credentials, each with a different scope set and expiration. This enables zero-downtime rotation and lets one integration hold read-only scopes while another carries write scopes.
Where to Find Service Accounts
Navigate to Settings → Developer Integrations in the ContraForce Portal. Service accounts appear in the Integrations table alongside webhooks, marked with a key icon and the type Service Account.Creating a Service Account
Open Developer Integrations
In the Portal, go to Settings → Developer Integrations and click Add Integration → Service Account.
Enter basic details
Provide a Name (up to 200 characters) and an optional Description (up to 1000 characters). Use a name that identifies the calling system — for example,
SIEM-ingest-prod or Ticketing-bridge.Select API scopes for the initial credential
Pick the scopes the first credential should carry. Scopes follow the
{resource}:{action} pattern and are grouped into Workspace Scopes (operate on workspace-owned resources such as incidents and Gamebooks) and Organization Scopes (operate on org-level resources such as users and webhooks).Optional — set credential expiration
Choose an expiration date if the credential should automatically stop working after a certain point. Leave blank for a credential that never expires.
Authenticating to the v2 API
Service accounts use HTTP Basic authentication (RFC 7617). EncodeClientId:ClientSecret in Base64 and send it in the Authorization header.
LastUsedAt) and writes an entry to the service account’s Request Logs.
Authentication failures
| Response | Likely cause |
|---|---|
401 Unauthorized | Invalid Client ID, invalid Client Secret, or malformed Authorization header |
403 Forbidden | Credential is revoked, expired, or the service account is disabled |
403 Forbidden | Request targets a v1 route (/api/... without /v2/) — service accounts are v2-only |
403 Forbidden | Authenticated but the credential is missing the scope the endpoint requires |
API Scopes Reference
Scopes are granted per credential. A service account can hold multiple credentials with different scope sets.Workspace scopes
Authorize actions against workspace-owned resources. Cross-workspace endpoints use these scopes and automatically return only data from workspaces the service account is allowed to see.| Scope | Grants |
|---|---|
incidents:read | View incidents, entities, evidence, alert rules, and comments |
incidents:write | Assign incidents, update status, and perform bulk updates |
incidents:comments | Create, update, and delete incident comments |
gamebooks:read | View Gamebooks, Gamebook history, and incident Gamebooks |
datasources:read | View connected data sources |
tickets:read | Search service tickets |
tickets:manage | Link and unlink tickets to incidents |
investigation:read | View user sign-in logs and directory logs |
Organization scopes
Authorize actions on org-level resources.| Scope | Grants |
|---|---|
webhooks:read | View webhook configurations and delivery logs |
webhooks:manage | Create, update, delete, pause, resume, and test webhooks |
org:users:read | View organization users and profiles |
org:users:manage | Add, update, and remove users |
org:users:roles | Assign and modify organizational roles |
org:service-accounts:read | View service accounts and credentials |
org:service-accounts:manage | Create, update, disable, and delete service accounts |
Write scopes imply their matching read scope. Granting
incidents:write automatically authorizes incidents:read on the same endpoint set.Managing the Service Account
Open a service account’s detail page from Settings → Developer Integrations to manage it. The page has three tabs: General, Request Logs, and Audit.General tab
- Disable — Blocks all credentials on the service account from authenticating. Use this for a temporary freeze (for example, during an incident).
- Enable — Re-activates a disabled service account.
- Delete — Permanently removes the service account and all its credentials. Cannot be undone.
- Edit — Update name and description.
Credential management
Each credential shows its prefix (first 6 characters), status, expiration, scopes, last-used timestamp, and creation date.| Action | What it does |
|---|---|
| New Credential | Issues an additional credential with its own scopes and expiration. Use for rotation or to split read vs. write integrations. |
| Revoke | Immediately invalidates a credential. Cannot be undone. |
Request Logs tab
Shows every API call made using any credential on the service account: timestamp, HTTP method, path, response status, latency, and source IP. Use this to audit integration behavior or troubleshoot403 failures.
Audit tab
Shows lifecycle events — creation, updates, credential issuance, revocation, disable/enable, and deletion — attributed to the Portal user who performed each action.Rotating a Credential (Zero Downtime)
Because a service account can hold multiple active credentials, you can rotate secrets without an outage.Issue a new credential
On the service account’s General tab, click New Credential. Select the same scopes as the credential you’re rotating and copy the new Client Secret immediately.
Deploy the new secret
Update your integration’s secret store with the new Client Secret. Deploy the configuration change.
Verify traffic on the new credential
Check Request Logs and confirm that requests are coming in. The new credential’s Last used timestamp updates within seconds of the first authenticated call.
How Service Accounts Work
- Identity — Each service account is an organization member with
IsServiceAccount = true. It is not visible in Settings → User Management and cannot sign in to the Portal. - Client ID — The stable GUID of the service account. Safe to share.
- Client Secret — 32 cryptographically random bytes, Base64-encoded. Stored as a SHA-256 hash (for authentication lookups) and as AES-256-GCM ciphertext wrapped by an RSA key in Azure Key Vault (envelope encryption). The plaintext is shown only at creation.
- Authorization — Every v2 endpoint declares a required scope. On each request, the authentication middleware resolves the credential, confirms it is active and unexpired, and projects its scopes onto the request principal. The endpoint’s scope filter then allows or denies. Endpoints that span workspaces filter returned data to the set of workspaces the service account is entitled to see.
- Isolation — Service accounts are deliberately restricted to the v2 API. The v2 design uses resource-based routing with per-request scope authorization, removing an authorization bypass that existed in v1.
Best Practices
- One service account per integration. Don’t share credentials across systems — it fragments audit trails and breaks rotation.
- Split read and write. Issue separate credentials for read-only monitoring and write automations on the same service account, so a leak of the monitoring secret can’t mutate state.
- Minimum scopes. Grant read-only scopes first. Add write scopes only when an integration actually needs to mutate state.
- Expiration everywhere. Set a credential expiration for anything non-critical and renew on a schedule.
- Name for humans. Future-you will grep the audit log.
Jira-incident-sync-prodbeatssa-3. - Monitor the Request Logs. A sudden drop in traffic usually means a rotation went wrong. A sudden spike may mean a runaway script.
Troubleshooting
| Symptom | Fix |
|---|---|
401 Unauthorized immediately after creation | Verify the Authorization header is Basic <base64(ClientId:ClientSecret)> with no whitespace |
403 Forbidden with “Service accounts must use the v2 API” | Change the URL to /api/v2/... |
403 Forbidden on a specific endpoint only | The credential is missing the required scope. Issue a new credential with the correct scope. |
403 Forbidden with “credential is not active” | The credential was revoked or expired. Issue a new credential. |
403 Forbidden with “service account is disabled or not found” | Re-enable the service account under Settings → Developer Integrations |
| Cross-workspace endpoint returns an empty list | The service account has no visible workspaces, or no data matched the filters in visible workspaces. |
| Credential works intermittently | Confirm no other integration is rotating the same credential. Use one credential per integration. |
If you have questions about service accounts or need help planning an integration, contact us at support@contraforce.com.