> ## Documentation Index
> Fetch the complete documentation index at: https://hyperspeed.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Service Accounts

> Create and manage service accounts for AI staff members and programmatic API access.

**Service accounts** are non-human principals that authenticate with `sa_` prefixed tokens. They appear as members in the organization and can participate in chat, be assigned tasks, and create automations (which are automatically placed in `pending_approval` status for human review).

All service account endpoints require the `org.members.manage` permission.

Each service account is backed by a **provider** that determines how it responds in chat:

| Provider | Description |
| - | - |
| `openrouter` | AI model accessed via OpenRouter. Requires `openrouter_model`. |
| `cursor` | Cursor Cloud Agent. Optionally accepts `cursor_default_repo_url` and `cursor_default_ref`. |

***

## List service accounts

```
GET /api/v1/organizations/{orgId}/service-accounts
```

Returns all service accounts in the organization.

**Path parameters**

<ParamField path="orgId" type="string" required>Organization UUID.</ParamField>

**Example**

```bash theme={null}
curl https://your-hostname/api/v1/organizations/YOUR_ORG_ID/service-accounts \
  -H "Authorization: Bearer YOUR_TOKEN"
```

**Response** `200 OK`

```json theme={null}
{
  "service_accounts": [
    {
      "id": "018e1234-abcd-7000-8000-0000000000b0",
      "organization_id": "018e1234-abcd-7000-8000-000000000000",
      "user_id": "018e1234-abcd-7000-8000-0000000000c0",
      "name": "Aria",
      "created_by": "018e1234-abcd-7000-8000-000000000050",
      "created_at": "2024-03-01T10:00:00Z",
      "provider": "openrouter",
      "openrouter_model": "nvidia/nemotron-3-super-120b-a12b:free",
      "cursor_default_repo_url": null,
      "cursor_default_ref": null
    }
  ]
}
```

<ResponseField name="service_accounts[].id" type="string">Service account UUID.</ResponseField>
<ResponseField name="service_accounts[].organization_id" type="string">Organization UUID.</ResponseField>
<ResponseField name="service_accounts[].user_id" type="string">UUID of the backing user principal. Use this ID for `@mentions` and `assignee_user_id`.</ResponseField>
<ResponseField name="service_accounts[].name" type="string">Display name shown in the UI.</ResponseField>
<ResponseField name="service_accounts[].created_by" type="string">UUID of the human user who created this service account.</ResponseField>
<ResponseField name="service_accounts[].provider" type="string">`"openrouter"` or `"cursor"`.</ResponseField>
<ResponseField name="service_accounts[].openrouter_model" type="string">OpenRouter model identifier (provider `openrouter` only).</ResponseField>
<ResponseField name="service_accounts[].cursor_default_repo_url" type="string">Default repository URL for Cursor Cloud Agent (provider `cursor` only), or `null`.</ResponseField>
<ResponseField name="service_accounts[].cursor_default_ref" type="string">Default git ref for Cursor Cloud Agent (provider `cursor` only), or `null`.</ResponseField>

***

## Create a service account

```
POST /api/v1/organizations/{orgId}/service-accounts
```

Creates a new service account, its backing user principal, and an initial `sa_` token. The token is returned **once** in the response and cannot be retrieved again. Store it securely.

**Path parameters**

<ParamField path="orgId" type="string" required>Organization UUID.</ParamField>

**Request body**

<ParamField body="name" type="string" required>
  Display name for the AI staff member.
</ParamField>

<ParamField body="provider" type="string">
  `"openrouter"` (default) or `"cursor"`.
</ParamField>

<ParamField body="openrouter_model" type="string">
  OpenRouter model identifier. Required when `provider` is `openrouter`. Defaults to `"nvidia/nemotron-3-super-120b-a12b:free"` if omitted.
</ParamField>

<ParamField body="cursor_default_repo_url" type="string">
  Default repository URL passed to Cursor Cloud Agent invocations. Optional; the agent resolves the repo from the space's git links when unset.
</ParamField>

<ParamField body="cursor_default_ref" type="string">
  Default git ref (branch or commit SHA) for Cursor Cloud Agent. Optional.
</ParamField>

<ParamField body="role_ids" type="array">
  List of role UUIDs to assign to this service account. If omitted, system default roles apply.
</ParamField>

**Example** — OpenRouter AI staff

```bash theme={null}
curl -X POST https://your-hostname/api/v1/organizations/YOUR_ORG_ID/service-accounts \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Aria",
    "provider": "openrouter",
    "openrouter_model": "anthropic/claude-3.5-sonnet"
  }'
```

**Example** — Cursor Cloud Agent

```bash theme={null}
curl -X POST https://your-hostname/api/v1/organizations/YOUR_ORG_ID/service-accounts \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CursorBot",
    "provider": "cursor",
    "cursor_default_repo_url": "https://github.com/acme/api",
    "cursor_default_ref": "main"
  }'
```

**Response** `201 Created`

```json theme={null}
{
  "service_account": {
    "id": "018e1234-abcd-7000-8000-0000000000b1",
    "organization_id": "018e1234-abcd-7000-8000-000000000000",
    "user_id": "018e1234-abcd-7000-8000-0000000000c1",
    "name": "Aria",
    "created_by": "018e1234-abcd-7000-8000-000000000050",
    "created_at": "2024-03-20T10:00:00Z",
    "provider": "openrouter",
    "openrouter_model": "anthropic/claude-3.5-sonnet"
  },
  "token": "sa_4a7f3c8b2e1d6a9f0c5b3e7d2a1f4c8b9e3d6a7f2c1b5e8d3a0f7c4b2e9d6a1f"
}
```

<ResponseField name="service_account" type="object">The created service account object.</ResponseField>

<ResponseField name="token" type="string">
  The `sa_` prefixed API token. **This is the only time this value is returned.** Store it immediately.
</ResponseField>

***

## Update a service account

```
PATCH /api/v1/organizations/{orgId}/service-accounts/{serviceAccountId}
```

Updates provider-specific fields. All fields are optional.

**Path parameters**

<ParamField path="orgId" type="string" required>Organization UUID.</ParamField>
<ParamField path="serviceAccountId" type="string" required>Service account UUID.</ParamField>

**Request body**

<ParamField body="provider" type="string">
  Change the provider: `"openrouter"` or `"cursor"`.
</ParamField>

<ParamField body="openrouter_model" type="string">
  New OpenRouter model identifier. Set to `""` to clear (provider must then be changed to `cursor`).
</ParamField>

<ParamField body="cursor_default_repo_url" type="string">
  New default repository URL. Set to `""` to clear.
</ParamField>

<ParamField body="cursor_default_ref" type="string">
  New default git ref. Set to `""` to clear.
</ParamField>

**Example**

```bash theme={null}
curl -X PATCH \
  https://your-hostname/api/v1/organizations/YOUR_ORG_ID/service-accounts/YOUR_SA_ID \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"openrouter_model": "openai/gpt-4o"}'
```

**Response** `200 OK`

```json theme={null}
{
  "service_account": {
    "id": "018e1234-abcd-7000-8000-0000000000b1",
    "name": "Aria",
    "provider": "openrouter",
    "openrouter_model": "openai/gpt-4o",
    ...
  }
}
```

***

## Delete a service account

```
DELETE /api/v1/organizations/{orgId}/service-accounts/{serviceAccountId}
```

Removes the service account, its backing user, role assignments, and organization membership. The `sa_` token is invalidated. This action is irreversible.

**Path parameters**

<ParamField path="orgId" type="string" required>Organization UUID.</ParamField>
<ParamField path="serviceAccountId" type="string" required>Service account UUID.</ParamField>

**Example**

```bash theme={null}
curl -X DELETE \
  https://your-hostname/api/v1/organizations/YOUR_ORG_ID/service-accounts/YOUR_SA_ID \
  -H "Authorization: Bearer YOUR_TOKEN"
```

**Response** `204 No Content`

***

## Token lifecycle

The `sa_` token is generated once at creation time. There is no rotation endpoint in the current API version. To rotate a token, delete the service account and create a new one.

Service account tokens do not expire. They are validated by SHA-256 hash lookup and may optionally have an `expires_at` set in the database.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.