---
title: "Applications"
description: "Manage application identities with the Alpacon API. Create applications, configure server accounts, bind existing accounts, and check permissions and errors."
---

> Full documentation index: https://docs.alpacax.com/llms.txt

# Applications

**Endpoint**: `/api/iam/applications/`

An application is an identity for automation. Create one before issuing its [service tokens](/reference/api/service-tokens/). Each token's scopes must fit the application's global roles; [grant the application a global role](/reference/api/#3-grant-the-application-a-global-role) before creating the token.

## Authentication and permissions

Use a signed-in session or a personal API token. Service tokens cannot call this API. A personal token needs the matching `application:create`, `application:read`, `application:update` or `application:delete` scope.

Every authenticated member can list and read applications. Creating one needs `application:create`; changing or deleting one needs `application:update` or `application:delete` on that application. Admins hold these permissions, and the creator receives the `application:maintainer` role on the application. Writes return `403 workspace_suspended` while the workspace is suspended.

The examples use a personal API token for a caller with the required roles and scopes.

## List applications

### Request

```http
GET /api/iam/applications/
```

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `name` | string | Filter by name |
| `service_type` | string | Filter by service type |
| `search` | string | Search name and description |
| `ordering` | string | `name`, `service_type`, `added_at` or `updated_at`; prefix with `-` for descending order. Default: `name` |
| `page` | integer | Page number, starting at 1 |
| `page_size` | integer | Results per page; default 15, maximum 100 |

### Response

`200 OK`, using [integer pagination](/reference/api/#pagination). This example shows selected application fields:

```json
{
  "count": 1,
  "current": 1,
  "next": null,
  "previous": null,
  "last": 1,
  "results": [
    {
      "id": "9d2e4b71-0c3a-4f5e-8b6d-1a2c3e4f5a6b",
      "name": "CI pipeline",
      "description": "Deployment checks",
      "service_type": "ci_cd",
      "permissions": {"update": true, "delete": true}
    }
  ]
}
```

### Example

```bash
curl "https://your-workspace.us1.alpacon.io/api/iam/applications/?service_type=ci_cd" \
  -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\""
```

## Application fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | UUID | Read-only application ID |
| `name` | string | Required; at most 128 characters, unique among applications that have not been deleted |
| `description` | string | Default `""` |
| `service_type` | string | `ai_agent`, `ci_cd`, `monitoring`, `automation`, `integration` or `other`; default `other`. Descriptive only |
| `created_by` | object | Read-only creator |
| `username` | string / null | Cannot be set on create. On update, must be a valid Unix username not in use by another identity |
| `shell` | string | Absolute Linux path, at most 32 characters; default `/usr/sbin/nologin`. Applied only when a server account is created |
| `home_directory` | string / null | Absolute path; null uses the OS default |
| `provisioning_enabled` | boolean | Default false; requires a username, so cannot be true on create |
| `auto_provisioning` | boolean | Default false; requires `provisioning_enabled`. Enabling it requests account provisioning across servers |
| `uid` | integer / null | At least 1000; cannot conflict with a user or another application |
| `added_at`, `updated_at` | datetime | Read-only timestamps |
| `permissions` | object | Read-only `{update, delete}` permission hints |

For readers who are neither admins nor application owners, responses omit `username`, `uid`, `shell`, `home_directory`, `provisioning_enabled` and `auto_provisioning`. List responses omit `shell` and `home_directory` for everyone.

## Create an application

### Request

```http
POST /api/iam/applications/
```

Send `name` and any optional fields from the table. Do not send `username`: it cannot be set at creation. Because provisioning requires a username, `provisioning_enabled` cannot be true in this request. Set the username and provisioning options afterward with `PATCH`.

### Request body

```json
{
  "name": "CI pipeline",
  "description": "Deployment checks",
  "service_type": "ci_cd"
}
```

### Response

`201 Created` with the application fields. Creating an application beyond the workspace plan's count limit returns `402 application_limit_exceeded`, with `axis: "application"`. The built-in `alpacon` application does not count toward that limit.

### Example

```bash
curl -X POST "https://your-workspace.us1.alpacon.io/api/iam/applications/" \
  -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\"" \
  -H "Content-Type: application/json" \
  -d '{"name":"CI pipeline","description":"Deployment checks","service_type":"ci_cd"}'
```

## Get an application

```http
GET /api/iam/applications/{id}/
```

`id` is the application UUID. Returns `200` with the application fields visible to you.

## Update an application

### Request

```http
PATCH /api/iam/applications/{id}/
PUT /api/iam/applications/{id}/
```

Returns `200` with the updated application. `id`, `created_by`, timestamps and `permissions` are read-only.

Setting `username` binds matching server accounts that are not already linked to an identity. Changing it unbinds accounts automatically linked by the previous name. A name matching an existing server account or group can require approval: the request returns `400 approval_superuser_approve_required` and creates an approval request.

### Example

```bash
curl -X PATCH "https://your-workspace.us1.alpacon.io/api/iam/applications/9d2e4b71-0c3a-4f5e-8b6d-1a2c3e4f5a6b/" \
  -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\"" \
  -H "Content-Type: application/json" \
  -d '{"username":"ci-deploy","provisioning_enabled":true}'
```

## Bind or unbind server accounts

### Request

```http
POST /api/iam/applications/{id}/system-users/
POST /api/iam/applications/{id}/system-users/unassign/
```

A Superuser or the application's maintainer can call these routes. If using a personal API token, it also needs `application:update`.

Both accept `system_user_ids`, a nonempty array of server-account UUIDs. Duplicate IDs are removed.

```json
{
  "system_user_ids": ["7d3984de-49ab-4cc6-bcdf-21fbd35858b8"]
}
```

### Response

Binding returns `200` with an array of accounts, each containing `id`, `uid`, `username`, `server`, `server_name`, `login_enabled` and `is_pinned`. A system account, an account bound to a user, or one bound to another application cannot be bound here.

Unbinding returns `200`:

```json
{
  "unassigned": 1,
  "system_user_ids": ["7d3984de-49ab-4cc6-bcdf-21fbd35858b8"]
}
```

## Delete an application

```http
DELETE /api/iam/applications/{id}/
```

Returns `204 No Content`. The application's service tokens stop authenticating immediately and disappear from the token list. Its roles are removed, provisioning is switched off and its server-account bindings are removed.

```bash
curl -X DELETE "https://your-workspace.us1.alpacon.io/api/iam/applications/9d2e4b71-0c3a-4f5e-8b6d-1a2c3e4f5a6b/" \
  -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\""
```

## Error responses

| Status | Error code | Description |
|--------|------------|-------------|
| 400 | `unique` | Name is already used by an application that has not been deleted |
| 400 | `application_username_invalid` | Username supplied on create, or an invalid Unix username |
| 400 | `application_username_in_use` | Username is already in use |
| 400 | `approval_superuser_approve_required` | A matching server account or group requires approval |
| 400 | `application_shell_invalid`, `application_home_directory_invalid` | Invalid shell or home-directory path |
| 400 | `application_uid_out_of_range`, `application_uid_in_use` | UID is below 1000 or conflicts with another identity |
| 400 | `application_provisioning_username_required` | Provisioning requested without a username |
| 400 | `application_auto_provisioning_requires_enabled` | Automatic provisioning requested while provisioning is disabled |
| 400 | `application_system_user_not_found` | A requested server account does not exist |
| 400 | `application_system_user_already_bound` | Account is a system account or already bound to another identity |
| 401 | `auth_token_missing` | Authentication missing or no accepted credential supplied |
| 402 | `application_limit_exceeded` | Workspace plan's application count exceeded |
| 403 | `api_token_scope_missing`, `rbac_permission_required`, `rbac_object_permission_required` | Missing token scope or role permission |
| 403 | `workspace_suspended` | Writes refused while the workspace is suspended |
| 404 | `api_not_found` | Application not found |

See [Error messages](/reference/api/#error-messages) for the coded error format.

Source: https://docs.alpacax.com/reference/api/applications/
