Sync API
Manual GitHub sync trigger and webhook secret provisioning.
Sync
The sync endpoints let you pull the linked GitHub repo into Hubify on demand, check the last sync state, and provision the per-lab webhook secret.
For automated push-driven sync, configure the GitHub webhook.
Base URL: https://hubify.com/api/v1
Manual sync
Pull the current default-branch HEAD into Hubify. Useful for first-time sync after linking a repo, or for reconciling drift if a webhook event was missed.
POST /api/v1/sync
Content-Type: application/json
{
"labId": "<id>",
"subPath": "papers", // optional — limit sync to a subtree
"ref": "abc123def..." // optional — sync a specific commit/branch
}
Required scope: lab:<slug>:rw.
Response:
{
"ok": true,
"pulled": 12, // new files added
"updated": 3, // existing files updated
"skipped": 47, // binary, oversized, or unchanged
"removed": 1, // deleted from repo, pruned from Hubify
"sha": "abc123def..."
}
Sync status
GET /api/v1/sync?labId=<id>
Required scope: lab:<slug>:r.
{
"repo": "https://github.com/owner/repo",
"defaultBranch": "main",
"lastSyncAt": 1714368000000,
"lastSyncSha": "a1b2c3d...",
"autoPushOnEdit": true
}
Provision webhook secret
Mint or fetch the per-lab GitHub webhook secret. The secret is returned on first call so you can paste it into GitHub's webhook settings; subsequent calls return the same value (idempotent — we don't rotate by accident).
POST /api/v1/sync/secret
Content-Type: application/json
{ "labId": "<id>" }
Required scope: lab:<slug>:admin.
{
"secret": "...64 hex chars...",
"existed": false,
"webhookUrl": "https://hubify.com/api/webhooks/github"
}
GitHub webhook
POST /api/webhooks/github
X-GitHub-Event: push
X-Hub-Signature-256: sha256=...
Hubify verifies the HMAC signature against the lab's gitWebhookSecret (provisioned above), then runs syncFromGithub for the pushed commit.
pingevent: ack with 200 (no sync)pushevent on default branch: full syncpushevent on non-default branch: ignored- Other events (star, fork, issues, etc.): ignored
Response on success:
{
"ok": true,
"delivery": "1234-5678-...",
"result": { "ok": true, "pulled": 0, "updated": 1, "skipped": 0, "removed": 0, "sha": "..." }
}
Errors
| Status | Meaning |
|---|---|
| 400 | Missing labId / invalid JSON / missing repository.full_name (webhook) |
| 401 | Invalid API key (REST) or signature mismatch (webhook) |
| 403 | Key lacks the required scope |
| 404 | Lab not found |
| 412 | Lab has no GitHub repo linked, or webhook secret not provisioned yet |
| 429 | Rate limit |
| 500 | Sync failed — see response body or activity feed |
See the Local Agents guide for the end-to-end setup walkthrough.