# Forgejo Issue Reactions API

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

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

---

## Available Reaction Types

The following reaction types are supported:

| Reaction | String Value | Emoji |
|----------|-------------|-------|
| Thumbs up | `+1` | :+1: |
| Thumbs down | `-1` | :-1: |
| Laugh | `laugh` | :laugh: |
| Hooray | `hooray` | :hooray: |
| Confused | `confused` | :confused: |
| Heart | `heart` | :heart: |
| Rocket | `rocket` | :rocket: |
| Eyes | `eyes` | :eyes: |

---

## Reaction Object Fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Reaction ID |
| `user` | object | User who reacted |
| `content` | string | Reaction type (e.g. `+1`, `heart`) |
| `created_at` | string | ISO 8601 timestamp |

---

## Issue Reactions

### List Reactions on an Issue

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

Returns all reactions 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 |
| `page` | integer | query | Page number (1-based). Default: `1` |
| `limit` | integer | query | Page size |

#### Response

Returns `200` with an array of Reaction objects.

#### Examples

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

# Summarize reactions by type
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions" \
  | jq 'group_by(.content) | map({reaction: .[0].content, count: length})'

# List who gave thumbs up
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions" \
  | jq '[.[] | select(.content == "+1") | .user.login]'
```

---

### Add a Reaction to an Issue

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

Adds a reaction from the authenticated user to the issue. If the user has already added this reaction, the existing reaction is returned.

#### 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 — `EditReactionOption`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `content` | string | **Yes** | Reaction type. One of: `+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes` |

#### Response

Returns `200` or `201` with the Reaction object.

#### Examples

```bash
# Add thumbs up to issue #42
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "+1"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"

# Add heart reaction
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "heart"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"

# Add rocket reaction
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "rocket"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"

# Add eyes reaction
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "eyes"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"

# Add confused reaction
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "confused"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"

# Add laugh reaction
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "laugh"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"

# Add hooray reaction
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "hooray"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"

# Add thumbs down reaction
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "-1"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"
```

---

### Remove a Reaction from an Issue

```
DELETE /repos/{owner}/{repo}/issues/{index}/reactions
```

Removes the authenticated user's reaction of the specified type from the 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 — `EditReactionOption`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `content` | string | **Yes** | Reaction type to remove. One of: `+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes` |

#### Response

Returns `200` on success.

#### Examples

```bash
# Remove thumbs up from issue #42
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "+1"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"

# Remove heart reaction
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "heart"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions"
```

---

## Comment Reactions

### List Reactions on a Comment

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

Returns all reactions on the specified comment.

#### Parameters

| Parameter | Type | In | Description |
|-----------|------|------|-------------|
| `owner` | string | path | **Required.** Repository owner |
| `repo` | string | path | **Required.** Repository name |
| `id` | integer | path | **Required.** Comment ID |
| `page` | integer | query | Page number (1-based). Default: `1` |
| `limit` | integer | query | Page size |

#### Response

Returns `200` with an array of Reaction objects.

#### Examples

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

# Summarize comment reactions
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions" \
  | jq 'group_by(.content) | map({reaction: .[0].content, count: length, users: [.[].user.login]})'
```

---

### Add a Reaction to a Comment

```
POST /repos/{owner}/{repo}/issues/comments/{id}/reactions
```

Adds a reaction from the authenticated user to the comment. If the user has already added this reaction, the existing reaction is returned.

#### 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 — `EditReactionOption`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `content` | string | **Yes** | Reaction type. One of: `+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes` |

#### Response

Returns `200` or `201` with the Reaction object.

#### Examples

```bash
# Add thumbs up to comment #789
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "+1"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"

# Add heart to comment
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "heart"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"

# Add rocket to comment
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "rocket"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"

# Add eyes to comment
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "eyes"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"
```

---

### Remove a Reaction from a Comment

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

Removes the authenticated user's reaction of the specified type from the comment.

#### 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 — `EditReactionOption`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `content` | string | **Yes** | Reaction type to remove. One of: `+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes` |

#### Response

Returns `200` on success.

#### Examples

```bash
# Remove thumbs up from comment #789
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "+1"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"

# Remove heart from comment
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"content": "heart"}' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"
```

---

## Common Patterns

### Get a reaction summary for an issue with user details

```bash
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/reactions" \
  | jq 'group_by(.content) | map({
      reaction: .[0].content,
      count: length,
      users: [.[].user.login]
    }) | sort_by(-.count)'
```

### Check if current user has reacted to an issue

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

### Toggle a reaction (add if not present, remove if present)

```bash
OWNER="{owner}"
REPO="{repo}"
INDEX="{index}"
REACTION="+1"
MY_USERNAME="{username}"

# Check if reaction exists
EXISTS=$(curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/${OWNER}/${REPO}/issues/${INDEX}/reactions" \
  | jq --arg user "$MY_USERNAME" --arg reaction "$REACTION" \
    '[.[] | select(.user.login == $user and .content == $reaction)] | length')

if [ "$EXISTS" -gt 0 ]; then
  # Remove reaction
  curl -s -X DELETE \
    -H "Authorization: token ${FORGEJO_PAT}" \
    -H "Content-Type: application/json" \
    -d "{\"content\": \"${REACTION}\"}" \
    "${FORGEJO_URL}/api/v1/repos/${OWNER}/${REPO}/issues/${INDEX}/reactions"
  echo "Removed ${REACTION} reaction"
else
  # Add reaction
  curl -s -X POST \
    -H "Authorization: token ${FORGEJO_PAT}" \
    -H "Content-Type: application/json" \
    -d "{\"content\": \"${REACTION}\"}" \
    "${FORGEJO_URL}/api/v1/repos/${OWNER}/${REPO}/issues/${INDEX}/reactions"
  echo "Added ${REACTION} reaction"
fi
```
