# Forgejo API — Stars & Watchers

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

---

## Endpoints Overview

### Repository-Level Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/repos/{owner}/{repo}/stargazers` | List users who starred the repo |
| `GET` | `/repos/{owner}/{repo}/subscribers` | List users watching the repo |
| `GET` | `/repos/{owner}/{repo}/subscription` | Check current user's watch status |
| `PUT` | `/repos/{owner}/{repo}/subscription` | Watch the repo |
| `DELETE` | `/repos/{owner}/{repo}/subscription` | Unwatch the repo |

### User-Level Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/user/starred` | List repos starred by authenticated user |
| `GET` | `/user/starred/{owner}/{repo}` | Check if authenticated user starred a repo |
| `PUT` | `/user/starred/{owner}/{repo}` | Star a repo |
| `DELETE` | `/user/starred/{owner}/{repo}` | Unstar a repo |
| `GET` | `/user/subscriptions` | List repos watched by authenticated user |

---

## Stargazer Endpoints

### List Stargazers

List all users who have starred a repository.

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

**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 stargazers
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/stargazers"

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

# Count stargazers (using jq)
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/stargazers" | jq 'length'
```

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

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

---

### List Repos Starred by Current User

```
GET /user/starred
```

**Query Parameters:**

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

```bash
# List all repos you've starred
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/starred"

# List with pagination
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/starred?page=1&limit=20"

# Get just the full names of starred repos
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/starred" | jq -r '.[].full_name'
```

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

---

### Check if Current User Starred a Repo

```
GET /user/starred/{owner}/{repo}
```

**Path Parameters:**

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

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

**Response:**
- `204 No Content` — You have starred this repo
- `404 Not Found` — You have not starred this repo

---

### Star a Repository

```
PUT /user/starred/{owner}/{repo}
```

**Path Parameters:**

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

```bash
# Star a repo
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/starred/{owner}/{repo}"

# Star multiple repos
for repo in {repo1} {repo2} {repo3}; do
  curl -s -X PUT \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/user/starred/{owner}/${repo}"
  echo "Starred ${repo}"
done
```

**Response:** `204 No Content`

**Note:** Starring an already-starred repo is a no-op and still returns `204`.

---

### Unstar a Repository

```
DELETE /user/starred/{owner}/{repo}
```

**Path Parameters:**

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

```bash
# Unstar a repo
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/starred/{owner}/{repo}"
```

**Response:** `204 No Content`

**Note:** Unstarring a repo you haven't starred is a no-op and still returns `204`.

---

## Watcher (Subscriber) Endpoints

### List Watchers (Subscribers)

List all users watching a repository.

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

**Path Parameters:**

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

**Query Parameters:**

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

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

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

# Count watchers
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/subscribers" | jq 'length'
```

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

---

### Check Current User's Watch Status

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

**Path Parameters:**

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

```bash
# Check if you're watching a repo
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/subscription"
```

**Response:** `200 OK`

```json
{
  "subscribed": true,
  "ignored": false,
  "reason": null,
  "created_at": "2024-01-15T10:30:00Z",
  "url": "https://git.cleverthis.com/api/v1/repos/{owner}/{repo}/subscription",
  "repository_url": "https://git.cleverthis.com/api/v1/repos/{owner}/{repo}"
}
```

**WatchInfo Fields:**

| Field | Type | Description |
|-------|------|-------------|
| `subscribed` | boolean | Whether the user is subscribed to notifications |
| `ignored` | boolean | Whether the user has muted notifications |
| `reason` | object/null | Reason for the subscription |
| `created_at` | string | ISO 8601 timestamp of when subscription was created |
| `url` | string | API URL for this subscription |
| `repository_url` | string | API URL of the repository |

**Response if not watching:** `404 Not Found`

---

### Watch a Repository

Subscribe to notifications for a repository.

```
PUT /repos/{owner}/{repo}/subscription
```

**Path Parameters:**

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

```bash
# Watch a repo (subscribe to notifications)
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/subscription"

# Watch multiple repos
for repo in {repo1} {repo2} {repo3}; do
  curl -s -X PUT \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/repos/{owner}/${repo}/subscription"
  echo "Now watching ${repo}"
done
```

**Response:** `200 OK` — `{WatchInfo}` object

---

### Unwatch a Repository

Unsubscribe from notifications for a repository.

```
DELETE /repos/{owner}/{repo}/subscription
```

**Path Parameters:**

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

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

**Response:** `204 No Content`

---

### List Repos Watched by Current User

```
GET /user/subscriptions
```

**Query Parameters:**

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

```bash
# List all repos you're watching
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/subscriptions"

# List with pagination
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/subscriptions?page=1&limit=30"

# Get just the full names of watched repos
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/subscriptions" | jq -r '.[].full_name'
```

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

---

## Browsing Other Users' Stars

### List Repos Starred by a Specific User

```
GET /users/{username}/starred
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `username` | string | Username to query |

**Query Parameters:**

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

```bash
# See what repos a user has starred
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/users/{username}/starred"
```

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

---

### List Repos Watched by a Specific User

```
GET /users/{username}/subscriptions
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `username` | string | Username to query |

**Query Parameters:**

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

```bash
# See what repos a user is watching
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/users/{username}/subscriptions"
```

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

---

## Common Patterns

### Get Star and Watch Counts for a Repo

```bash
# Get star count from repo info
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}" | jq '{stars_count, watchers_count, forks_count}'
```

### Star All Repos in an Organization

```bash
# Star all repos in an org
REPOS=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/orgs/{org}/repos?limit=100" | jq -r '.[].full_name')

for repo in $REPOS; do
  owner=$(echo "$repo" | cut -d'/' -f1)
  name=$(echo "$repo" | cut -d'/' -f2)
  curl -s -X PUT \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/user/starred/${owner}/${name}"
  echo "Starred ${repo}"
done
```

### Unwatch All Repos (Notification Cleanup)

```bash
# Get all watched repos and unwatch them
WATCHED=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/subscriptions?limit=100" | jq -r '.[].full_name')

for repo in $WATCHED; do
  owner=$(echo "$repo" | cut -d'/' -f1)
  name=$(echo "$repo" | cut -d'/' -f2)
  curl -s -X DELETE \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/repos/${owner}/${name}/subscription"
  echo "Unwatched ${repo}"
done
```

### Export Starred Repos List

```bash
# Export all starred repos as a simple list
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/user/starred?limit=100" | \
  jq -r '.[] | "\(.full_name)\t\(.html_url)\t\(.description // "No description")"'
```

### Compare Star Counts Across Repos

```bash
# Compare stars for repos in an org
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/orgs/{org}/repos?limit=100" | \
  jq -r 'sort_by(.stars_count) | reverse | .[] | "\(.stars_count)\t\(.full_name)"'
```

---

## Error Responses

| Code | Description |
|------|-------------|
| `403 Forbidden` | Repository is private and user lacks access |
| `404 Not Found` | Repository or user not found; or not watching (for subscription check) |
