Start attaching a repository to GitHub
POST/api/repos/{owner}/{repo}/github-attach
startGithubAttach
Starts an **attach** (ADR 0136): the repository becomes GitHub-synced with the GitHub repository its GitHub App binding names, keeping its own issues and every local commit. This only creates the attach run, in `planning`; a background worker computes the plan, which `GET …/github-attach` then previews and `POST …/github-attach/confirm` confirms. Nothing is written to GitHub or to the repository's refs here. Requires repository **admin**, from a **signed-in session** or an access token with **no workspace or repository lock** (ADR 0162; its scopes must reach repository admin): a locked token is refused with `403 forbidden` even when its owner is an admin, because the run records who asked. `expected_github_repository_id` must be the GitHub repository the binding names (it guards a re-bind between reading and clicking); a missing or different binding is `409 relationship_conflict`. A deployment that does not offer GitHub sync, or a relationship that can never be attached (`github_backup`), is `409 relationship_unavailable`; a repository already synced (`github_managed`) is `409 relationship_conflict` — detach it first. A repository whose sync was turned off or cut over (`neosource_managed`, either `authority_handoff`) can be attached again. **Idempotent**: while an attach to the same GitHub repository is in flight, this returns its `run_id` and creates nothing; one to a different repository is `409 relationship_conflict`.
Requires authentication using a bearer token or a session cookie — see tokens and scopes.
curl
curl -X POST 'https://neosource.dev/api/repos/OWNER/REPO/github-attach' \
-H 'Authorization: Bearer $NEOSOURCE_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"expected_github_repository_id":0}'fetch
fetch("https://neosource.dev/api/repos/OWNER/REPO/github-attach", {
method: "POST",
headers: {
Authorization: "Bearer $NEOSOURCE_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({"expected_github_repository_id":0}),
});Path parameters
ownerrequiredRepository owner or organization slug.
reporequiredRepository name.
Request bodyrequired
application/json
Responses
202The attach run (new, or the one already in flight)
application/json
Standard errors
Bodies documented once for the whole API — see standard errors.
- 400Bad Request — one of: invalid_input
- 401Authentication required
- 403Forbidden — one of: forbidden
- 404Not Found — one of: not_found
- 409Conflict — one of: attach_publish_unconfirmed, conflict, relationship_conflict, relationship_unavailable
- 429Rate limited — retry after the `Retry-After` header
- 500Internal server error
- 502Bad Gateway — one of: upstream
- 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
- 504Gateway timeout — the request exceeded the server's handling budget