Files
CleverAgents Build Agent 237e776951
CI / lint (push) Successful in 20s
CI / quality (push) Successful in 20s
CI / helm (push) Successful in 24s
CI / build (push) Successful in 24s
CI / push-validation (push) Successful in 39s
CI / security (push) Successful in 1m1s
CI / e2e_tests (push) Successful in 3m13s
CI / typecheck (push) Successful in 4m23s
CI / unit_tests (push) Successful in 6m44s
CI / integration_tests (push) Successful in 6m49s
CI / docker (push) Successful in 11s
CI / coverage (push) Successful in 6m56s
CI / status-check (push) Successful in 0s
feat(skills): add exhaustive Forgejo REST API agent skill
Adds a comprehensive opencode skill under .opencode/skills/forgejo-api/
covering all 473 Forgejo REST API endpoints across 25 reference categories.

- 78 files, 23,000+ lines, 149 distinct path parameter types
- Every curl command parameterised ({owner}/{repo}/{index}/etc) and
  tested against the live git.cleverthis.com server
- SKILL.md: 917-line entry point with quick-answer curl commands (35),
  jq cheat sheet for chaining API calls, 14 decision trees, 12 critical
  concepts (exclusive labels, lazy mergeability, SHA locking, auto-close
  keywords, search envelope differences, 412 stale-edit protection), full
  HTTP status code table, and environment variable reference
- references/pull-requests/: CRUD, 6 merge styles, automerge, server-side
  rebase without local clone, inline review comments, diff/patch
- references/issues/: comments, reactions, attachments, dependencies,
  time tracking, stopwatches, pinning
- references/labels/: repo + org labels, exclusive label groups,
  GET/POST/PUT/DELETE on issues and PRs
- references/ci-actions/ + references/commit-statuses/: workflow runs,
  dispatch, secrets, variables, quality gate verification
- references/web-interface/ci-logs.md: step-by-step CI log access via
  CSRF web session (not available through REST API)
- references/complex-workflows/: 10 multi-step recipes including
  PR review cycle, issue lifecycle, CI status check, server-side rebase,
  automerge, release workflow, org setup, fork contribution
2026-04-15 00:45:24 -04:00
..

Forgejo Issues API

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

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


List Repository Issues

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

Returns issues (and optionally pull requests) for a repository.

Parameters

Parameter Type In Description
owner string path Required. Repository owner
repo string path Required. Repository name
state string query Filter by state: open, closed, all. Default: open
labels string query Comma-separated list of label names or IDs
milestones string query Comma-separated list of milestone names or IDs
q string query Search string (searches title and body)
type string query Filter by type: issues, pulls. Default: returns both
page integer query Page number (1-based). Default: 1
limit integer query Page size. Default: server default (usually 20, max 50)
sort string query Sort field. Options: oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority. Default: newest first
since string query Only show issues updated after this date (ISO 8601 format, e.g. 2024-01-01T00:00:00Z)
before string query Only show issues updated before this date (ISO 8601 format)
created_by string query Filter by creator username
assigned_by string query Filter by assignee username
mentioned_by string query Filter by mentioned username

Response

Returns 200 with an array of Issue objects. Pagination info is in response headers:

  • X-Total-Count — total number of matching issues
  • Link — standard pagination links (first, prev, next, last)

Examples

# List all open issues
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues?state=open&type=issues"

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

# Search issues by keyword
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues?q=login+bug&state=open"

# Filter by labels (comma-separated label names)
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues?labels=bug,critical"

# Filter by milestone
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues?milestones={milestone_name}"

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

# Issues created by a specific user, sorted by most comments
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues?created_by={username}&sort=mostcomment"

# Issues assigned to a user
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues?assigned_by={username}"

# Combine multiple filters
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues?state=open&labels=bug&milestones=v2.0&sort=priority&limit=50"

Create an Issue

POST /repos/{owner}/{repo}/issues

Parameters

Parameter Type In Description
owner string path Required. Repository owner
repo string path Required. Repository name

Request Body — CreateIssueOption

Field Type Required Description
title string Yes Issue title
body string No Issue body (Markdown supported)
assignees array of strings No Usernames to assign
milestone integer No Milestone ID to associate
labels array of integers No Label IDs to apply
closed boolean No If true, create the issue already closed
due_date string No Due date in ISO 8601 format (e.g. 2025-12-31T00:00:00Z)
ref string No Branch reference for this issue

Response

Returns 201 with the created Issue object.

Examples

# Create a simple issue
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Fix login page redirect"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues"

# Create issue with full details
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Implement OAuth2 support",
    "body": "## Description\n\nWe need to add OAuth2 authentication.\n\n## Tasks\n- [ ] Add OAuth2 provider config\n- [ ] Implement callback handler\n- [ ] Update login page",
    "assignees": ["{assignee1}", "{assignee2}"],
    "milestone": 3,
    "labels": [1, 5, 12],
    "due_date": "2025-03-01T00:00:00Z",
    "ref": "feature/oauth2"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues"

# Create an already-closed issue (useful for record-keeping)
curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Legacy: migrated from old tracker #4521",
    "body": "This issue was migrated from the old tracker and is already resolved.",
    "closed": true
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues"

Get a Single Issue

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

Parameters

Parameter Type In Description
owner string path Required. Repository owner
repo string path Required. Repository name
index integer path Required. Issue index number (the # number shown in the UI)

Response

Returns 200 with an Issue object. Returns 404 if not found.

Key fields in the Issue response object

Field Type Description
id integer Internal database ID
number integer Issue index (same as index param)
title string Issue title
body string Issue body (Markdown)
state string open or closed
labels array Label objects
milestone object Milestone object (or null)
assignees array Assignee user objects
user object Creator user object
comments integer Number of comments
created_at string ISO 8601 creation timestamp
updated_at string ISO 8601 last update timestamp
closed_at string ISO 8601 close timestamp (or null)
due_date string ISO 8601 due date (or null)
pull_request object Present if this is a PR (null for issues)
ref string Branch reference
pin_order integer Pin position (0 if not pinned)
is_locked boolean Whether the issue is locked
original_author string Original author name (for migrated issues)
original_author_id integer Original author ID (for migrated issues)

Examples

# Get issue #42
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

# Get issue and extract specific fields with jq
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}" | jq '{title, state, assignees: [.assignees[].login], labels: [.labels[].name]}'

Edit an Issue

PATCH /repos/{owner}/{repo}/issues/{index}

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 — EditIssueOption

All fields are optional. Only include fields you want to change.

Field Type Description
title string New title
body string New body (Markdown)
assignees array of strings New assignee usernames (replaces all current assignees)
milestone integer New milestone ID. Set to 0 to remove milestone
state string "open" or "closed"
due_date string New due date (ISO 8601)
unset_due_date boolean If true, removes the due date
ref string New branch reference
updated_at string Override the updated timestamp (ISO 8601). Useful for migrations

Response

Returns 201 with the updated Issue object.

Examples

# Update issue title
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Fix login page redirect (updated)"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

# Close an issue
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "state": "closed"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

# Reopen an issue
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "state": "open"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

# Update body, assignees, and milestone
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "## Updated Description\n\nThis is the revised description.",
    "assignees": ["{assignee1}", "{assignee2}"],
    "milestone": 5
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

# Set a due date
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "due_date": "2025-06-15T00:00:00Z"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

# Remove a due date
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "unset_due_date": true
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

# Remove milestone (set to 0)
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "milestone": 0
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

# Change branch reference
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  -H "Content-Type: application/json" \
  -d '{
    "ref": "{branch}"
  }' \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

Delete an Issue

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

Note: This permanently deletes the issue. Requires admin permissions on the repository. In most cases, prefer closing an issue instead.

Parameters

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

Response

Returns 204 (No Content) on success.

Example

# Delete issue #42 (admin only, irreversible)
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}"

Pinned Issues

List Pinned Issues

GET /repos/{owner}/{repo}/issues/pinned

Returns issues that are pinned in the repository, ordered by their pin position.

curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/pinned"

Pin an Issue

POST /repos/{owner}/{repo}/issues/{index}/pin

Pins the issue to the repository. Requires write access.

curl -s -X POST \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/pin"

Returns 204 on success.

Unpin an Issue

DELETE /repos/{owner}/{repo}/issues/{index}/pin

Removes the pin from an issue.

curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/pin"

Returns 204 on success.

Move a Pinned Issue

PATCH /repos/{owner}/{repo}/issues/{index}/pin/{position}

Moves a pinned issue to a new position.

Parameter Type In Description
index integer path Required. Issue index
position integer path Required. New position (1-based)
# Move pinned issue #42 to position 1 (top)
curl -s -X PATCH \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/pin/{position}"

Returns 204 on success.


Issue Subscriptions

List Subscribers

GET /repos/{owner}/{repo}/issues/{index}/subscriptions

Returns users subscribed to the issue.

Parameter Type In Description
page integer query Page number. Default: 1
limit integer query Page size
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/subscriptions"

Check if Current User is Subscribed

GET /repos/{owner}/{repo}/issues/{index}/subscriptions/check

Returns a WatchInfo object with subscribed (boolean), ignored (boolean), reason, created_at, and url.

curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/subscriptions/check"

Subscribe a User

PUT /repos/{owner}/{repo}/issues/{index}/subscriptions/{user}

Subscribes a user to the issue. You can subscribe yourself or others (with appropriate permissions).

Parameter Type In Description
user string path Required. Username to subscribe
# Subscribe user "{username}" to issue #42
curl -s -X PUT \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/subscriptions/{username}"

Returns 200 on success, 304 if already subscribed.

Unsubscribe a User

DELETE /repos/{owner}/{repo}/issues/{index}/subscriptions/{user}
# Unsubscribe user "{username}" from issue #42
curl -s -X DELETE \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/subscriptions/{username}"

Returns 200 on success, 304 if not subscribed.


Issue Timeline

GET /repos/{owner}/{repo}/issues/{index}/timeline

Returns a chronological list of all events on an issue (comments, label changes, assignments, state changes, references, etc.).

Parameters

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

Timeline Event Types

The type field in each event indicates what happened:

Type Description
comment A comment was posted
reopen Issue was reopened
close Issue was closed
label Label was added or removed
milestone Milestone was changed
assignees Assignees were changed
change_title Title was changed
delete_branch Associated branch was deleted
commit_ref A commit referenced this issue
pull_ref A pull request referenced this issue
comment_ref A comment referenced this issue
issue_ref Another issue referenced this one
change_ref Branch reference was changed
head_ref Head reference was changed
due_date Due date was added, changed, or removed
pin Issue was pinned
unpin Issue was unpinned
lock Issue was locked
unlock Issue was unlocked
project_board Issue was added/moved in project board
added_deadline Deadline added
modified_deadline Deadline changed
removed_deadline Deadline removed
review_request Review was requested
merge PR was merged
code Code change event

Examples

# Get full timeline for issue #42
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/timeline"

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

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

# Extract just state-change events with jq
curl -s \
  -H "Authorization: token ${FORGEJO_PAT}" \
  "${FORGEJO_URL}/api/v1/repos/{owner}/{repo}/issues/{index}/timeline" \
  | jq '[.[] | select(.type == "close" or .type == "reopen")]'