Providers

Forgejo and Codeberg

Use Codeberg and self-hosted Forgejo instances: issues, pull requests, notifications, releases and webhooks.

The Forgejo provider covers Codeberg and self-hosted Forgejo instances. It reads and writes issues and pull requests. It also covers notifications, commit statuses, releases, repository contents and repository and organisation webhooks. The Gitea provider uses the same implementation.

DetailValue
Importforges/forgejo
Factoriesforgejo(), forgejoLite()
Authtoken, anonymous

Authentication

The provider accepts an access token. OAuth2 applications on Forgejo issue user tokens, which you pass the same way:

import { forgejo } from 'forges/forgejo'

const forge = forgejo({
  auth: { type: 'token', token: process.env.CODEBERG_TOKEN! },
}).create()

Without auth, the provider makes anonymous public reads.

Instance

The default instance is https://codeberg.org. For a self-hosted instance, set baseUrl to the root of the instance. The provider appends /api/v1:

forgejo({ baseUrl: 'https://git.example.com', auth })

refreshCapabilities() reads the instance version from /version.

Marking notifications done

Forgejo notifications have a read state but no done state. markDone() is 'emulated': it marks the notification read and unsubscribes from the thread.

Merging

If you don't pass method, merge() reads the merge styles that the repository allows. When exactly one style is allowed, it uses that style. When several are allowed, it throws MergeMethodRequiredError. With whenChecksPass, Forgejo merges the pull request after its checks succeed.

Reviews

Reviews are native. createReview() without an event creates a pending review, and submitReview() submits it. The API doesn't expose whether a review conversation is resolved, so resolveReviewThread() is unavailable.

Checks and CI

checks.list() reads commit statuses, and checks.report() writes them. Forgejo Actions has no stable API for runs and jobs, so checks.rerun() and the ci methods are unavailable.

Changed files

threads.files() and contents.compare() return line counts for each file, but no patch. Forgejo serves diffs only for a whole pull request.

search.threads() searches across repositories. It has no involves filter and returns results newest first. Passing involves adds a filter_unsupported warning. Passing a sort other than relevance adds a sort_unsupported warning.

Webhooks

Set webhookSecret to the secret configured on the hook:

const forge = forgejo({
  webhookSecret: process.env.FORGEJO_WEBHOOK_SECRET,
}).create()

const events = await forge.webhooks.ingest({
  headers: request.headers,
  body: await request.text(),
})

Forgejo sends these headers with each delivery:

HeaderContent
X-Forgejo-SignatureThe hex HMAC-SHA256 of the body
X-Forgejo-EventThe event name
X-Forgejo-DeliveryThe delivery ID

The provider also accepts the X-Gitea-* version of each header.

A label delivery doesn't say which labels were added or removed. A changed label set becomes a label event with the edited action, and removing every label becomes one with the unlabelled action.

webhooks.deliveries() and webhooks.redeliver() are unavailable.

Recording fixtures

CODEBERG_TOKEN=... FIXTURE_FORGEJO_REPO=owner/repo \
FIXTURE_FORGEJO_PULL=1 pnpm record-fixtures forgejo

To add an issue, set FIXTURE_FORGEJO_ISSUE. To record another instance, set CODEBERG_BASE_URL.

Capabilities

Generated by pnpm capability-matrix; do not edit by hand.

CapabilitySupport
experimental❌
sources.poll✅
sources.webhook✅
sources.subscribe❌
repos.get✅
users.get✅
repos.list✅
repos.labels✅
repos.createLabelexperimental
repos.milestones✅
repos.collaborators✅
repos.permissionForexperimental
repos.addCollaboratorexperimental
repos.assignableUsers✅
repos.reviewerCandidatesexperimental
threads.getissue, PR, commit (experimental)
threads.listissue, PR
threads.getMany✅
comments.listissue, PR
comments.editissue (experimental), PR (experimental)
comments.deleteissue (experimental), PR (experimental)
reactions.listissue, PR
notifications.list✅
notifications.markRead✅
notifications.markDoneemulated
notifications.unsubscribe✅
notifications.markAllRead✅
notifications.markAllDone❌
notifications.unreadCount✅
writes.commentissue (experimental), PR
writes.upsertCommentissue (emulated), PR (emulated)
writes.closeissue (experimental), PR
writes.reopenissue (experimental), PR
writes.createissue (experimental), PR (experimental)
writes.updateissue (experimental), PR (experimental)
writes.setLabelsissue (experimental), PR (experimental)
writes.addLabelsissue (experimental), PR (experimental)
writes.removeLabelsissue (experimental), PR (experimental)
writes.setMilestoneissue (experimental), PR (experimental)
writes.reactissue (experimental), PR (experimental)
writes.setAssigneesissue (experimental), PR (experimental)
writes.requestReviewPR (experimental)
writes.merge✅
writes.approveAndMerge✅
writes.transfer❌
writes.markDuplicate❌
subscriptions.getissue, PR
subscriptions.setissue, PR
installations❌
checks.threadPR
checks.list✅
checks.reportexperimental
checks.rerun❌
ci.runs❌
ci.run❌
ci.jobs❌
ci.log❌
contents.file✅
contents.tree✅
contents.branches✅
contents.tags✅
contents.resolveRef✅
contents.commits✅
contents.commit✅
contents.compare✅
contents.threadFiles✅
contents.threadCommits✅
reviews.list✅
reviews.createexperimental
reviews.submitexperimental
reviews.approveexperimental
reviews.resolveThread❌
releases.list✅
releases.get✅
releases.latest✅
releases.getByTag✅
releases.downloadAssetexperimental
webhooks.listexperimental
webhooks.createexperimental
webhooks.updateexperimental
webhooks.deleteexperimental
webhooks.rotateSecretexperimental
webhooks.deliveries❌
webhooks.redeliver❌
search.threads✅
search.repos✅
search.commits❌
securityAlerts❌
eventKindsnative
authtoken, anonymous
limitsunknown
Copyright © 2026