Files API

Read, write, and delete lab files. Backs the local-agents and CLI workflows.

Files

Read and write any file in a lab — notes, papers, scripts, datasets. Authenticated callers see the same tree the orchestrator and Files panel see. When the lab has a linked GitHub repo with auto-push enabled, write/delete operations also commit to the repo.

Base URL: https://hubify.com/api/v1

Required scope:

  • lab:<slug>:r for GET
  • lab:<slug>:rw for POST / PATCH / DELETE

The wildcard lab:*:r / lab:*:rw / lab:*:admin also works.

List files in a lab

GET /api/v1/files?labId=<id>

Returns the full file tree:

{
  "files": [
    {
      "_id": "k57...",
      "labId": "k88...",
      "name": "today.md",
      "path": "/notes/today.md",
      "type": "file",
      "parentPath": "/notes",
      "mimeType": "text/markdown",
      "size": 4123,
      "content": "...",
      "createdAt": 1714368000000,
      "updatedAt": 1714368042000
    }
  ],
  "total": 1
}

Read a single file

GET /api/v1/files?labId=<id>&path=/notes/today.md

Returns just that file's record. 404 if the path does not exist.

Create or overwrite a file

POST /api/v1/files
Content-Type: application/json

{
  "labId": "<id>",
  "path": "/notes/today.md",
  "content": "# Today\n\nMeeting notes...",
  "mimeType": "text/markdown"
}

If a file already exists at path, this updates its content. Otherwise it creates the file (and the implied parent folder structure). MIME type is inferred from the extension if omitted.

Response:

{ "created": true, "path": "/notes/today.md", "fileId": "k7...", "bytes": 28 }

Update content only

PATCH /api/v1/files
Content-Type: application/json

{ "labId": "<id>", "path": "/notes/today.md", "content": "..." }

Same shape as POST, but returns 404 if no file exists at path. Use this when you specifically don't want to create new files by accident.

Delete a file

DELETE /api/v1/files?labId=<id>&path=/notes/today.md

Response:

{ "deleted": true, "path": "/notes/today.md" }

GitHub round-trip

When a lab has a GitHub repo linked and gitAutoPushOnEdit is true (toggle in Lab Settings):

  • POST / PATCH writes also PUT /repos/.../contents/{path} on GitHub
  • DELETE also DELETE /repos/.../contents/{path} on GitHub

The Hubify request returns success as long as the Convex write succeeded — GitHub push errors are logged on the lab's activity feed but don't fail the API call. Use GET /api/v1/sync to confirm the latest sync SHA.

See Local Agents guide for the full bidirectional flow.

Errors

StatusMeaning
400Missing labId / path / content
401Invalid or missing API key
403Key lacks lab:<slug>:r (GET) or lab:<slug>:rw (write)
404No file at the given path (GET / PATCH / DELETE)
429Rate limit (120/min read, 30/min write)
500Convex error — check response body
← Back to docs index