Skip to main content
Service accounts are non-human identities that your applications, scripts, and integrations use to call the ContraForce v2 API. Each service account authenticates with a Client ID and Client Secret, and every credential carries its own set of granular API scopes that determine exactly what it can do across the organization.
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:manage API scope on an existing credential
  • A clear understanding of the API scopes the integration needs — start with the minimum and expand as required
Service accounts can only call the v2 API (https://portal.contraforce.com/api/v2/...). Requests to the v1 API are rejected with 403 Forbidden.

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

1

Open Developer Integrations

In the Portal, go to Settings → Developer Integrations and click Add Integration → Service Account.
2

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.
3

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).
Follow least-privilege. Grant only the scopes the integration actually calls. You can always issue a second credential with broader scopes later.
4

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.
5

Create and capture the secret

Click Create. ContraForce returns the Client ID and a Client Secret.
The Client Secret is shown once and cannot be retrieved again. Copy it immediately into your secret store (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault, etc.). If you lose it, revoke the credential and issue a new one.

Authenticating to the v2 API

Service accounts use HTTP Basic authentication (RFC 7617). Encode ClientId:ClientSecret in Base64 and send it in the Authorization header.
curl https://portal.contraforce.com/api/v2/incidents/across-workspaces \
  -H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
  -H "Content-Type: application/json" \
  -d '{"isFirstCall": true}'
On success, ContraForce records usage metadata on the credential (LastUsedAt) and writes an entry to the service account’s Request Logs.

Authentication failures

ResponseLikely cause
401 UnauthorizedInvalid Client ID, invalid Client Secret, or malformed Authorization header
403 ForbiddenCredential is revoked, expired, or the service account is disabled
403 ForbiddenRequest targets a v1 route (/api/... without /v2/) — service accounts are v2-only
403 ForbiddenAuthenticated 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.
ScopeGrants
incidents:readView incidents, entities, evidence, alert rules, and comments
incidents:writeAssign incidents, update status, and perform bulk updates
incidents:commentsCreate, update, and delete incident comments
gamebooks:readView Gamebooks, Gamebook history, and incident Gamebooks
datasources:readView connected data sources
tickets:readSearch service tickets
tickets:manageLink and unlink tickets to incidents
investigation:readView user sign-in logs and directory logs

Organization scopes

Authorize actions on org-level resources.
ScopeGrants
webhooks:readView webhook configurations and delivery logs
webhooks:manageCreate, update, delete, pause, resume, and test webhooks
org:users:readView organization users and profiles
org:users:manageAdd, update, and remove users
org:users:rolesAssign and modify organizational roles
org:service-accounts:readView service accounts and credentials
org:service-accounts:manageCreate, 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.
Deleting a service account breaks every integration using its credentials. Disable first and monitor Request Logs for any stragglers before deleting.

Credential management

Each credential shows its prefix (first 6 characters), status, expiration, scopes, last-used timestamp, and creation date.
ActionWhat it does
New CredentialIssues an additional credential with its own scopes and expiration. Use for rotation or to split read vs. write integrations.
RevokeImmediately 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 troubleshoot 403 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.
1

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.
2

Deploy the new secret

Update your integration’s secret store with the new Client Secret. Deploy the configuration change.
3

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.
4

Revoke the old credential

Once all traffic has shifted, click Revoke on the old credential. Any residual caller using the old secret will receive 403 Forbidden.

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-prod beats sa-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

SymptomFix
401 Unauthorized immediately after creationVerify 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 onlyThe 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 listThe service account has no visible workspaces, or no data matched the filters in visible workspaces.
Credential works intermittentlyConfirm 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.