GitHub
Verified request, response and authorization contracts.
GitHub installations belong to a workspace. Connecting requires a human owner/admin and verified GitHub account ownership. Repository access is checked again when credentials or PR actions are requested. Run-scoped GitHub credentials are worker integration details and are intentionally not examples for customer PAT clients.
Connect starts with GitHub user authorization. Melso finds the installations of its GitHub App that the member owns: their personal account, or an organization where they are an active admin. The member confirms which of those accounts to connect, since one may already serve another company; with none, GitHub's installation page opens next and the account installed there is connected. GitHub returns the browser to Melso after installing, and after an owner changes repository access when the App's "Redirect on update" setting is on.
A coding Run gets a token for each GitHub owner among its repositories: contents and pull requests write, issues write, and read access to checks, statuses, Actions, deployments and environments, each as far as the installation approved it. It never gets Workflows or Administration access. The chat's command VM gets read-only access to the company's repositories and those on Areas the member can open; when the member's Vault holds a GH_TOKEN or GITHUB_TOKEN, the VM uses that token instead.
Examples use the environment variables from Overview. UUID placeholders must be replaced with your own IDs.
GET /api/workspaces/{workspaceId}/github/installations
Auth: Workspace member with access to this resource.
Request: Path: workspace UUID.
Response: {installations:GitHubInstallationResponse[],can_manage:boolean,configured:boolean,repository_browse_configured:boolean,configuration_error:string}; management identifiers are redacted for non-admins and can_manage indicates management access.
Status: 200; 503 GitHub authorization unavailable. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/github/installations" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"GET /api/workspaces/{workspaceId}/github/connect
Auth: Human workspace owner/admin; Run/MCP actors rejected.
Request: Optional query return_to:"github"|"repositories"|"chat", the page GitHub returns to. Optional mode:"install" opens GitHub's installation page to add another account instead of finding existing installations.
Response: {configured:boolean,url?:string,error?:string}. Open url in the member's browser; it expires with its one-use state after 10 minutes.
Status: 200; 400 invalid return target or mode; 403 human admin required. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/github/connect" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"GET /api/workspaces/{workspaceId}/github/connect/candidates
Auth: The human workspace owner/admin who authorized on GitHub.
Request: Query state:string, the github_choose value GitHub returned to the page.
Response: {candidates:{installation_id:integer,account_login:string,account_type:string,account_avatar_url?:string}[],return_to:string}. The owner proof stays on the server.
Status: 200; 400 invalid state; 403 human admin required; 404 no pending choice. Authentication and resource-access errors follow Overview.
POST /api/workspaces/{workspaceId}/github/connect/complete
Auth: The human workspace owner/admin who authorized on GitHub.
Request: {state:string,installation_ids:integer[]}, installations from the pending choice.
Response: Empty.
Status: 204; 400 installation outside the choice; 403 access revoked; 404 no pending choice; 409 the choice expired or an installation changed. Authentication and resource-access errors follow Overview.
GET /api/workspaces/{workspaceId}/github/installations/{installationId}/repositories
Auth: Workspace owner/admin, or a workspace API key with admin scope.
Request: Path: workspace and installation record UUIDs. Query page?:integer (default 1), per_page?:integer (default/max 100).
Response: {repositories:GitHubRepositoryResponse[],total_count:integer,next_page:integer|null}.
Status: 200; 403 reconnect required; 404 installation mismatch; 502 GitHub request failed; 503 GitHub unavailable. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/github/installations/$INSTALLATION_ID/repositories" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"DELETE /api/workspaces/{workspaceId}/github/installations/{installationId}
Auth: Workspace owner/admin.
Request: Path: workspace and installation record IDs.
Disconnects the account from this workspace. When no other workspace uses the installation, Melso also uninstalls its GitHub App from the account, so GitHub stops sending its webhooks and its tokens stop working. Mirrored pull requests and Task links stay.
Response: Empty.
Status: 204; 404 this workspace has no such installation; 502 GitHub did not uninstall the App, and the installation stays connected. Authentication and resource-access errors follow Overview.
curl -sS -X DELETE "$MELSO_URL/api/workspaces/$WORKSPACE_ID/github/installations/$INSTALLATION_ID" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"GET /api/tasks/{id}/pull-requests
Auth: Workspace member with access to this resource.
Request: Path: Task ID.
Response: {pull_requests:GitHubPullRequestResponse[]}.
Status: 200. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/tasks/$ID/pull-requests" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"GET /api/pull-requests/resolve
Auth: Workspace member with access to this resource.
Request: Query owner:string, repo:string, number:integer required.
Response: {id:UUID} for an authorized linked PR.
Status: 200; 400 missing/invalid query; 404 no accessible PR. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/pull-requests/resolve?owner=example&repo=product&number=1" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"GET /api/pull-requests/{id}
Auth: Workspace member with access to this resource.
Request: Path: PR record UUID.
Response: GitHubPullRequestDetailResponse.
Status: 200; 404 inaccessible PR. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/pull-requests/$ID" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"POST /api/pull-requests/{id}/merge
Auth: Workspace owner/admin (a person), or a workspace API key with admin scope. Run and MCP credentials are rejected, and tasks API keys get 403 workspace_key_scope; can_merge on the PR detail reports whether the caller may merge.
Request: merge_method?:"merge"|"squash"|"rebase", commit_title?:string, commit_message?:string.
Response: {merged:boolean,sha:string,pull_request:GitHubPullRequestResponse}.
Status: 200; 400 invalid method; 403 denied; 409 merge/check conflict; 502 GitHub failure. Authentication and resource-access errors follow Overview.
This action merges the PR. Use it only after review and authorization; closing keywords may also complete linked Tasks.
curl -sS -X POST "$MELSO_URL/api/pull-requests/$ID/merge" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID" \
-H "Content-Type: application/json" -d '{"merge_method":"squash"}'GitHubPullRequestDetailResponse
Source: server/internal/handler/github_pr_detail.go (GitHubPullRequestDetailResponse). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.
| Field | JSON type |
|---|---|
body | string |
commits_count | integer |
checks | GitHubPullRequestCheckResponse[] |
preferred_merge_method | string |
allow_merge_commit | boolean |
allow_squash_merge | boolean |
allow_rebase_merge | boolean |
can_merge | boolean |
review_decision | string (may be omitted) |
review_task | GitHubPRReviewTaskResponse or null (may be omitted) |
GitHubInstallationResponse
Source: server/internal/handler/github.go (GitHubInstallationResponse). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.
| Field | JSON type |
|---|---|
id | string |
workspace_id | string |
installation_id | integer or null (may be omitted) |
requires_reconnect | boolean |
account_login | string |
account_type | string |
account_avatar_url | string or null |
created_at | string |
GitHubPullRequestResponse
Source: server/internal/handler/github.go (GitHubPullRequestResponse). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.
| Field | JSON type |
|---|---|
id | string |
provider | string |
workspace_id | string |
repo_owner | string |
repo_name | string |
number | integer |
title | string |
state | string |
html_url | string |
branch | string or null |
head_sha | string or null: the head commit Melso last mirrored for the pull request; null when unknown |
author_login | string or null |
author_avatar_url | string or null |
merged_at | string or null |
closed_at | string or null |
pr_created_at | string |
pr_updated_at | string |
mergeable_state | string or null |
mergeable | string or null |
merge_state_status | string or null |
snapshot_available | boolean or null (may be omitted) |
checks_rollup | string or null |
checks_conclusion | string or null |
checks_total | integer |
checks_passed | integer |
checks_failed | integer |
checks_running | integer |
checks_pending | integer |
failed_check_names | string[] |
snapshot_stale | boolean |
snapshot_fetched_at | string or null |
snapshot_head_sha | string or null: the head commit the stored CI and merge snapshot describes. It equals head_sha exactly when snapshot_available is true; another commit means the snapshot is for an older head, and its fields stay empty until one for the current head arrives. Null before the first snapshot and when snapshots are not configured. Always null for other providers, whose check counts describe head_sha |
additions | integer |
deletions | integer |
changed_files | integer |
GitHubRepositoryResponse
Source: server/internal/handler/github.go (GitHubRepositoryResponse). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.
| Field | JSON type |
|---|---|
id | integer |
full_name | string |
html_url | string |
clone_url | string |
description | string or null |
private | boolean |
archived | boolean |
default_branch | string |
GitHubPullRequestDetailResponse also includes every GitHubPullRequestResponse field.