# Forgejo API — Repository Forks

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

---

## Endpoints Overview

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/repos/{owner}/{repo}/forks` | List forks of a repository |
| `POST` | `/repos/{owner}/{repo}/forks` | Create a fork |
| `GET` | `/repos/{owner}/{repo}/sync_fork` | Check fork sync status (default branch) |
| `POST` | `/repos/{owner}/{repo}/sync_fork` | Sync fork with upstream (default branch) |
| `GET` | `/repos/{owner}/{repo}/sync_fork/{branch}` | Check specific branch sync status |
| `POST` | `/repos/{owner}/{repo}/sync_fork/{branch}` | Sync specific branch with upstream |

---

## List Forks

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

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

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

# List forks of an org repo
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/forks"
```

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

Each fork repository object includes a `parent` field pointing to the upstream repo.

---

## Create Fork

```
POST /repos/{owner}/{repo}/forks
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Repository owner to fork from |
| `repo` | string | Repository name to fork from |

**Request Body (CreateForkOption):**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | No | Custom name for the fork (defaults to original repo name) |
| `organization` | string | No | Organization to fork into (defaults to authenticated user) |

```bash
# Fork to your own account (same name)
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/forks"

# Fork with a custom name
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-{upstream_repo}-fork"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/forks"

# Fork into an organization
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "organization": "{org}"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/forks"

# Fork into an organization with a custom name
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "org-fork-of-{upstream_repo}",
    "organization": "{org}"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/forks"
```

**Response:** `202 Accepted` — `{Repository}` object of the new fork

**Notes:**
- Returns `202 Accepted` (not `201 Created`) because forking may be asynchronous
- The forked repo's `fork` field will be `true`
- The `parent` field will reference the upstream repo
- You cannot fork your own repo to the same owner
- If a fork already exists for the target owner, you'll get a `409 Conflict`

---

## Check Fork Sync Status (Default Branch)

Check whether the fork's default branch is behind the upstream.

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

**Path Parameters:**

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

```bash
# Check if the fork's default branch is in sync
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork"
```

**Response:** `200 OK`

```json
{
  "allowed": true,
  "base_branch": "{branch}",
  "missing_commits": 5
}
```

**Response Fields:**

| Field | Type | Description |
|-------|------|-------------|
| `allowed` | boolean | Whether syncing is allowed (e.g., not if there are conflicts) |
| `base_branch` | string | The base (default) branch being compared |
| `missing_commits` | integer | Number of commits the fork is behind upstream |

**Notes:**
- If `missing_commits` is `0`, the fork is up-to-date
- If `allowed` is `false`, there may be conflicts that prevent automatic sync
- Returns `404` if the repo is not a fork

---

## Sync Fork with Upstream (Default Branch)

Sync the fork's default branch to match upstream.

```
POST /repos/{owner}/{repo}/sync_fork
```

**Path Parameters:**

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

```bash
# Sync the fork's default branch with upstream
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork"
```

**Response:** `200 OK` on success

**Notes:**
- This fast-forwards the default branch to match upstream
- The fork must be a fork (not a standalone repo)
- You must have write access to the fork
- Returns `404` if the repo is not a fork

---

## Check Branch Sync Status

Check whether a specific branch on the fork is behind the upstream.

```
GET /repos/{owner}/{repo}/sync_fork/{branch}
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Fork owner |
| `repo` | string | Fork name |
| `branch` | string | Branch name to check |

```bash
# Check if a specific branch is in sync
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork/{branch}"

# Check main branch sync
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork/{branch}"

# Check release branch sync
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork/{branch}"
```

**Response:** `200 OK`

```json
{
  "allowed": true,
  "base_branch": "{branch}",
  "missing_commits": 12
}
```

---

## Sync Specific Branch with Upstream

Sync a specific branch of the fork with the same branch on upstream.

```
POST /repos/{owner}/{repo}/sync_fork/{branch}
```

**Path Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `owner` | string | Fork owner |
| `repo` | string | Fork name |
| `branch` | string | Branch name to sync |

```bash
# Sync "develop" branch
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork/{branch}"

# Sync "main" branch
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork/{branch}"

# Sync "release-v2" branch
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork/{branch}"
```

**Response:** `200 OK` on success

---

## Common Patterns

### Fork, Clone, and Set Up Remote

```bash
# 1. Create the fork via API
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/forks"

# 2. Clone the fork locally
git clone "${FORGEJO_URL}/{owner}/{repo}.git"
cd project

# 3. Add upstream remote
git remote add upstream "${FORGEJO_URL}/{upstream_owner}/project.git"
```

### Check and Sync All Branches

```bash
# Check sync status for multiple branches
for branch in {branch1} {branch2} {branch3}; do
  echo "=== ${branch} ==="
  curl -s \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork/${branch}" | jq '.'
done
```

### Auto-Sync Fork if Behind

```bash
# Check if behind, sync if needed
MISSING=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork" | jq '.missing_commits')

if [ "$MISSING" -gt 0 ]; then
  echo "Fork is ${MISSING} commits behind, syncing..."
  curl -s -X POST \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/sync_fork"
  echo "Sync complete."
else
  echo "Fork is up to date."
fi
```

### List All Forks and Their Sync Status

```bash
# Get all forks of a repo and check their sync status
FORKS=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/forks" | jq -r '.[].full_name')

for fork in $FORKS; do
  STATUS=$(curl -s \
    -H "Authorization: token ${FORGEJO_PAT}" \
    "${FORGEJO_URL}/api/v1/repos/${fork}/sync_fork" 2>/dev/null | jq -r '.missing_commits // "N/A"')
  echo "${fork}: ${STATUS} commits behind"
done
```

---

## Error Responses

| Code | Description |
|------|-------------|
| `403 Forbidden` | Insufficient permissions |
| `404 Not Found` | Repository not found, or repo is not a fork (for sync endpoints) |
| `409 Conflict` | Fork already exists for this owner |
| `422 Unprocessable Entity` | Invalid parameters (e.g., invalid fork name) |
