---
title: "Link an existing GitHub repository"
method: POST
path: "/api/apps/{app_id}/github/link-existing"
---

# Link an existing GitHub repository

`POST /api/apps/{app_id}/github/link-existing`

## Request

- Base URL: `https://app.base44.com`
- URL: `https://app.base44.com/api/apps/{app_id}/github/link-existing`
- Auth: HTTP bearer

<Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Connects an app created with the Base44 CLI to the GitHub repository that already holds its code. Base44 adopts the repository as it is, without creating one or pushing code to it.

The repository's default branch must be `main`, and its `base44/config.jsonc` must name this app. From then on the repository is where the app's code lives. Entities, agents, and functions you deployed with the CLI are replaced by their versions in the repository.

Before the call can succeed, the app's owner needs:

- Their GitHub account connected to Base44. This is done once, in Base44.
- The Base44 GitHub App installed on the repository with write access.

When either is missing, send the user to the link in the error's details, `connect_url` or `install_url`, then repeat the same call. A refused call changes nothing. If a response is lost, check [Get GitHub connection](/api-reference/get-github-connection) before retrying, because a repeat after a successful link is refused.

Base44 imports the repository's code in the background after the call returns. [Pull changes from GitHub](/api-reference/pull-changes-from-github) reports the app as already up to date once the import has finished.

## Path parameters

- `app_id` string, required: ID of the app to connect to a GitHub repository.

## Request body

- LinkExistingRepoRequest: Request to link the app to a repository that already holds its code.
  - `repo_full_name` string, required: Repository to link, as `owner/repo`. Its `base44/config.jsonc` project name must equal the app's name.

## Response `200`

The connection Base44 stored for the app.

- LinkedRepositoryResponse: Result of linking an app to the repository that already holds its code.
  - `connection_id` string, required: ID of the connection Base44 stored for this app.
  - `repo_full_name` string, required: Full repository name, as `owner/repo`.
  - `repo_url` string, required: URL of the repository on GitHub.
  - `default_branch` string, required: Branch Base44 syncs with. Always `main`.
  - `last_synced_commit` string, required: Head commit of `main` the app was linked at.

## Other responses

- `401`: Missing or invalid credentials.
- `403`: The call was refused before anything changed. The `error.code` says why. - `owner_required` means you aren't the app's owner. - `github_not_connected` means your GitHub account isn't connected to Base44. `details.connect_url` is the Base44 page where you connect it. - `installation_unavailable` means Base44 can't reach the repository through your GitHub account, usually because the Base44 GitHub App isn't installed on it. `details.install_url` is where to install it or add the repository. - `push_access_missing` means the Base44 GitHub App is installed without write access. `details.install_url` is where to change that. - `repository_not_accessible` means your GitHub account can't push to the repository, or GitHub refused it access, for example because the organization requires SSO. - `github_org_not_allowed` means the app's workspace doesn't allow this GitHub organization. - `workspace_role_required` means your workspace role can't add this GitHub organization. - `webhook_permission_missing` means the Base44 GitHub App can't add webhooks to the repository. - `git_sync_not_supported` means the app's type doesn't support Git sync. You also get this when you used a workspace API key. This endpoint takes a personal access token.
- `404`: App not found.
- `409`: The repository or the app isn't in a state to link. The `error.code` says why. - `already_managed` means the app's code is already managed in Base44. - `app_already_processing` means the app is busy with another GitHub operation. Try again shortly. - `default_branch_not_main` means the repository's default branch isn't `main`. - `config_not_found` means the repository has no readable `base44/config.jsonc` with a project name. - `name_mismatch` means the project name in `base44/config.jsonc` isn't this app's name. - `repository_already_linked` means the repository is already connected to a Base44 app.
- `422`: `repo_full_name` isn't in `owner/repo` form, or GitHub refused to add the repository's webhook with `webhook_creation_refused`, for example because the repository has too many webhooks.
- `429`: Rate limit exceeded. The base limit is 10 requests per minute. See [Rate limits](/developers/references/apps-api/get-started/rate-limits) for the multiplier your plan gets. GitHub limiting Base44's requests also lands here, with `github_rate_limited`. Nothing was changed. Wait for the `Retry-After` header's number of seconds before retrying.
- `502`: GitHub couldn't be reached, with `github_unavailable`, or didn't accept the repository's webhook, with `webhook_creation_failed`. Nothing was changed.

## Changes

- **2026-10-28** `21162ba67ca7`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/idealspot/apis/base44-app-management-api/changes/api/apps/:app_id/github/link-existing/post.md)

---

[API](https://skmtc.dev/idealspot/apis/base44-app-management-api.md) - [All operations](https://skmtc.dev/idealspot/apis/base44-app-management-api/llms.txt) - [OpenAPI document](https://skmtc.dev/idealspot/apis/base44-app-management-api/revisions/b5b4ebd82a1e?raw)
