Skip to content

GitHub integration

These endpoints back the GitHub integration: logging work from a GitHub issue, mapping repositories to projects, and configuring the instance’s GitHub App. The per-user account link (/me/github) lives on the Account page.

POST /api/v1/github/log-work scope: write

Logs a work entry against a GitHub issue for a client that only knows its git remotes. The server normalizes the remotes, resolves the repo→project mapping, parses the duration/date in the caller’s timezone, enriches with the issue title and labels, and links recent agent sessions that point at the issue. Rate-limited on the ingest path. Returns 404 with a help message when no remote is a mapped github.com repo.

Request body

Field Type Required Description
remotes string[] yes Git remote fetch URLs, verbatim (1–10). The first that maps to a project wins.
issueNumber integer yes The issue (or pull request) number.
args string yes The raw <duration> [date] string, exactly as typed (≤ 200 chars).
curl -X POST "https://<your-instance>/api/v1/github/log-work" \
  -H "Authorization: Bearer spantail_pat_yourtoken" \
  -H "Content-Type: application/json" \
  -d '{
    "remotes": ["git@github.com:acme/website.git"],
    "issueNumber": 123,
    "args": "2h yesterday"
  }'

Returns 201 Created. degraded is true when the App was unreachable and the entry carries only the bare issue reference (no title or labels). entry is a full work entry.

A mapping says “work logged from this repository belongs to this project”. Repo full names are unique instance-wide. The collection is nested under a workspace.

GET /api/v1/workspaces/:id/github-mappings scope: read

Any workspace member. Returns the workspace’s mappings.

curl "https://<your-instance>/api/v1/workspaces/wrk_demo/github-mappings" \
  -H "Authorization: Bearer spantail_pat_yourtoken"

source is installation when the App covers the repo, or manual for a hand-entered mapping.

POST /api/v1/workspaces/:id/github-mappings scope: admin

Workspace admin. Maps a repository to a project in this workspace. Works without the App (records a manual mapping); with the App, the repo id and installation are resolved server-side. A repo already mapped anywhere returns 409 conflict; a project outside the workspace returns 400.

Request body

Field Type Required Description
repoFullName string yes owner/repo (case-insensitive).
projectId string yes Project in this workspace to map to.

Returns 201 Created with the created mapping (same shape as the list rows).

DELETE /api/v1/workspaces/:id/github-mappings/:mappingId scope: admin

Workspace admin. Removes the mapping. Returns 204 No Content.

GET /api/v1/workspaces/:id/github-mappings/unmapped-repos scope: admin

Workspace admin. Repositories the App’s installations cover that no one has mapped yet — the picker’s source. Read live from GitHub; empty ({ "repos": [] }) without an App.

{ "repos": [ { "repoId": 42, "fullName": "acme/website", "private": true } ] }

Every instance registers its own GitHub App. These endpoints report and manage it. Secrets never leave the server — only display data and toggles are returned.

GET /api/v1/instance/github/enabled auth required

Any signed-in user. Gates the “Connect GitHub” card. Returns { "enabled": true }.

GET /api/v1/instance/github scope: admin

Instance admin. Returns the App’s display fields and its installations.

curl "https://<your-instance>/api/v1/instance/github" \
  -H "Authorization: Bearer spantail_pat_yourtoken"

app is null before an App is registered.

POST /api/v1/instance/github/app/manifest scope: admin

Instance admin. Starts the GitHub App Manifest flow: returns the GitHub form target and the manifest JSON the SPA posts to GitHub, and binds the flow to the caller’s browser. GitHub then calls back to /api/github/setup, which stores the App’s credentials encrypted. There is nothing to copy or paste.

Request body

Field Type Required Description
owner string | null yes The organization login to register the App under, or null for the caller’s personal account.

DELETE /api/v1/instance/github/app scope: admin

Instance admin. Removes the App configuration. Mappings survive, so #N log-work keeps working in the degraded, link-only form. Returns 204 No Content.

GET /api/v1/instance/github/installations/:installationId/repos scope: admin

Instance admin. Read live from GitHub — the repositories a given installation can reach.

Connecting your own GitHub account (so comments log work as you) is a per-user action — see GitHub connection on the Account page.