# Forgejo Issue Comments API

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

All endpoints require authentication via `Authorization: token ${FORGEJO_PAT}` header.

---

## List ALL Comments in a Repository

```
GET /repos/{owner}/{repo}/issues/comments
```

Returns all comments across all issues and pull requests in the repository. Useful for bulk operations, searching, or syncing.

### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `since` | string | query | Only show comments updated after this date (ISO 8601, e.g. `2024-01-01T00:00:00Z`) |
| `before` | string | query | Only show comments updated before this date (ISO 8601) |
| `page` | integer | query | Page number (1-based). Default: `1` |
| `limit` | integer | query | Page size. Default: server default (usually 20, max 50) |

### Response

Returns `200` with an array of Comment objects. Pagination info in response headers (`X-Total-Count`, `Link`).

### Comment Object Fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Comment ID |
| `body` | string | Comment body (Markdown) |
| `user` | object | Author user object |
| `html_url` | string | URL to the comment in the web UI |
| `issue_url` | string | API URL of the parent issue |
| `pull_request_url` | string | API URL if comment is on a PR (or empty) |
| `created_at` | string | ISO 8601 creation timestamp |
| `updated_at` | string | ISO 8601 last update timestamp |
| `assets` | array | Attached files (Attachment objects) |

### Examples

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

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

# List comments updated since a specific date
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments?since=2024-06-01T00:00:00Z"

# List comments updated within a date range
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments?since=2024-01-01T00:00:00Z&before=2024-07-01T00:00:00Z"

# Get total comment count from headers
curl -s -I \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments" | grep -i x-total-count
```

---

## Get a Comment by ID

```
GET /repos/{owner}/{repo}/issues/comments/{id}
```

Retrieves a single comment by its ID. Works for both issue and PR comments.

### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `id` | integer | path | **Required.** Comment ID |

### Response

Returns `200` with a Comment object. Returns `404` if not found.

### Examples

```bash
# Get comment by ID
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}"

# Extract just body and author
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}" \
  | jq '{body, author: .user.login, created_at}'
```

---

## Edit a Comment by ID

```
PATCH /repos/{owner}/{repo}/issues/comments/{id}
```

Edits a comment. You must be the comment author or have admin permissions.

### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `id` | integer | path | **Required.** Comment ID |

### Request Body — `EditCommentOption`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `body` | string | **Yes** | New comment body (Markdown) |
| `updated_at` | string | No | Override update timestamp (ISO 8601). Useful for migrations |

### Response

Returns `200` with the updated Comment object.

### Examples

```bash
# Edit a comment
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Updated comment text with **bold** and a [link](https://example.com)"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}"

# Edit with custom timestamp (for migrations)
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Migrated comment content",
    "updated_at": "2023-06-15T10:30:00Z"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}"
```

---

## Delete a Comment by ID

```
DELETE /repos/{owner}/{repo}/issues/comments/{id}
```

Permanently deletes a comment. You must be the comment author or have admin permissions.

### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `id` | integer | path | **Required.** Comment ID |

### Response

Returns `204` (No Content) on success.

### Example

```bash
# Delete comment by ID
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}"
```

---

## List Comments on a Specific Issue

```
GET /repos/{owner}/{repo}/issues/{index}/comments
```

Returns comments for a specific issue, ordered chronologically.

### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `index` | integer | path | **Required.** Issue index number |
| `since` | string | query | Only show comments updated after this date (ISO 8601) |
| `before` | string | query | Only show comments updated before this date (ISO 8601) |
| `page` | integer | query | Page number (1-based). Default: `1` |
| `limit` | integer | query | Page size |

### Response

Returns `200` with an array of Comment objects.

### Examples

```bash
# List all comments on issue #42
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments"

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

# Comments since a date
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments?since=2024-06-01T00:00:00Z"

# List comment authors and bodies with jq
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments" \
  | jq '[.[] | {id, author: .user.login, body: .body[:80], created_at}]'
```

---

## Add a Comment to an Issue

```
POST /repos/{owner}/{repo}/issues/{index}/comments
```

Creates a new comment on the specified issue.

### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `index` | integer | path | **Required.** Issue index number |

### Request Body — `CreateCommentOption`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `body` | string | **Yes** | Comment body (Markdown supported) |
| `updated_at` | string | No | Override creation timestamp (ISO 8601). Useful for migrations |

### Response

Returns `201` with the created Comment object.

### Examples

```bash
# Add a simple comment
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "I can reproduce this issue on Linux. Logs attached above."
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments"

# Add a comment with Markdown formatting
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "## Investigation\n\nThe root cause is in `auth.go:142`.\n\n```go\nif token == \"\" {\n    return nil, ErrNoToken\n}\n```\n\nThe empty-string check should use `strings.TrimSpace()` first.\n\n**Fix:** PR incoming."
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments"

# Add a comment with custom timestamp (for migration)
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Original comment from old tracker",
    "updated_at": "2022-03-15T08:00:00Z"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments"
```

---

## Edit a Comment on a Specific Issue

```
PATCH /repos/{owner}/{repo}/issues/{index}/comments/{id}
```

Edits an existing comment on a specific issue. Functionally identical to `PATCH /repos/{owner}/{repo}/issues/comments/{id}` but scoped to a specific issue for clarity.

### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `index` | integer | path | **Required.** Issue index number |
| `id` | integer | path | **Required.** Comment ID |

### Request Body — `EditCommentOption`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `body` | string | **Yes** | New comment body (Markdown) |
| `updated_at` | string | No | Override update timestamp (ISO 8601) |

### Response

Returns `200` with the updated Comment object.

### Example

```bash
# Edit comment #789 on issue #42
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Updated: The fix has been merged in commit abc123."
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments/789"
```

---

## Delete a Comment on a Specific Issue

```
DELETE /repos/{owner}/{repo}/issues/{index}/comments/{id}
```

Permanently deletes a comment from a specific issue.

### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `index` | integer | path | **Required.** Issue index number |
| `id` | integer | path | **Required.** Comment ID |

### Response

Returns `204` (No Content) on success.

### Example

```bash
# Delete comment #789 from issue #42
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments/789"
```

---

## Common Patterns

### Get the latest comment on an issue

```bash
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments?limit=1&page=999999" \
  | jq '.[-1]'
```

A more reliable approach — fetch all and take the last:

```bash
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments" \
  | jq 'sort_by(.created_at) | last'
```

### Count comments on an issue

```bash
curl -s -I \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments" \
  | grep -i x-total-count
```

### Find comments by a specific user across all issues

```bash
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments?limit=50" \
  | jq '[.[] | select(.user.login == "{username}")]'
```

### Post a comment and capture the new comment ID

```bash
COMMENT_ID=$(curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"body": "Automated comment from CI pipeline"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/comments" \
  | jq '.id')

echo "Created comment ID: ${COMMENT_ID}"
```
