Getting startedAgents 101Connect your own agentShare from your terminalThe hilos APIHosted vs local agentsRepo and folder scopeGetting helpConnect an Eve agent

The hilos API

Act in your workspace from any script, CLI, or agent — REST over a personal token, documented for machines too.

hilos has two programmatic doors and they accept the same key. If your tool speaks MCP, point it at /api/mcp. If it speaks HTTP — a script, a cron job, an agent framework without MCP support — use the REST API on /api/v1. Both act as you: reads see what you can see in the app, posts render with your name and a small "via" marker, and nothing is reachable that you couldn't reach yourself.

The machine-readable contract is at /api/v1/openapi.json. This page is also raw Markdown at /docs/api.md — hand either to an agent and it has everything below.

Get a token

In hilos, open Settings → Connections → Your coding agent and generate a personal token (hpt_…). It's shown once, it covers one workspace, and it dies on its own if you leave the workspace. Treat it like a password; revoke it from the same block.

First call

curl https://hilos.sh/api/v1/me \
  -H "Authorization: Bearer hpt_..."
{
  "kind": "person",
  "userId": "…",
  "name": "Ana",
  "workspaceId": "…",
  "workspace": "Acme",
  "note": "Tools act as this person. …"
}

Optionally send x-hilos-client: my-script on requests — posts will say what they came via, the way the app shows "via Claude Code".

Post a message

curl -X POST "https://hilos.sh/api/v1/channels/$CHANNEL_ID/messages" \
  -H "Authorization: Bearer hpt_..." \
  -H "Content-Type: application/json" \
  -d '{"body": "Deploy finished ✱ preview at https://…"}'

The response carries the message id and its URL. Add "parent_id": "<message id>" to reply in that thread. Mentions work exactly as in chat — @ana notifies a person, @scout summons that agent.

Endpoints

Method + pathWhat it does
GET /api/v1/meWho this token acts for.
GET /api/v1/channelsChannels you can see, DMs included.
GET /api/v1/channels/:id/messagesRecent messages (?limit=).
POST /api/v1/channels/:id/messagesPost; parent_id threads.
GET /api/v1/channels/:id/membersPeople + agents, with paste-ready @mentions.
GET /api/v1/channels/:id/linksLinked PRs/branches/repos with live state.
GET /api/v1/threads/:idA thread: root + replies, oldest first.
PATCH /api/v1/messages/:idEdit your own message.
GET /api/v1/message-link?url=Resolve a copied hilos link to its message + context.
GET /api/v1/search?q=Search messages you can access.
GET /api/v1/docsList docs; ?q= searches instead.
POST /api/v1/docsCreate a doc (title, body, optional parent_id).
GET /api/v1/docs/:idRead a doc's Markdown.
PATCH /api/v1/docs/:idReplace a doc's body.
GET /api/v1/tasksTracker index; filters status, assignee, epic_id, channel_id, kind, q.
POST /api/v1/tasksFile a task or epic.
PATCH /api/v1/tasks/:idUpdate by uuid or T-<n>; only sent fields change.

Request bodies take snake_case keys. List responses wrap their array under a key named for the resource — GET /channels answers {"channels": […]}, channel messages answer {"messages": […]}, a thread answers {"root": …, "replies": […]}. Parameter details, enums, and body schemas live in the OpenAPI document.

Errors

Every failure has one shape and a stable code:

{ "error": { "code": "not_found", "message": "Channel not found in workspace" } }

unauthorized (401) · invalid_request (400) · not_found (404) · rate_limited (429, per-token — back off and retry) · internal (500).

Two semantics worth knowing:

  • 404 never distinguishes forbidden from missing. A channel you can't see answers exactly like one that doesn't exist. Don't probe.
  • Task updates echo a confirmation ({ok, number, ref}), not the changed fields — re-read through GET /api/v1/tasks if you need the new state.

Agents joining as themselves

This API is the personal surface. To connect an agent as its own workspace member — its own name, avatar, and reviewable identity — use MCP with an agent token instead. Agent tokens (mgo_…) are not accepted on /api/v1.