# Plane API Reference for AI Automation

## Instance Details

| Key | Value |
|-----|-------|
| **Web UI** | `https://plane.caprover.al-arcade.com/` |
| **Admin Panel** | `https://plane.caprover.al-arcade.com/god-mode/` |
| **API Base URL** | `https://plane.caprover.al-arcade.com/api/v1/` |
| **Workspace** | `https://plane.caprover.al-arcade.com/al-arcade/` |
| **Workspace Slug** | `al-arcade` |
| **Public Spaces** | `https://plane.caprover.al-arcade.com/spaces/` |
| **Server** | `18.192.166.221` (CapRover) |
| **Docker Services** | `srv-captain--plane`, `srv-captain--plane-db`, `srv-captain--plane-redis`, `srv-captain--plane-mq`, `srv-captain--plane-minio` |

### Admin Account

| Field | Value |
|-------|-------|
| **Email** | `aglantech@gmail.com` |
| **Password** | `Alarcade123#` |

### Infrastructure Credentials (Internal Only)

| Service | Connection |
|---------|-----------|
| PostgreSQL | `postgresql://plane:plane_db_pass_2024@srv-captain--plane-db:5432/plane` |
| Redis | `redis://srv-captain--plane-redis:6379/` |
| RabbitMQ | `amqp://plane:plane_mq_pass_2024@srv-captain--plane-mq:5672/plane` |
| MinIO | Endpoint: `http://srv-captain--plane-minio:9000`, Access Key: `plane_access_key`, Secret: `plane_secret_key_2024`, Bucket: `uploads` |

---

## Authentication

All API requests require an API key in the header:
```
X-API-Key: <your-api-key>
```

Generate an API key from: Plane Web UI → Settings → API Tokens (`https://plane.caprover.al-arcade.com/settings/api-tokens/`)

### Quick Test
```bash
curl -s https://plane.caprover.al-arcade.com/api/v1/users/me/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json"
```

---

## User

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `users/me/` | Get current authenticated user profile |

---

## Workspaces & Projects

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/` | List all projects |
| POST | `workspaces/<slug>/projects/` | Create a new project |
| GET | `workspaces/<slug>/projects/<id>/` | Get a project |
| PATCH | `workspaces/<slug>/projects/<id>/` | Update a project |
| DELETE | `workspaces/<slug>/projects/<id>/` | Delete a project |
| POST | `workspaces/<slug>/projects/<id>/archive/` | Archive a project |
| DELETE | `workspaces/<slug>/projects/<id>/archive/` | Unarchive a project |
| GET | `workspaces/<slug>/projects/<id>/summary/` | Get project summary (counts) |

### Create Project Example
```json
POST /api/v1/workspaces/al-arcade/projects/
{
  "name": "Hospital Game",
  "identifier": "HOS",
  "description": "Multiplayer hospital management game",
  "network": 2
}
```
- `network`: 0 = Secret, 2 = Public
- `identifier`: 1-5 uppercase letters, used in issue IDs (e.g., HOS-123)

---

## Work Items (Issues/Tasks)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/work-items/` | List all work items |
| POST | `workspaces/<slug>/projects/<project_id>/work-items/` | Create a work item |
| GET | `workspaces/<slug>/projects/<project_id>/work-items/<id>/` | Get a work item |
| PATCH | `workspaces/<slug>/projects/<project_id>/work-items/<id>/` | Update a work item |
| DELETE | `workspaces/<slug>/projects/<project_id>/work-items/<id>/` | Delete a work item |
| GET | `workspaces/<slug>/work-items/search/?search=<query>` | Search work items globally |
| GET | `workspaces/<slug>/work-items/<PROJECT_ID>-<SEQ>/` | Get by identifier (e.g., HOS-42) |

### Create Work Item Example
```json
POST /api/v1/workspaces/al-arcade/projects/<project_id>/work-items/
{
  "name": "Implement player spawning system",
  "description_html": "<p>Players need to spawn at designated points</p>",
  "state": "<state_id>",
  "priority": "high",
  "assignees": ["<user_id>"],
  "labels": ["<label_id>"],
  "start_date": "2024-01-15",
  "target_date": "2024-01-20",
  "estimate_point": 5
}
```

**Priority values:** `urgent`, `high`, `medium`, `low`, `none`

### Work Item Links

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/links/` | List links |
| POST | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/links/` | Add a link |
| PATCH | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/links/<id>/` | Update link |
| DELETE | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/links/<id>/` | Delete link |

### Work Item Comments

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/comments/` | List comments |
| POST | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/comments/` | Add comment |
| PATCH | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/comments/<id>/` | Update comment |
| DELETE | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/comments/<id>/` | Delete comment |

### Work Item Activities

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/activities/` | List activity log |

### Work Item Relations

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/relations/` | List relations |
| POST | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/relations/` | Create relation |

**Relation types:** `blocking`, `blocked_by`, `duplicate`, `relates_to`, `start_before`, `start_after`, `finish_before`, `finish_after`

### Work Item Attachments

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/attachments/` | List attachments |
| POST | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/attachments/` | Get presigned upload URL |
| PATCH | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/attachments/<id>/` | Confirm upload |
| DELETE | `workspaces/<slug>/projects/<project_id>/work-items/<issue_id>/attachments/<id>/` | Delete attachment |

---

## States (Workflow)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/states/` | List all states |
| POST | `workspaces/<slug>/projects/<project_id>/states/` | Create a state |
| PATCH | `workspaces/<slug>/projects/<project_id>/states/<id>/` | Update a state |
| DELETE | `workspaces/<slug>/projects/<project_id>/states/<id>/` | Delete a state |

### Create State Example
```json
POST /api/v1/workspaces/al-arcade/projects/<project_id>/states/
{
  "name": "In Review",
  "color": "#F59E0B",
  "group": "started"
}
```

**State groups:** `backlog`, `unstarted`, `started`, `completed`, `cancelled`

---

## Labels

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/labels/` | List all labels |
| POST | `workspaces/<slug>/projects/<project_id>/labels/` | Create a label |
| PATCH | `workspaces/<slug>/projects/<project_id>/labels/<id>/` | Update a label |
| DELETE | `workspaces/<slug>/projects/<project_id>/labels/<id>/` | Delete a label |

### Create Label Example
```json
POST /api/v1/workspaces/al-arcade/projects/<project_id>/labels/
{
  "name": "FishNet",
  "color": "#3B82F6"
}
```

---

## Cycles (Sprints)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/cycles/` | List cycles |
| POST | `workspaces/<slug>/projects/<project_id>/cycles/` | Create a cycle |
| GET | `workspaces/<slug>/projects/<project_id>/cycles/<id>/` | Get a cycle |
| PATCH | `workspaces/<slug>/projects/<project_id>/cycles/<id>/` | Update a cycle |
| DELETE | `workspaces/<slug>/projects/<project_id>/cycles/<id>/` | Delete a cycle |
| GET | `workspaces/<slug>/projects/<project_id>/cycles/<cycle_id>/cycle-issues/` | List issues in cycle |
| POST | `workspaces/<slug>/projects/<project_id>/cycles/<cycle_id>/cycle-issues/` | Add issues to cycle |
| DELETE | `workspaces/<slug>/projects/<project_id>/cycles/<cycle_id>/cycle-issues/<issue_id>/` | Remove from cycle |
| POST | `workspaces/<slug>/projects/<project_id>/cycles/<cycle_id>/transfer-issues/` | Transfer incomplete to another cycle |
| POST | `workspaces/<slug>/projects/<project_id>/cycles/<cycle_id>/archive/` | Archive cycle |

**Filter:** `?cycle_view=current` / `upcoming` / `completed` / `draft` / `incomplete` / `all`

### Create Cycle Example
```json
POST /api/v1/workspaces/al-arcade/projects/<project_id>/cycles/
{
  "name": "Sprint 1 - Core Multiplayer",
  "description": "Implement base networking and player spawning",
  "start_date": "2024-01-15",
  "end_date": "2024-01-29"
}
```

### Add Issues to Cycle
```json
POST /api/v1/workspaces/al-arcade/projects/<project_id>/cycles/<cycle_id>/cycle-issues/
{
  "issues": ["<issue_id_1>", "<issue_id_2>"]
}
```

---

## Modules (Feature Groups)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/modules/` | List modules |
| POST | `workspaces/<slug>/projects/<project_id>/modules/` | Create a module |
| GET | `workspaces/<slug>/projects/<project_id>/modules/<id>/` | Get a module |
| PATCH | `workspaces/<slug>/projects/<project_id>/modules/<id>/` | Update a module |
| DELETE | `workspaces/<slug>/projects/<project_id>/modules/<id>/` | Delete a module |
| GET | `workspaces/<slug>/projects/<project_id>/modules/<module_id>/module-issues/` | List issues in module |
| POST | `workspaces/<slug>/projects/<project_id>/modules/<module_id>/module-issues/` | Add issues to module |
| DELETE | `workspaces/<slug>/projects/<project_id>/modules/<module_id>/module-issues/<issue_id>/` | Remove from module |
| POST | `workspaces/<slug>/projects/<project_id>/modules/<id>/archive/` | Archive module |

### Create Module Example
```json
POST /api/v1/workspaces/al-arcade/projects/<project_id>/modules/
{
  "name": "Networking System",
  "description": "All FishNet multiplayer networking features",
  "start_date": "2024-01-01",
  "target_date": "2024-03-01",
  "status": "planned"
}
```

**Status values:** `backlog`, `planned`, `in-progress`, `paused`, `completed`, `cancelled`

---

## Members

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/members/` | List workspace members |
| GET | `workspaces/<slug>/projects/<project_id>/members/` | List project members |
| POST | `workspaces/<slug>/projects/<project_id>/members/` | Add member to project |
| PATCH | `workspaces/<slug>/projects/<project_id>/members/<id>/` | Update member role |
| DELETE | `workspaces/<slug>/projects/<project_id>/members/<id>/` | Remove member |

**Roles:** `admin` (20), `member` (15), `viewer` (10), `guest` (5)

---

## Estimates

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/estimates/` | Get project estimate |
| POST | `workspaces/<slug>/projects/<project_id>/estimates/` | Create estimate system |
| PATCH | `workspaces/<slug>/projects/<project_id>/estimates/` | Update estimate |
| DELETE | `workspaces/<slug>/projects/<project_id>/estimates/` | Delete estimate |

---

## Intake (Triage Queue)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/projects/<project_id>/intake-issues/` | List intake items |
| POST | `workspaces/<slug>/projects/<project_id>/intake-issues/` | Create intake item |
| PATCH | `workspaces/<slug>/projects/<project_id>/intake-issues/<id>/` | Accept/decline/snooze |
| DELETE | `workspaces/<slug>/projects/<project_id>/intake-issues/<id>/` | Delete intake item |

---

## Workspace Invitations

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/invitations/` | List invitations |
| POST | `workspaces/<slug>/invitations/` | Invite someone |
| DELETE | `workspaces/<slug>/invitations/<id>/` | Revoke invitation |

---

## Stickies (Notes)

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `workspaces/<slug>/stickies/` | List stickies |
| POST | `workspaces/<slug>/stickies/` | Create sticky |
| PATCH | `workspaces/<slug>/stickies/<id>/` | Update sticky |
| DELETE | `workspaces/<slug>/stickies/<id>/` | Delete sticky |

---

## Common Query Parameters

| Parameter | Description |
|-----------|-------------|
| `cursor` | Pagination cursor |
| `per_page` | Items per page (default 100) |
| `order_by` | Sort field (prefix `-` for descending) |
| `fields` | Comma-separated fields to include |
| `expand` | Comma-separated relations to expand |

---

## External ID Tracking (for AI integration)

Work items, cycles, modules, states, labels, and comments all support:
- `external_id` — your system's ID for this object
- `external_source` — identifier for your system (e.g., "claude-ai")

This lets your AI track which items it created:
```json
{
  "name": "Fix spawn race condition",
  "external_id": "ai-task-001",
  "external_source": "claude-automation"
}
```

---

## Full Workflow Example: AI Creates a Sprint

```python
import requests

BASE = "https://plane.caprover.al-arcade.com/api/v1"
HEADERS = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}
WS = "al-arcade"  # workspace slug

# 1. Create project
project = requests.post(f"{BASE}/workspaces/{WS}/projects/", headers=HEADERS, json={
    "name": "Hospital Multiplayer",
    "identifier": "HMP",
    "description": "Co-op hospital management game"
}).json()
project_id = project["id"]

# 2. Create labels
for label in [("Networking", "#3B82F6"), ("UI", "#10B981"), ("Gameplay", "#F59E0B")]:
    requests.post(f"{BASE}/workspaces/{WS}/projects/{project_id}/labels/", 
                  headers=HEADERS, json={"name": label[0], "color": label[1]})

# 3. Get default states
states = requests.get(f"{BASE}/workspaces/{WS}/projects/{project_id}/states/", 
                      headers=HEADERS).json()
todo_state = next(s["id"] for s in states["results"] if s["group"] == "unstarted")

# 4. Create a cycle (sprint)
cycle = requests.post(f"{BASE}/workspaces/{WS}/projects/{project_id}/cycles/", headers=HEADERS, json={
    "name": "Sprint 1 - Core Systems",
    "start_date": "2024-01-15",
    "end_date": "2024-01-29"
}).json()

# 5. Create work items
issues = []
for task in ["Player spawning", "Lobby system", "Network sync"]:
    issue = requests.post(f"{BASE}/workspaces/{WS}/projects/{project_id}/work-items/", 
                          headers=HEADERS, json={
        "name": task,
        "state": todo_state,
        "priority": "high",
        "external_source": "claude-ai"
    }).json()
    issues.append(issue["id"])

# 6. Add issues to cycle
requests.post(f"{BASE}/workspaces/{WS}/projects/{project_id}/cycles/{cycle['id']}/cycle-issues/",
              headers=HEADERS, json={"issues": issues})
```

---

## Instance Setup (First Time)

1. Visit `https://plane.caprover.al-arcade.com/god-mode/` — create admin account
2. Visit `https://plane.caprover.al-arcade.com/` — create workspace (slug: `al-arcade`)
3. Go to Settings → API Tokens → create a token
4. Use that token in the `X-API-Key` header for all API calls

## SSH Access to Plane Server

```bash
ssh -i /Users/mahmoudaglan/NewMigration/newServer.pem -o StrictHostKeyChecking=no ubuntu@18.192.166.221

# View Plane logs
sudo docker logs $(sudo docker ps -q --filter "name=srv-captain--plane.1") --tail 50

# Restart Plane
sudo docker service update --force srv-captain--plane

# Access Plane DB directly
sudo docker exec -it $(sudo docker ps -q --filter "name=srv-captain--plane-db") psql -U plane -d plane
```

## Public Sharing (Community Progress)

Plane has a built-in **Publish** feature:
1. Open any project view (Board, List, Spreadsheet)
2. Click the Share/Publish icon
3. Choose what's visible (issues, comments, reactions, votes)
4. Get a public link like: `https://plane.caprover.al-arcade.com/spaces/<publish_id>`

No login required for viewers — share with your community to show game progress.
