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.

  • ping event: ack with 200 (no sync)
  • push event on default branch: full sync
  • push event 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

StatusMeaning
400Missing labId / invalid JSON / missing repository.full_name (webhook)
401Invalid API key (REST) or signature mismatch (webhook)
403Key lacks the required scope
404Lab not found
412Lab has no GitHub repo linked, or webhook secret not provisioned yet
429Rate limit
500Sync failed — see response body or activity feed

See the Local Agents guide for the end-to-end setup walkthrough.

← Back to docs index