Gogs — API Surface#
API types#
Gogs exposes four distinct surfaces: a REST HTTP API (versioned at /api/v1), a Web UI (HTML pages served over HTTP), a Git protocol layer (HTTP smart protocol + SSH), and a CLI (for operators/server management). There is no gRPC or WebSocket API.
REST/HTTP API#
Router:
gopkg.in/macaron.v1— same router instance used by the web UIRoute registration:
apiv1.RegisterRoutes(m *macaron.Macaron)called fromcmd/gogs/web.go:636. All API routes are defined insideinternal/route/api/v1/api.gounder the/api/v1group. Route definitions and handler functions live in separate files named by resource (e.g.,repo_issue.go,repo_branch.go).Middleware chain:
- Outer Macaron middleware (session, CSRF,
context.Contexter) — inherited from parent group context.APIContexter()— builds*context.APIContext(wraps*context.Context, addsc.Org,c.Repo.AccessMode)- Per-route auth guards:
reqToken(),reqBasicAuth(),reqAdmin(),reqRepoWriter(),reqRepoAdmin(),reqRepoOwner() repoAssignment()— resolves:username/:reponameURL params, loads repo, checks read accessorgAssignment()— resolves:orgname/:teamidURL params
- Outer Macaron middleware (session, CSRF,
Authentication:
- Access token:
reqToken()checksc.IsTokenAuth(token passed viaAuthorization: token <sha1>or query param) - HTTP Basic:
reqBasicAuth()checksc.IsBasicAuth - Site admin:
reqAdmin()checksc.User.IsAdmin - No OAuth2 server (Gogs can use GitHub OAuth as login provider but does not act as an OAuth2 server)
- Token creation requires Basic Auth (
/users/:username/tokensguarded byreqBasicAuth())
- Access token:
Key endpoints (all prefixed
/api/v1):Category Method Path Description Misc POST /markdownRender Markdown to HTML Misc POST /markdown/rawRender raw Markdown Users GET /users/searchSearch users Users GET /users/:usernameGet user profile Users GET/POST /users/:username/tokensList / create access tokens (requires Basic Auth) Users GET /users/:username/keysList public keys Users GET /userGet authenticated user Users GET/POST/DELETE /user/emailsManage emails Users GET/PUT/DELETE /user/following/:usernameFollow / unfollow Users GET/POST /user/keysList / create SSH keys Users GET /user/issuesList authenticated user’s issues Repos GET /users/:username/reposList user repositories Repos GET /orgs/:org/reposList org repositories Repos GET/POST /user/reposList / create repos for auth user Repos POST /org/:org/reposCreate org repository Repos GET /repos/searchSearch repositories Repos GET /repos/:username/:reponameGet repository info Repos DELETE /repos/:username/:reponameDelete repository Repos POST /repos/migrateMigrate external repository Repos GET /repos/:u/:r/releasesList releases Repos GET/POST /repos/:u/:r/hooksList / create webhooks Repos PATCH/DELETE /repos/:u/:r/hooks/:idEdit / delete webhook Repos GET/PUT/DELETE /repos/:u/:r/collaborators/:cManage collaborators Repos GET /repos/:u/:r/raw/*Get raw file content Repos GET/PUT /repos/:u/:r/contents/*Get / create/update file contents Repos GET /repos/:u/:r/archive/*Download archive (zip/tar.gz) Repos GET /repos/:u/:r/git/trees/:shaGet git tree Repos GET /repos/:u/:r/git/blobs/:shaGet git blob Repos GET /repos/:u/:r/forksList forks Repos GET /repos/:u/:r/tagsList tags Repos GET /repos/:u/:r/branchesList branches Repos GET /repos/:u/:r/branches/*Get single branch Repos GET /repos/:u/:r/commits/:shaGet single commit Repos GET /repos/:u/:r/commitsList all commits Repos GET/POST /repos/:u/:r/keysList / create deploy keys Issues GET/POST /repos/:u/:r/issuesList / create issues Issues GET/PATCH /repos/:u/:r/issues/:indexGet / edit issue Issues GET/POST /repos/:u/:r/issues/:index/commentsList / create comments Issues PATCH/DELETE /repos/:u/:r/issues/comments/:idEdit / delete comment Issues GET/POST/PUT/DELETE /repos/:u/:r/issues/:index/labelsManage issue labels Labels GET/POST /repos/:u/:r/labelsList / create labels Labels PATCH/DELETE /repos/:u/:r/labels/:idEdit / delete label Milestones GET/POST /repos/:u/:r/milestonesList / create milestones Milestones PATCH/DELETE /repos/:u/:r/milestones/:idEdit / delete milestone Repos (misc) PATCH /repos/:u/:r/issue-trackerEdit issue tracker settings Repos (misc) PATCH /repos/:u/:r/wikiEdit wiki settings Repos (misc) POST /repos/:u/:r/mirror-syncTrigger mirror sync Repos (misc) GET /repos/:u/:r/editorconfig/:filenameGet EditorConfig Orgs GET /users/:username/orgsList user orgs Orgs GET/POST /user/orgsList / create orgs for auth user Orgs GET/PATCH /orgs/:orgnameGet / edit org Orgs GET /orgs/:orgname/teamsList org teams Admin POST /admin/usersCreate user (admin only) Admin PATCH/DELETE /admin/users/:usernameEdit / delete user Admin POST /admin/users/:username/keysAdd public key for user Admin POST /admin/users/:username/orgsCreate org for user Admin POST /admin/users/:username/reposCreate repo for user Admin POST /admin/orgs/:orgname/teamsCreate org team Admin GET /admin/teams/:teamid/membersList team members Admin PUT/DELETE /admin/teams/:teamid/members/:usernameAdd / remove team member Admin PUT/DELETE /admin/teams/:teamid/repos/:reponameAdd / remove team repository API compatibility: Gogs deliberately mirrors the Gitea/GitHub API v3 surface for the core resources (users, repos, issues, webhooks). This enables tooling that targets GitHub’s API to work with Gogs with minimal changes. There is no formal versioning strategy beyond
/v1in the path; no deprecation headers or changelog tracking is visible.
Git protocol API#
Git HTTP smart protocol#
- Routes:
/:username/:reponame/*(GET, POST, OPTIONS), registered outside the session/CSRF middleware group incmd/gogs/web.go:671 - Middleware:
repo.HTTPContexter(repo.NewStore())— authenticates HTTP Git requests (Basic Auth or token), loads repo, checks permissions - Handler:
repo.HTTP— proxies the authenticated request to the systemgit http-backendsubprocess viaos/exec - Go-Get support:
context.ServeGoGet()middleware on the same group handles?go-get=1requests forgo get
Git LFS API#
- Routes:
/:username/:reponame/info/lfs/...(Git LFS Batch + Basic APIs) - Spec: Implements Git LFS v1.0 protocol
- Endpoints:
POST /objects/batch— batch object download/upload requestsGET /objects/basic/:oid— download single LFS objectPUT /objects/basic/:oid— upload single LFS objectPOST /objects/basic/verify— verify uploaded object
- Auth: HTTP Basic Auth or access token; users with 2FA are blocked from LFS via username/password
- Storage backends: Local filesystem only (
lfsx.StorageLocal); config-driven viaconf.LFS.Storage - Registration:
lfs.RegisterRoutes(m.Router)incmd/gogs/web.go:668
Git SSH protocol#
- Not HTTP-based — handled by
internal/ssh(a built-in SSH server listening on a separate port) - Flow: SSH connection → public key lookup in database → exec
gogs serv <key_id>subprocess → permission check → execgit-receive-pack/git-upload-pack - No Go API surface — the SSH protocol boundary is at the OS process level
Web UI#
Router: Macaron with full middleware stack (session, CSRF, i18n, cache, captcha, toolbox)
Auth guards:
reqSignIn(requires login),ignSignIn(optional login — required ifAUTH_REQUIREDis on),reqSignOut(login page redirect),reqAdmin,reqRepoAdmin,reqRepoWriterForm binding:
binding.BindIgnErr— Macaron’s form binding with silent validation errorsKey route groups:
/— home feed (requiresignSignIn)/explore/repos,/explore/users,/explore/organizations— public discovery/install— first-run installer/user/login,/user/sign_up,/user/reset_password— auth flows/user/settings/...— profile, avatar, emails, password, SSH keys, 2FA, applications (tokens), repos, orgs/admin/...— admin dashboard, users, orgs, repos, auth sources, notices/org/...— organization management, teams/repo/create,/repo/migrate,/repo/fork/:repoid— repo creation/:username/:reponame/...— repo views, issues, PRs, releases, wiki, settings, webhooks, branches, commits, diffs, editor, download
Webhook types supported: gogs (generic HTTP POST), Slack, Discord, Dingtalk
Internal API#
GET /-/metrics— Prometheus metrics endpoint (guarded byapp.MetricsFilter())POST /-/api/sanitize_ipynb— Sanitizes a Jupyter Notebook JSON payload (strips unsafe HTML before rendering)
CLI#
Framework:
github.com/urfave/cli/v3Command structure:
Command Subcommands Purpose gogs web— Start the web server (primary command) gogs serv— SSH shell entry point (called by built-in SSH server per connection) gogs hookpre-receive,update,post-receiveGit hook entry points (called by git) gogs admincreate-user,delete-inactivate-users,delete-repository-archives,delete-missing-repositories,git-gc-repos,rewrite-authorized-keys,sync-repository-hooks,reinit-missing-repositoriesOperational maintenance tasks gogs import— Import repositories from a local path gogs backup— Backup Gogs data to a zip archive gogs restore— Restore Gogs data from a backup archive Flag patterns: Global
--config / -cflag shared across all subcommands viaconfigFromLineage()(walkscli.Command.Lineage()because urfave/cli v3 doesn’t automatically propagate parent flags to subcommands). Each subcommand defines its own flags. No environment variable binding.gogs servandgogs hookare not operator-facing — they are called internally by the SSH server and the git process respectively. They perform access control and webhook delivery trigger respectively.
Plugin / Extension system#
Gogs has no formal plugin system. Extension points are:
- Auth providers (
internal/auth/{github,ldap,pam,smtp}) — new providers can be added by implementing the auth provider interface, but this requires a source code change and recompilation, not runtime loading. - Webhook targets — operators can configure any HTTP endpoint as a webhook receiver; the supported sender types (gogs, Slack, Discord, Dingtalk) are hardcoded.
- Git hooks — operators can configure server-side git hooks via the web UI (
/settings/hooks/git) if the feature is enabled. These are arbitrary shell scripts executed by git, not Go code. - Custom templates and static files — the
custom/directory can override any bundled template or static asset. This is a filesystem-level customization, not a Go API.