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

# Projects

> Discover, create, update and archive projects through every developer surface.

export function AirctrlWordmark() {
  return <span className="airctrl-wordmark" aria-label="AIRCTRL">
      <span aria-hidden="true" className="airctrl-wordmark-air">AIR</span>
      <span aria-hidden="true" className="airctrl-wordmark-ctrl">CTRL</span>
    </span>;
}

A project groups records and gateways. Project access is independent: being a member of one project does not grant access to another.

## What you need

* A human PAT.
* An account ID from `GET /v1/accounts`, `listAccounts()`, `airctrl project accounts`, or `list_accounts`.
* The required permission for the action.

| Action             | Required permission                |
| ------------------ | ---------------------------------- |
| Create a project   | `projects:create` in the account   |
| Update a project   | `projects:update` in that project  |
| Archive or restore | `projects:archive` in that project |

When you create a project, <AirctrlWordmark /> makes you its Project Administrator. This does not make you an administrator of projects created by other members.

## Create a project

### API

```bash theme={}
curl --request POST \
  --url "$AIRCTRL_API_URL/v1/projects" \
  --header "Authorization: Bearer $AIRCTRL_TOKEN" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: 00000000-0000-4000-8000-000000000020" \
  --data '{
    "accountId": "00000000-0000-4000-8000-000000000001",
    "name": "Payments service",
    "description": "Credentials used by the payments application"
  }'
```

```json theme={}
{
  "ok": true,
  "data": {
    "project_id": "00000000-0000-4000-8000-000000000010"
  }
}
```

### SDK

```ts theme={}
const project = await airctrl.createProject({
  accountId: '00000000-0000-4000-8000-000000000001',
  name: 'Payments service',
  description: 'Credentials used by the payments application',
})

console.log(project.project_id)
```

### CLI

```bash theme={}
airctrl project create \
  --account 00000000-0000-4000-8000-000000000001 \
  --name "Payments service" \
  --description "Credentials used by the payments application"
```

### MCP

```text theme={}
Create an AIRCTRL project named "Payments service" in account
"00000000-0000-4000-8000-000000000001". Use "Credentials used by the
payments application" as its description. Show the final account, name and
description, then wait for my confirmation before creating it.
```

<div className="technical-reference">
  **MCP tool used:** `create_project`
</div>

## List and read projects

### SDK

```ts theme={}
const projects = await airctrl.listProjects({
  accountId: '00000000-0000-4000-8000-000000000001',
  includeArchived: false,
})

const project = await airctrl.getProject(
  '00000000-0000-4000-8000-000000000010',
  { accountId: '00000000-0000-4000-8000-000000000001' },
)
```

### CLI

```bash theme={}
airctrl project list --account 00000000-0000-4000-8000-000000000001
airctrl project get 00000000-0000-4000-8000-000000000010 \
  --account 00000000-0000-4000-8000-000000000001
```

### MCP

```text theme={}
List the active projects in account "00000000-0000-4000-8000-000000000001".
Then show the safe details for project
"00000000-0000-4000-8000-000000000010". Do not change anything.
```

<div className="technical-reference">
  **MCP tools used:** `list_projects`, `get_project`
</div>

## Update a project

Project updates replace all three editable fields. Send `null` to clear the description.

```ts theme={}
await airctrl.updateProject(
  '00000000-0000-4000-8000-000000000010',
  {
    name: 'Payments API',
    description: null,
    isActive: true,
  },
  { accountId: '00000000-0000-4000-8000-000000000001' },
)
```

CLI:

```bash theme={}
airctrl project update 00000000-0000-4000-8000-000000000010 \
  --account 00000000-0000-4000-8000-000000000001 \
  --name "Payments API" \
  --description null \
  --active true
```

MCP request:

```text theme={}
Update project "00000000-0000-4000-8000-000000000010" in account
"00000000-0000-4000-8000-000000000001". Rename it to "Payments API", clear
its description and keep it active. Show every resulting value and wait for
my confirmation before changing it.
```

<div className="technical-reference">
  **MCP tool used:** `update_project`
</div>

## Archive or restore

Archiving also makes the project inactive.

```ts theme={}
await airctrl.setProjectArchiveState(projectId, true, { accountId })
await airctrl.setProjectArchiveState(projectId, false, { accountId })
```

```bash theme={}
airctrl project archive "$PROJECT_ID" --account "$AIRCTRL_ACCOUNT_ID"
airctrl project restore "$PROJECT_ID" --account "$AIRCTRL_ACCOUNT_ID"
```

MCP request:

```text theme={}
Archive project "00000000-0000-4000-8000-000000000010" in account
"00000000-0000-4000-8000-000000000001". Show its name, ID and current state,
then wait for my confirmation. Do not change any other project.
```

<div className="technical-reference">
  **MCP tool used:** `set_project_archive`
</div>

## Common failures

* `401`: the PAT is missing, invalid or expired.
* `403`: the caller lacks the required account or project permission.
* `409`: a repeated write conflicts with the current state or idempotency key.
* A project read can return `null` when the project is not available to the caller.
