Developers

The Zentile API.

A REST API and an MCP server for your hubs, stacks, and tiles. Build automations, save links from anywhere, or let Claude manage your Zentile for you.

Get a key

API access is included in the Max plan. Create a key in Settings → Billing → API keys. Each key is shown once at creation — store it somewhere safe. Keys look likeznt_a1b2c3… and can be revoked at any time.

Every request authenticates with a Bearer header:

Authorization: Bearer znt_your_api_key

Quick test

curl https://zentile.app/api/v1/me \
  -H "Authorization: Bearer znt_your_api_key"

# → { "userId": "…", "plan": "max" }

Conventions

  • • Base URL: https://zentile.app/api/v1
  • • JSON in, JSON out. Send Content-Type: application/json on writes.
  • • Errors always return { "error": "message" } with a matching status code (400, 401, 403, 404, 500).
  • • The hierarchy: workspace → hub → stack → tile. Lists are ordered by sort_order.

REST API v1

Identity & workspaces

GET/api/v1/me

Who am I? Returns the user id and plan behind the API key.

Response

{ "userId": "uuid", "plan": "max" }
GET/api/v1/workspaces

List your workspaces.

Response

{ "workspaces": [ { "id": "uuid", "name": "Personal", "ico": "🏠", "sort_order": 0, "created_at": "…" } ] }

Hubs

GET/api/v1/hubs?workspaceId=…

List hubs. workspaceId is optional — omit it to list every hub you own.

Response

{ "hubs": [ { "id": "uuid", "workspace_id": "uuid", "name": "Research", "ico": "🔬",
             "description": null, "public_slug": null, "sort_order": 0, "created_at": "…" } ] }
POST/api/v1/hubs

Create a hub inside a workspace. ico and description are optional.

Request body

{ "workspaceId": "uuid", "name": "Research", "ico": "🔬", "description": "Papers & tools" }

Response

201 → { "hub": { "id": "uuid", "name": "Research", … } }
GET/api/v1/hubs/:id

One hub in full — the hub plus its stacks, each stack carrying its tiles.

Response

{ "hub": { "id": "uuid", "name": "Research", …,
           "stacks": [ { "id": "uuid", "name": "Papers", …,
                         "tiles": [ { "id": "uuid", "title": "Attention Is All You Need", "url": "…", … } ] } ] } }
PATCH/api/v1/hubs/:id

Update a hub. Send any of name, ico, description.

Request body

{ "name": "Deep Research" }

Response

{ "hub": { … } }
DELETE/api/v1/hubs/:id

Delete a hub and everything in it.

Response

{ "ok": true }
POST/api/v1/hubs/:id/publish

Publish the hub as a public page. Returns the slug and full URL. Already published? You get the existing slug back.

Response

{ "slug": "brilliant-otter-042", "url": "https://zentile.app/h/brilliant-otter-042" }
DELETE/api/v1/hubs/:id/publish

Unpublish the hub — the public page goes away.

Response

{ "ok": true }

Stacks

GET/api/v1/stacks?hubId=…

List stacks, optionally scoped to a hub.

Response

{ "stacks": [ { "id": "uuid", "hub_id": "uuid", "name": "Daily Tools", "accent": "blue", … } ] }
POST/api/v1/stacks

Create a stack inside a hub. The workspace is derived from the hub automatically.

Request body

{ "hubId": "uuid", "name": "Reading List", "accent": "teal" }

Response

201 → { "stack": { … } }
PATCH/api/v1/stacks/:id

Update a stack. Send any of name, accent, collapsed, sort_order.

Request body

{ "name": "Read Later", "accent": "purple" }

Response

{ "stack": { … } }
DELETE/api/v1/stacks/:id

Delete a stack and its tiles.

Response

{ "ok": true }

Tiles

GET/api/v1/tiles?stackId=…

List tiles, optionally scoped to a stack.

Response

{ "tiles": [ { "id": "uuid", "stack_id": "uuid", "title": "Anthropic Docs", "url": "https://docs.anthropic.com", "emoji": "📚", "note": "", "pinned": false, … } ] }
POST/api/v1/tiles

Add a tile (a saved link) to a stack. url, emoji, and note are optional.

Request body

{ "stackId": "uuid", "title": "Anthropic Docs", "url": "https://docs.anthropic.com", "emoji": "📚" }

Response

201 → { "tile": { … } }
PATCH/api/v1/tiles/:id

Update a tile. Send any of title, url, emoji, note, pinned, sort_order.

Request body

{ "pinned": true }

Response

{ "tile": { … } }
DELETE/api/v1/tiles/:id

Delete a tile.

Response

{ "ok": true }

Search

GET/api/v1/search?q=…

Search everything you own: tiles matching by title, url, or note (up to 50), plus hubs and stacks matching by name.

Response

{ "query": "anthropic", "tiles": [ … ], "hubs": [ … ], "stacks": [ … ] }

MCP server

Zentile speaks the Model Context Protocol, so AI assistants like Claude can read and manage your hubs directly. Same API key, same permissions as the REST API.

Endpoint

https://zentile.app/api/mcp

Connect Claude Code

One command in your terminal:

claude mcp add --transport http zentile https://zentile.app/api/mcp \
  --header "Authorization: Bearer znt_your_api_key"

Available tools

  • list_workspaceslist your workspaces
  • list_hubslist hubs, optionally by workspace
  • get_hubone hub with all its stacks and tiles
  • create_hubcreate a hub in a workspace
  • create_stackcreate a stack in a hub
  • add_tilesave a link into a stack
  • searchsearch tiles, hubs, and stacks
  • publish_hubpublish a hub and get its public URL

Try saying

  • • “Save this link to my Research hub: https://arxiv.org/abs/1706.03762”
  • • “What do I have in my Work Tools hub?”
  • • “Create a hub called Trip Planning with stacks for Flights, Hotels, and Things To Do — then publish it and give me the link.”