Migrate to the normalized /api/v1 API surface
Use this guide when you need to update existing automation for the proxy’s normalized HTTP contract.
What changed
Section titled “What changed”Treat Forgejo Proxy as the canonical API surface for this ecosystem:
- API families now live under
/api/v1/... - Root-path exceptions are intentionally narrow:
/healthand/activitypub/** thfg apialways joins your path onto the active/api/v1base URL- Project write flows use the normalized
/api/v1/projects/...routes instead of legacy/api/v1/proxy/...paths
This is a breaking cleanup for callers that hard-coded the old paths.
Update path patterns
Section titled “Update path patterns”Use this mapping when migrating scripts and operator runbooks.
| Before | After | Notes |
|---|---|---|
thfg api /repos/owner/repo with unclear base-path assumptions | thfg api /repos/owner/repo relative to /api/v1 | The CLI path stays the same, but the contract is now explicit. |
curl "$PROXY_URL/api/v1/proxy/projects/$PROJECT/issues" | curl "$PROXY_URL/api/v1/projects/$PROJECT/columns/$COLUMN/cards" | The normalized API is column-scoped. Pick the target column explicitly. |
curl "$PROXY_URL/api/v1/proxy/projects/$PROJECT/columns/$COLUMN/move" | curl "$PROXY_URL/api/v1/projects/$PROJECT/columns/$COLUMN/cards" | Posting a card to the target column is the normalized move/add contract. |
| Root-path custom API routes | /api/v1/... | Keep only /health and /activitypub/** at the root. |
thfg api /activitypub/... | thfg activitypub ... or curl "$PROXY_URL/activitypub/..." | ActivityPub stays outside /api/v1. |
Update thfg usage
Section titled “Update thfg usage”Generic API calls
Section titled “Generic API calls”thfg api now has one clear rule: pass a path relative to /api/v1.
# Read a repo through the normalized proxy API surfacethfg api /repos/myorg/myrepo
# Fetch all pages from an array endpointthfg api /user/repos --paginate
# Inspect the merged proxy contractthfg api specRoot exceptions
Section titled “Root exceptions”Do not use thfg api for root-path resources.
# Health stays at the rootcurl "$PROXY_URL/health"
# ActivityPub stays at the root toothfg activitypub repo actor myorg/myrepoUpdate project automation
Section titled “Update project automation”Legacy project write endpoints hid the destination column behind /api/v1/proxy/... routes. The normalized API makes the target column explicit.
Add an issue to a project column
Section titled “Add an issue to a project column”curl -s -X POST \ -H "Authorization: token $FORGEJO_TOKEN" \ -H "X-Webui-Username: $FORGEJO_WEBUI_USERNAME" \ -H "X-Webui-Password: $FORGEJO_WEBUI_PASSWORD" \ -H "Content-Type: application/json" \ -d '{"issue_id":7,"owner":"forgejo-proxy","repo":"forgejo-proxy"}' \ "$FORGEJO_PROXY_URL/api/v1/projects/2/columns/5/cards"Move a card to another column
Section titled “Move a card to another column”Use the same normalized endpoint, but point it at the new column.
curl -s -X POST \ -H "Authorization: token $FORGEJO_TOKEN" \ -H "X-Webui-Username: $FORGEJO_WEBUI_USERNAME" \ -H "X-Webui-Password: $FORGEJO_WEBUI_PASSWORD" \ -H "Content-Type: application/json" \ -d '{"issue_id":7,"owner":"forgejo-proxy","repo":"forgejo-proxy"}' \ "$FORGEJO_PROXY_URL/api/v1/projects/2/columns/7/cards"Resolve the column first
Section titled “Resolve the column first”If an older script relied on the proxy choosing a default column implicitly, resolve the column up front:
thfg project columns --id 2 --output-format json | jq '.[] | {id, title}'Validate the migration
Section titled “Validate the migration”Run these checks after updating your scripts:
# Contract still loadsthfg api spec > /dev/null
# Updated path worksthfg api /repos/myorg/myrepo > /dev/null
# Root exception still workscurl "$PROXY_URL/health"