Overview
The GitHub Integration API lets you link a GitHub repository to a registry entry so that default-branch pushes and matching Git tags automatically publish updated skill versions. It requires a Pro plan and the registry:push permission.
For the operator setup flow, see Set up GitHub integration.
The integration works in three steps:
- Install the SelfTune GitHub App on your GitHub account or organization
- Bind the installation to your SelfTune org
- Connect a specific repository to a registry entry
SelfTune can read repository contents and publish into the registry by
default. If you grant the optional Checks and Commit statuses
permissions, it can also post publish results back to GitHub. It still does
not open pull requests or push commits back to GitHub.
Settings
Read org GitHub settings
Returns org-level GitHub write-back policy.
GET /api/v1/github/settings
Authorization: Bearer {API_KEY}
Response
{
"write_back_mode": "checks"
}
Update org GitHub settings
POST /api/v1/github/settings
Content-Type: application/json
Authorization: Bearer {API_KEY}
{
"write_back_mode": "checks"
}
write_back_mode values:
off
checks
checks_and_prs
Authentication
All endpoints require:
Authorization: Bearer {API_KEY}
Installations
List installations
Returns all GitHub App installations bound to your org.
GET /api/v1/github/installations
Authorization: Bearer {API_KEY}
Response
{
"installations": [
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"installation_id": 12345678,
"account_login": "my-org",
"account_type": "Organization",
"suspended": false,
"created_at": "2026-04-01T10:00:00Z",
"updated_at": "2026-04-01T10:00:00Z"
}
]
}
Bind installation
Records a GitHub App installation so SelfTune can access repositories under that account.
Call this after the user completes the GitHub App installation flow and you have the installation_id from GitHub’s redirect callback.
POST /api/v1/github/installations
Content-Type: application/json
Authorization: Bearer {API_KEY}
{
"installation_id": 12345678,
"account_login": "my-org",
"account_type": "Organization"
}
Request fields
| Field | Type | Required | Notes |
|---|
installation_id | Integer | Yes | GitHub App installation ID from the OAuth callback |
account_login | String | Yes | GitHub username or org name (max 100 chars) |
account_type | "User" | "Organization" | Yes | Type of GitHub account |
suspended | Boolean | No | Whether the installation is suspended; defaults to false |
Response
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"installation_id": 12345678,
"account_login": "my-org",
"account_type": "Organization",
"suspended": false,
"created_at": "2026-04-01T10:00:00Z",
"updated_at": "2026-04-01T10:00:00Z"
}
Repositories
List repositories
Returns repositories accessible through a given installation.
GET /api/v1/github/repos?installation_id=12345678
Authorization: Bearer {API_KEY}
Query parameters
| Parameter | Type | Required | Notes |
|---|
installation_id | Integer | Yes | The installation to list repos for |
Response
{
"repos": [
{
"id": 987654321,
"full_name": "my-org/my-skill-repo",
"owner": "my-org",
"name": "my-skill-repo",
"visibility": "public",
"default_branch": "main",
"html_url": "https://github.com/my-org/my-skill-repo",
"pushed_at": "2026-04-10T08:00:00Z",
"connected_elsewhere": false
}
]
}
connected_elsewhere is true when another SelfTune org already has a connection to this repo.
Connections
A connection links one repository to one registry entry. When a git tag matching tag_pattern is pushed, SelfTune publishes a new version of that entry automatically.
List connections
GET /api/v1/github/connections
Authorization: Bearer {API_KEY}
Response
{
"connections": [
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"org_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"entry_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"entry_name": "my-skill",
"installation_id": 12345678,
"repo_owner": "my-org",
"repo_name": "my-skill-repo",
"repo_full_name": "my-org/my-skill-repo",
"default_branch": "main",
"skill_path": ".",
"auto_publish": true,
"write_back_enabled": false,
"tag_pattern": "v*",
"created_by": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"created_at": "2026-04-01T10:00:00Z",
"updated_at": "2026-04-01T10:00:00Z",
"last_attempt": null
}
]
}
Create connection
Links a repository to a registry entry. After creation, pushes to the configured default branch publish commit-based prerelease versions and tags that match tag_pattern publish release versions.
POST /api/v1/github/connections
Content-Type: application/json
Authorization: Bearer {API_KEY}
{
"entry_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"installation_id": 12345678,
"repo_full_name": "my-org/my-skill-repo",
"default_branch": "main",
"skill_path": ".",
"auto_publish": true,
"write_back_enabled": false,
"tag_pattern": "v*"
}
Request fields
| Field | Type | Required | Default | Notes |
|---|
entry_id | UUID | Yes | — | The registry entry to publish to |
installation_id | Integer | Yes | — | The bound GitHub installation that has access to the repo |
repo_full_name | String | Yes | — | owner/repo format (e.g. my-org/my-skill) |
default_branch | String | No | "main" | Branch used for non-tag pushes |
skill_path | String | No | "." | Path within the repo to the skill root; use "." for repo root |
auto_publish | Boolean | No | true | Whether tag pushes automatically publish a new version |
write_back_enabled | Boolean | No | false | Whether this connection should post commit statuses and check-runs when org mode allows it |
tag_pattern | String | No | "v*" | Glob pattern for tags that trigger publishing (e.g. "v*" matches v1.0.0) |
Response
Returns the created connection object (same shape as list items above) with HTTP 201.
Update connection
Updates connection-level write-back policy.
PATCH /api/v1/github/connections/{id}
Content-Type: application/json
Authorization: Bearer {API_KEY}
{
"write_back_enabled": true
}
Response
Returns the updated connection object.
Delete connection
Removes the connection. Existing published versions are not affected.
DELETE /api/v1/github/connections/{id}
Authorization: Bearer {API_KEY}
Response
Sync connection
Manually triggers a sync for an existing connection, re-reading the latest state of the repository. Useful for backfilling or re-publishing after a configuration change.
POST /api/v1/github/connections/{id}/sync
Authorization: Bearer {API_KEY}
Response
Returns HTTP 200 with:
{
"connection_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "published",
"version": "0.0.0-github.abcdef1",
"source_ref": "abcdef1234567890fedcba9876543210abcdef12",
"published_at": "2026-04-14T12:00:00Z",
"message": "Published 0.0.0-github.abcdef1 from acme/skills.",
"write_back_status": "success",
"check_run_id": "123456789",
"status_context": "selftune/publish/abcd1234"
}
write_back_status values:
disabled
pending
success
failed
unsupported
Registry entry fields
When creating a registry entry via the push API, two new optional fields are available:
| Field | Type | Default | Notes |
|---|
visibility | "public" | "org" | "unlisted" | "org" | Who can discover this entry in the registry |
source_repo | String | — | The owner/repo this entry is sourced from |
Visibility options:
"public" — listed in the public registry and discoverable by anyone
"org" — visible only within your SelfTune org
"unlisted" — accessible by direct link but not listed publicly
Version source tracking
Published versions now include provenance fields indicating how they were created:
| Field | Type | Notes |
|---|
source | "cli" | "github" | "github-direct" | How the version was published |
source_ref | String | null | Git ref (tag or SHA) the version was built from |
source_repo | String | null | owner/repo the version came from |
These fields appear in version responses from the registry API and are set automatically when publishing via GitHub.