API

GitHub API

Connect a GitHub account or App, browse repos, branches and files, and manage push webhooks.

The GitHub API connects an Openship instance to GitHub — via the Openship GitHub App, an OAuth account, or the local gh CLI — and then lets you browse the accounts, repositories, branches and files you can deploy from. It also manages the push webhooks that drive auto-deploy. In the dashboard this is the GitHub connection card in Settings and the repo picker in the deploy wizard.

Base path & auth

All paths are relative to your instance, under /api — e.g. https://your-host/api/github/home. Send a personal access token as a bearer header (Authorization: Bearer <token>), created with openship token create. The dashboard uses your session cookie instead. See the API overview for the full auth model and Auth for how GitHub credentials are stored.

Both cloud and self-hosted

This module is mounted on every instance. The local identity routes and every /api/github/sources route are self-hosted only and return 404 on Openship Cloud. Source management additionally requires the active workspace's owner role.

Endpoints

Method & pathPermissionWhat it does
GET /api/github/statusgithub:readGitHub connection status for the org.
GET /api/github/homegithub:readConnection state, accounts, and repos in one call.
GET /api/github/local-statusgithub:readWhether the host has gh CLI auth available (self-hosted only).
GET /api/github/connect/pollgithub:readPoll device-flow login status (self-hosted only).
POST /api/github/connectgithub:writeStart or advance the connection flow.
POST /api/github/installations/claimgithub:writeVerify and bind a self-hosted App setup redirect to the active workspace.
GET /api/github/connect/redirectpublicGitHub OAuth callback — browser navigates here, no session yet.
POST /api/github/disconnectgithub:adminDisconnect one source or all.
GET /api/github/sourcesgithub:admin + ownerList workspace-owned Apps and callback configuration.
POST /api/github/sources/manifestgithub:admin + ownerStart a GitHub.com App manifest flow.
POST /api/github/sources/manifest/convertgithub:admin + ownerConvert the one-time manifest code and save the App.
POST /api/github/sources/manualgithub:admin + ownerVerify and register an existing GitHub/GHE App.
PATCH /api/github/sources/:idgithub:admin + ownerVerify and update App identity, endpoints, or credentials.
DELETE /api/github/sources/:idgithub:admin + ownerRemove local credentials and reconcile its project bindings.
POST /api/github/sources/:id/verifygithub:admin + ownerRecheck the stored App credentials.
POST /api/github/sources/:id/defaultgithub:admin + ownerMake this App the workspace's preferred source.
POST /api/github/sources/:id/installgithub:admin + ownerCreate a one-time, workspace-bound App installation URL.
GET /api/github/reposgithub:listList the connected account's repos (optionally ?owner=).
POST /api/github/reposgithub:writeCreate a repository.
GET /api/github/orgs/:org/reposgithub:listList repositories in an org / account.
GET /api/github/repos/:owner/:repogithub:readGet a repository's metadata.
DELETE /api/github/repos/:owner/:repogithub:adminDelete a repository.
GET /api/github/repos/:owner/:repo/branchesgithub:listList a repository's branches.
GET /api/github/repos/:owner/:repo/clone-tokengithub:readMint a short-lived clone token + git clone command.
GET /api/github/repos/:owner/:repo/filesgithub:listList files/dirs at a path (query: path, branch).
GET /api/github/repos/:owner/:repo/filegithub:readRead a single file's contents (query: file, branch).
GET /api/github/repos/:owner/:repo/webhooksgithub:listList a repo's webhooks.
POST /api/github/repos/:owner/:repo/webhooksgithub:writeRegister (or reuse) the Openship push webhook.
DELETE /api/github/repos/:owner/:repo/webhooksgithub:adminDelete a webhook.

Connection state

GET /api/github/home is the dashboard's single entry point: it returns { state, accounts, repos } in one round trip, filtered to the accounts and repos your member role is allowed to see. GET /api/github/status is narrower — the Settings card's data source — returning { state, accounts, installUrl, cloudUnreachable, customSourcesConfigured }. The last field tells clients that App lifecycle controls belong to the workspace source manager rather than the legacy Openship App connection.

curl https://your-host/api/github/home \
  -H "Authorization: Bearer $OPENSHIP_TOKEN"
# The CLI has no dedicated `github` command; use the raw-request escape hatch:
openship api /github/home

Connect

Starts or advances the connection flow. The response is intentionally mode-agnostic — the frontend just reacts to the flow field:

  • { connected: true } — already connected, nothing to do.
  • { connected: false, flow: "redirect", url } — open url (OAuth handoff or GitHub App install).
  • { connected: false, flow: "device_code", userCode, verificationUri, ... } — self-hosted device login.
  • { connected: false, flow: "terminal", command, message } — run command (e.g. gh auth login) yourself.
POST /api/github/connect

The optional body field source ("oauth" | "cli") forces a specific path when the dashboard shows both the "Connect Openship App" and "Use gh CLI" buttons; omit it to let the server pick based on the instance's auth mode.

curl -X POST https://your-host/api/github/connect \
  -H "Authorization: Bearer $OPENSHIP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"source":"oauth"}'

Disconnect

POST /api/github/disconnect

Body (or ?source=): source is "oauth", "cli", or "all" (default "all"). This drops Openship's stored credentials for that source; it does not uninstall the GitHub App — that happens only when you remove it from github.com (Openship reacts to the uninstall webhook).

openship api /github/disconnect -X POST -d '{"source":"cli"}'

This endpoint does not delete a workspace-owned source. Use DELETE /api/github/sources/:id for that explicit owner-only operation.

Workspace-owned GitHub App sources

These endpoints are available only on self-hosted instances. All reads are sanitized: private keys, client secrets, webhook secrets, and their encrypted envelope are never returned.

List sources

openship api /github/sources

Returns { data, configuration }. configuration contains publicReady, publicUrl, setupUrl, and webhookUrl. Each source in data contains public App metadata, health, default status, and its claimed installations.

One-click manifest

Start the GitHub.com flow with:

openship api /github/sources/manifest -X POST -d '{"name":"Acme GitHub"}'

The response contains { url, manifest }. Submit manifest as a JSON string in a form field named manifest to url; the dashboard does this automatically. GitHub redirects to the configured setup page with code and state, which must be sent to:

POST /api/github/sources/manifest/convert
{ "code": "…", "state": "…" }

Conversion consumes the user/workspace-bound state exactly once, encrypts GitHub's generated credentials, and returns { data, installUrl }.

Manual registration and GitHub Enterprise Server

POST /api/github/sources/manual

Prop

Type

The API signs an App JWT and verifies /app before saving the source. It returns { data, installUrl }.

PATCH /api/github/sources/:id accepts the same identity and endpoint fields, all optional. Omitted secret fields retain their existing encrypted values. App ID or API URL cannot change while the source has claimed installations. POST .../verify refreshes public App metadata and marks bad credentials as needing attention.

Making a source default atomically rebinds existing projects for every GitHub owner installed on that source. Deleting a source promotes another active source when possible and rebinds affected projects; projects with no replacement lose their installation binding and auto-deploy is disabled. Deleting locally does not uninstall the GitHub App itself.

Create a repository

POST /api/github/repos

Prop

Type

curl -X POST https://your-host/api/github/repos \
  -H "Authorization: Bearer $OPENSHIP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"my-app","private":true,"owner":"acme"}'
openship api /github/repos -X POST -d '{"name":"my-app","private":true}'

Returns 201 with { data } (the created repository).

Browse repos, branches and files

List repos for the connected account (?owner= narrows to one account), or for a named org via GET /api/github/orgs/:org/repos. Both return { data: [...] } filtered to repos your role may see.

# Repos for one owner
openship api /github/repos --query owner=acme

# Branches for a repo
openship api /github/repos/acme/my-app/branches

# One repo, with its branches inlined
openship api /github/repos/acme/my-app --query branches=true

File browsing reads directly from GitHub:

  • GET /api/github/repos/:owner/:repo/files — directory listing. Query: path (default repo root) and branch.
  • GET /api/github/repos/:owner/:repo/file — one file's contents. Query: file (default package.json) and branch. .json files are parsed and returned as JSON.
curl "https://your-host/api/github/repos/acme/my-app/file?file=package.json&branch=main" \
  -H "Authorization: Bearer $OPENSHIP_TOKEN"

Webhooks

POST /api/github/repos/:owner/:repo/webhooks registers the Openship push webhook on the repo (or reuses an existing one) so pushes trigger auto-deploy. It takes no request body — the target repo comes from the path. GET lists the repo's hooks. To remove one, DELETE with the hook id:

DELETE /api/github/repos/:owner/:repo/webhooks

Prop

Type

openship api /github/repos/acme/my-app/webhooks -X DELETE -d '{"hookId":123456}'

Clone token

GET /api/github/repos/:owner/:repo/clone-token mints a short-lived (under an hour) GitHub App installation token and returns { token, cloneUrl, command } — a ready-to-run git clone. This is the same credential the build pipeline clones with, and is available only when the Openship GitHub App is installed for the owner.

Errors you might see

400 — Not connected to GitHub

Returned by the repo-listing routes when no usable GitHub source (App installation, OAuth account, or gh CLI) is configured. Connect first with POST /api/github/connect, then retry.

409 — no installation token

clone-token needs a GitHub App installation for the owner. In gh CLI or PAT modes there is no installation token, so this route 409s. Install the Openship GitHub App on that account to use clone tokens.

503 — cloud_unreachable

On a self-hosted instance connected to Openship Cloud, GitHub OAuth and App-install URLs are resolved through openship.io. If the SaaS is unreachable, connect returns 503 rather than a dead install link. Check network / the cloud connection in Settings, then retry.

An instance configured with its own self-hosted GitHub App does not use this cloud proxy; GITHUB_AUTH_MODE=auto selects the complete local App configuration first.

404 on a repo route

The :owner/:repo isn't visible to the active GitHub source (private, not granted to your member role, or does not exist). Confirm the repo appears in GET /api/github/home first.

On this page