# Forgejo API — Repository Collaborators & Teams

Base URL: `https://git.cleverthis.com/api/v1`

---

## Endpoints Overview

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/repos/{owner}/{repo}/collaborators` | List collaborators |
| `GET` | `/repos/{owner}/{repo}/collaborators/{collaborator}` | Check if user is collaborator |
| `PUT` | `/repos/{owner}/{repo}/collaborators/{collaborator}` | Add collaborator |
| `DELETE` | `/repos/{owner}/{repo}/collaborators/{collaborator}` | Remove collaborator |
| `GET` | `/repos/{owner}/{repo}/collaborators/{collaborator}/permission` | Get permission level |
| `GET` | `/repos/{owner}/{repo}/assignees` | List available assignees |
| `GET` | `/repos/{owner}/{repo}/reviewers` | List available reviewers |
| `GET` | `/repos/{owner}/{repo}/teams` | List teams with access |
| `GET` | `/repos/{owner}/{repo}/teams/{team}` | Check team access |
| `PUT` | `/repos/{owner}/{repo}/teams/{team}` | Add team |
| `DELETE` | `/repos/{owner}/{repo}/teams/{team}` | Remove team |

---

## Permission Levels

Forgejo uses the following permission levels for collaborators:

| Permission | Description |
|------------|-------------|
| `read` | Can view and clone the repository |
| `write` | Can push to the repository |
| `admin` | Full administrative access |

---

## Collaborator Endpoints

### List Collaborators

```
GET /repos/{owner}/{repo}/collaborators
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Repository owner (user or org) |
| `repo` | string | Repository name |

**Query Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | integer | Page number (1-based) |
| `limit` | integer | Page size |

```bash
# List all collaborators
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators"

# List collaborators with pagination
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators?page=1&limit=50"
```

**Response:** `200 OK` — Array of `{User}` objects

Each user object includes: `id`, `login`, `full_name`, `email`, `avatar_url`, `is_admin`, `created`, etc.

---

### Check if User is Collaborator

```
GET /repos/{owner}/{repo}/collaborators/{collaborator}
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Repository owner |
| `repo` | string | Repository name |
| `collaborator` | string | Username to check |

```bash
# Check if "{collaborator}" is a collaborator
curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/{collaborator}"
```

**Response:**
- `204 No Content` — User is a collaborator
- `404 Not Found` — User is not a collaborator
- `422 Unprocessable Entity` — User is the repo owner (implicitly has access)

---

### Add Collaborator

```
PUT /repos/{owner}/{repo}/collaborators/{collaborator}
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Repository owner |
| `repo` | string | Repository name |
| `collaborator` | string | Username to add |

**Request Body (AddCollaboratorOption):**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `permission` | string | No | Permission level: `"read"`, `"write"`, or `"admin"` (default: `"write"`) |

```bash
# Add collaborator with write access (default)
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "permission": "write"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/{collaborator}"

# Add collaborator with read-only access
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "permission": "read"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/{collaborator}"

# Add collaborator with admin access
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "permission": "admin"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/{collaborator}"

# Add collaborator with empty body (defaults to write)
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/{collaborator}"
```

**Response:** `204 No Content` — Collaborator added successfully

**Note:** If the user is already a collaborator, this updates their permission level.

---

### Remove Collaborator

```
DELETE /repos/{owner}/{repo}/collaborators/{collaborator}
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Repository owner |
| `repo` | string | Repository name |
| `collaborator` | string | Username to remove |

```bash
# Remove collaborator
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/{collaborator}"
```

**Response:** `204 No Content` — Collaborator removed successfully

---

### Get Collaborator Permission Level

```
GET /repos/{owner}/{repo}/collaborators/{collaborator}/permission
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Repository owner |
| `repo` | string | Repository name |
| `collaborator` | string | Username to check |

```bash
# Get permission level for "{collaborator}"
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/{collaborator}/permission"
```

**Response:** `200 OK`

```json
{
  "permission": "write",
  "role_name": "write",
  "user": {
    "id": 5,
    "login": "{username}",
    "full_name": "Alice Smith",
    "email": "{username}@example.com",
    "avatar_url": "https://git.cleverthis.com/avatars/...",
    ...
  }
}
```

**Response Fields:**

| Field | Type | Description |
|-------|------|-------------|
| `permission` | string | Permission level: `"read"`, `"write"`, `"admin"`, `"owner"`, `"none"` |
| `role_name` | string | Role name (same as permission) |
| `user` | object | Full user object |

---

## Assignee and Reviewer Endpoints

### List Available Assignees

Returns all users who can be assigned to issues in this repo (collaborators + org members with access).

```
GET /repos/{owner}/{repo}/assignees
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Repository owner |
| `repo` | string | Repository name |

```bash
# List all available assignees
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/assignees"
```

**Response:** `200 OK` — Array of `{User}` objects

---

### List Available Reviewers

Returns all users who can review pull requests in this repo.

```
GET /repos/{owner}/{repo}/reviewers
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Repository owner |
| `repo` | string | Repository name |

```bash
# List all available reviewers
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/reviewers"
```

**Response:** `200 OK` — Array of `{User}` objects

---

## Team Access Endpoints

These endpoints manage team-level access for organization-owned repositories.

### List Teams with Access

```
GET /repos/{owner}/{repo}/teams
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Organization name (must be org repo) |
| `repo` | string | Repository name |

```bash
# List all teams with access to this repo
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/teams"
```

**Response:** `200 OK` — Array of `{Team}` objects

Team object includes:

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Team ID |
| `name` | string | Team name |
| `description` | string | Team description |
| `organization` | object | Org object |
| `permission` | string | Permission: `"none"`, `"read"`, `"write"`, `"admin"`, `"owner"` |
| `units` | array[string] | Accessible units (e.g., `"repo.code"`, `"repo.issues"`) |
| `includes_all_repositories` | boolean | Whether team has access to all org repos |
| `can_create_org_repo` | boolean | Whether team members can create org repos |

---

### Check Team Access

```
GET /repos/{owner}/{repo}/teams/{team}
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Organization name |
| `repo` | string | Repository name |
| `team` | string | Team slug/name |

```bash
# Check if "developers" team has access
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/teams/{team}"
```

**Response:**
- `200 OK` — `{Team}` object (team has access)
- `404 Not Found` — Team does not have access
- `405 Method Not Allowed` — Repository is not owned by an organization

---

### Add Team to Repository

```
PUT /repos/{owner}/{repo}/teams/{team}
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Organization name |
| `repo` | string | Repository name |
| `team` | string | Team slug/name |

```bash
# Give "developers" team access to the repo
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/teams/{team}"

# Give "qa-team" access
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/teams/{team}"
```

**Response:** `204 No Content` — Team added successfully

**Note:** The team's permission level and accessible units are determined by the team's own settings in the organization, not by this endpoint.

---

### Remove Team from Repository

```
DELETE /repos/{owner}/{repo}/teams/{team}
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Organization name |
| `repo` | string | Repository name |
| `team` | string | Team slug/name |

```bash
# Remove "contractors" team access
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/teams/{team}"
```

**Response:** `204 No Content` — Team removed successfully

---

## Common Patterns

### Bulk Add Collaborators

```bash
# Add multiple collaborators with a loop
for user in {user1} {user2} {user3} {user4}; do
  curl -s -X PUT \
    -H "Authorization: token ${FORGEJO_PAT}" \
    -H "Content-Type: application/json" \
    -d '{"permission": "write"}' \
    "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/${user}"
  echo "Added ${user}"
done
```

### Audit Collaborator Permissions

```bash
# Get all collaborators and their permissions
for user in $(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators" | jq -r '.[].login'); do
  perm=$(curl -s \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/${user}/permission" | jq -r '.permission')
  echo "${user}: ${perm}"
done
```

### Downgrade All Admin Collaborators to Write

```bash
# Find admins and downgrade to write
for user in $(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators" | jq -r '.[].login'); do
  perm=$(curl -s \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/${user}/permission" | jq -r '.permission')
  if [ "$perm" = "admin" ]; then
    curl -s -X PUT \
      -H "Authorization: token ${FORGEJO_PAT}" \
      -H "Content-Type: application/json" \
      -d '{"permission": "write"}' \
      "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/collaborators/${user}"
    echo "Downgraded ${user} from admin to write"
  fi
done
```

---

## Error Responses

| Code | Description |
|------|-------------|
| `403 Forbidden` | Insufficient permissions (admin required for managing collaborators) |
| `404 Not Found` | Repository or user not found |
| `405 Method Not Allowed` | Team endpoints used on non-org repo |
| `422 Unprocessable Entity` | Cannot add repo owner as collaborator, or invalid permission |
