---
title: "Create a service account"
method: POST
path: "/workspaces/{workspaceId}/service-accounts"
tags: ["Service accounts"]
---

# Create a service account

`POST /workspaces/{workspaceId}/service-accounts`

## Request

- Base URL: `https://tasg.app/api/v1`
- URL: `https://tasg.app/api/v1/workspaces/{workspaceId}/service-accounts`
- Auth: HTTP bearer

Workspace owner only, max 10 per workspace. A service account is a machine identity: it authenticates only with its `tf_` tokens, cannot log in, is confined to this workspace's projects (granted here as an editor; restrict further with token scopes) and appears under its own name as the actor in activity, events and webhooks. It cannot manage tokens, memories, email preferences or create workspaces. The `tf_` plaintext is returned ONCE and never again; store it.

## Path parameters

- `workspaceId` string, uuid, required

## Request body

- object
  - `name` string, required: Actor display name, e.g. "CRM sync".
  - `project_ids` string[]: Projects (of this workspace) to grant. Can be changed later.
  - `scopes` TokenScope[]: Scopes of the first token. Default `["read","write"]`.

## Response `201`

Created, with its first token.

- object
  - `service_account` object, required
    - `id` string, uuid, required: Also the actor id this identity appears under in events, activity and audit.
    - `name` string, required: Display name: what shows up as the actor, e.g. "CRM sync" or "Reporting bot".
    - `status` 'active' | 'inactive', required
    - `projects` object[], required: Projects it can act in (as an editor; the token scopes can restrict further).
      - `id` string, uuid, required
      - `name` string, required
    - `tokens` ServiceAccountToken[], required
      - `id` string, uuid, required
      - `name` string, required
      - `scopes` TokenScope[], required
      - `lastUsedAt` string, date-time, nullable
      - `createdAt` string, date-time, required
    - `created_at` string, date-time, required
    - `token` object, required: Token metadata (camelCase keys). The tf_ plaintext appears only in the mint response.
      - `id` string, uuid, required
      - `name` string, required
      - `scopes` TokenScope[], required
      - `lastUsedAt` string, date-time, nullable
      - `createdAt` string, date-time, required
      - `plain` string, required: The `tf_` secret. Shown once.

## Other responses

- `400`: Validation failed: the body or query did not match the schema, or a business rule was violated. `error` says which.
- `401`: Missing, invalid, expired or revoked credentials.
- `403`: Authenticated, but not allowed: not a member, insufficient project role or the API token lacks the required scope.
- `429`: Rate limited. Back off and retry after the window in the `RateLimit-*` headers.

---

[API](https://skmtc.dev/tasg/apis/tasg-api.md) · [All operations](https://skmtc.dev/tasg/apis/tasg-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tasg/apis/tasg-api/revisions/cd2a1dbaf5cf?raw)
