GitHub
Two-way GitHub sync for your project via a fine-grained personal access token.
For a step-by-step walkthrough, see the GitHub guide. GitHub sync is included on paid plans.
Connect a GitHub repository to your project for two-way sync. After connecting, every new version (a prompt, a file save, a restore, an import) is pushed to develop, the published code is pushed to main on every publish, and commits you push to develop are pulled in before the next prompt. All endpoints require the api-key header and are free.
#Connect GitHub Repository
/api/v1/vcaas/projects/:projectId/github/connectapi-keyFreeConnect a GitHub repository to your project using a Fine-grained Personal Access Token (PAT). This validates permissions, stores credentials, sets up branches (develop and main), and performs the initial sync. After connecting, every new version is pushed to develop, and the published code to main on every publish.
- Go to
https://github.com/settings/personal-access-tokens. - Click "Generate new token".
- Select "Only select repositories" and choose your repo.
- Under "Repository permissions", set Contents: Read and write (Metadata: Read is added automatically).
- Click "Generate token" and copy it (it starts with
github_pat_).
For empty repositories, Totalum creates the develop and main branches automatically. For non-empty repositories, both branches must already exist.
syncDirection (controls behavior when the repo has existing content with no common git history):
"totalum_to_github"(default) — pushes the Totalum project code to GitHub, replacing the repository content on bothdevelopandmainbranches."github_to_totalum"— pulls the GitHub repository code into Totalum, replacing the current project code. If thedevelopbranch doesn't exist on GitHub, it is created frommain.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | GitHub Fine-grained Personal Access Token |
repositoryFullName | string | Yes | Full repository name (e.g. "owner/repo") |
syncDirection | string | No | "totalum_to_github" (default) or "github_to_totalum". Controls behavior when repo has existing content with no common history |
Response fields
| Field | Type | Description |
|---|---|---|
data.connected | boolean | true if connection was successful |
data.repositoryFullName | string | The connected repository |
data.syncAction | string | "push_new", "push", "pull", "merge_and_push", or "already_synced" |
data.repoHasContent | boolean | Whether the repo had existing content |
data.requiresRebuild | boolean | Whether a rebuild was triggered. If true, poll GET /github/pull-status until status is "success" or "error" |
Example request
curl -X POST \
-H "api-key: tlm_sk_your_key" \
-H "Content-Type: application/json" \
-d '{"token":"github_pat_xxx","repositoryFullName":"myuser/my-repo","syncDirection":"totalum_to_github"}' \
https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/connectconst res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/connect", {
method: "POST",
headers: {
"api-key": process.env.TOTALUM_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"token": "github_pat_xxx",
"repositoryFullName": "myuser/my-repo",
"syncDirection": "totalum_to_github"
}),
});
const { errors, data } = await res.json();{
"errors": null,
"data": {
"connected": true,
"repositoryFullName": "myuser/my-repo",
"syncAction": "push_new",
"repoHasContent": false,
"requiresRebuild": false
}
}{
"errors": {
"errorCode": "MISSING_GITHUB_FIELDS",
"errorMessage": "token and repositoryFullName are required"
},
"data": null
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
MISSING_GITHUB_FIELDS | 400 | token and repositoryFullName are required |
INVALID_SYNC_DIRECTION | 400 | syncDirection must be "totalum_to_github" or "github_to_totalum" |
GITHUB_VALIDATION_FAILED | 400 | Token invalid, missing permissions, or repo not found |
GITHUB_SYNC_FAILED | 400 | Initial sync with GitHub failed |
AGENT_RUNNING | 409 | Cannot connect while agent is running |
PLATFORM_CAPABILITY_QUOTA_REACHED | 403 | GitHub sync is not included on your plan |
#Disconnect GitHub
/api/v1/vcaas/projects/:projectId/github/connectapi-keyFreeRemove the GitHub integration from your project. Deletes the stored token and repository credentials. Code already in your project is not affected.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Response fields
| Field | Type | Description |
|---|---|---|
data.success | boolean | true on success |
data.message | string | Confirmation message |
Example request
curl -X DELETE -H "api-key: tlm_sk_your_key" \
https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/connectconst res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/connect", {
method: "DELETE",
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{ "errors": null, "data": { "success": true, "message": "GitHub disconnected successfully" } }{
"errors": {
"errorCode": "GITHUB_NOT_CONNECTED",
"errorMessage": "GitHub is not connected to this project"
},
"data": null
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
GITHUB_NOT_CONNECTED | 400 | GitHub is not connected to this project |
#Get GitHub Status
/api/v1/vcaas/projects/:projectId/github/statusapi-keyFreeCheck whether GitHub is connected and the token is still valid.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Response fields
| Field | Type | Description |
|---|---|---|
data.connected | boolean | Whether GitHub is connected |
data.tokenValid | boolean | Whether the PAT token is still valid |
data.tokenExpired | boolean | True when the last linked PAT was detected as expired/revoked. Sticky until the user reconnects. Use this to prompt the user to reconnect |
data.repositoryFullName | string | Connected repository, or last-known repo when tokenExpired is true |
data.developBranch | string | "develop" (only if connected) |
data.productionBranch | string | "main" (only if connected) |
data.lastPushAt | string | undefined | When Totalum last pushed to GitHub |
data.lastPushSha | string | null | undefined | The commit it pushed |
data.needsReconnect | boolean | undefined | true when the token must be replaced (connect again) |
Example request
curl -H "api-key: tlm_sk_your_key" \
https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/statusconst res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/status", {
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{
"errors": null,
"data": {
"connected": true,
"tokenValid": true,
"tokenExpired": false,
"repositoryFullName": "myuser/my-repo",
"developBranch": "develop",
"productionBranch": "main"
}
}#Pull from GitHub
/api/v1/vcaas/projects/:projectId/github/pullapi-keyFreePull the latest changes from the GitHub develop branch into your project. If files changed, the server rebuilds automatically in the background. Poll the pull status endpoint until complete. This is an async operation.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Response fields
| Field | Type | Description |
|---|---|---|
data.status | string | "pulling" (async rebuild started) or "no_changes" |
data.message | string | Status message |
data.filesUpdated | number | Number of files updated |
Example request
curl -X POST -H "api-key: tlm_sk_your_key" \
https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/pullconst res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/pull", {
method: "POST",
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{
"errors": null,
"data": {
"status": "pulling",
"message": "Pull started successfully",
"filesUpdated": 5
}
}{
"errors": {
"errorCode": "GITHUB_NOT_CONNECTED",
"errorMessage": "GitHub is not connected (connect first)"
},
"data": null
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
GITHUB_NOT_CONNECTED | 400 | GitHub is not connected (connect first) |
GITHUB_PULL_ERROR | 400 | Failed to pull changes |
AGENT_RUNNING | 409 | Cannot pull while agent is running |
PLATFORM_CAPABILITY_QUOTA_REACHED | 403 | GitHub sync is not included on your plan |
#Get Pull Status
/api/v1/vcaas/projects/:projectId/github/pull-statusapi-keyFreePoll this endpoint after calling Pull from GitHub, OR after a Connect GitHub call that returned requiresRebuild: true (e.g. github_to_totalum direction). Returns the current rebuild status. Auto-completes after 10 minutes.
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Response fields
| Field | Type | Description |
|---|---|---|
data.status | string | "pulling", "success", "error", or null (no pull) |
data.createdAt | string | ISO 8601 date when the pull started |
Example request
curl -H "api-key: tlm_sk_your_key" \
https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/pull-statusconst res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/pull-status", {
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{ "errors": null, "data": { "status": "success", "createdAt": "2026-03-17T10:00:00.000Z" } }#Download Environment Variables
/api/v1/vcaas/projects/:projectId/github/envapi-keyFreeGet the project's environment variables as .env file content for both development and production environments. Use this to set up a local development environment or configure production deployments.
Same content as Get Project Env, both environments at once, as JSON. Included on paid plans (source download).
Path parameters
| Parameter | Type | Description |
|---|---|---|
projectId | string | The project ID |
Response fields
| Field | Type | Description |
|---|---|---|
data.envDev | string | .env file content for development (KEY=VALUE format, one per line) |
data.envProd | string | .env file content for production (KEY=VALUE format, one per line) |
Example request
curl -H "api-key: tlm_sk_your_key" \
https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/envconst res = await fetch("https://builder-api.totalum.app/api/v1/vcaas/projects/my-app/github/env", {
headers: {
"api-key": process.env.TOTALUM_API_KEY,
},
});
const { errors, data } = await res.json();{
"errors": null,
"data": {
"envDev": "TOTALUM_ENV=dev\nTOTALUM_PROJECT_KEY=tlm_pk_xxx\nBETTER_AUTH_SECRET=xxxx\nNEXT_PUBLIC_APP_URL=http://localhost:3100\n...",
"envProd": "TOTALUM_ENV=live\nTOTALUM_PROJECT_KEY=tlm_pk_xxx\nBETTER_AUTH_SECRET=xxxx\nNEXT_PUBLIC_APP_URL=https://my-app.totalum-project.com\n..."
}
}Error codes
| Code | HTTP | Meaning |
|---|---|---|
PLATFORM_CAPABILITY_QUOTA_REACHED | 403 | Source download is not included on your plan |
PROJECT_NOT_READY | 409 | The project is still being set up; retry after Retry-After seconds |
