Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.myhero.so/llms.txt

Use this file to discover all available pages before exploring further.

Practical, copy-pasteable examples.
Each demo assumes you have an API key (hero_ak_*) — see Working with the API if you don’t.
export HERO_API_KEY=hero_ak_your_key_here

1. Fetch your default workspace

The simplest possible call — verifies your key is wired up correctly and returns the workspace your account lands on by default.
curl https://app.myhero.so/api/workspace/default \
  -H "Authorization: Bearer $HERO_API_KEY"
If you get a 401, the key is wrong or expired.
If you get a 403 with WorkspaceScopeViolation, the key is workspace-scoped and the default workspace isn’t in its scope — pass an explicit workspaceId to a scoped endpoint instead.

2. Create a document programmatically

Two calls: list your projects, then create a document inside one.
1

List your projects

curl https://app.myhero.so/api/project/all/$WORKSPACE_ID \
  -H "Authorization: Bearer $HERO_API_KEY"
Pick the _id of the project you want to write into.
2

Create the document

curl -X POST https://app.myhero.so/api/document \
  -H "Authorization: Bearer $HERO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "<project-id>",
    "name": "My new doc",
    "type": "FILE"
  }'
Returns { "data": { "_id": "...", "name": "My new doc", ... } }. Open it in the HERO app at app.myhero.so/#/<projectId>/<documentId>/editor.

3. Stream an AI agent (and watch it use tools)

POST /api/ai-agent/stream runs HERO’s general agent and emits Server-Sent Events as it thinks, calls tools, and edits your workspace. You see the model’s reply stream in token-by-token, get notified every time it invokes a tool (create-document, add-row, search-web, and 50+ others), and at the end receive a change summary of every entity it touched — undoable in one shot if the user changes their mind. The five event types over text/event-stream:
typedata
delta{ content: string } — incremental token output
tool_callprovider-specific payload — agent is invoking a tool
tool_resultprovider-specific payload — tool returned
done{ finalContent, usage, sessionId, hasUndo, changes? }
error{ message: string }

Quick peek with cURL

-N disables curl’s buffering so you see the chunks land in real time.
curl -N -X POST https://app.myhero.so/api/ai-agent/stream \
  -H "Authorization: Bearer $HERO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chatMessages": [
      { "type": "user", "text": "Create a document called Sprint 14 retro in my Engineering project, then add an H1 \"What went well\" and three bullet points." }
    ],
    "context": { "workspaceId": "<workspace-id>", "projectId": "<project-id>" }
  }'
You’ll see a flurry of data: {"type":"delta",...} lines as the agent narrates what it’s about to do, then data: {"type":"tool_call",...} as it invokes create-document and write-document-markdown, then a final data: {"type":"done",...} with the change summary.

Full Node.js client — parse, react, capture

const res = await fetch("https://app.myhero.so/api/ai-agent/stream", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.HERO_API_KEY}`,
    "Content-Type": "application/json",
    Accept: "text/event-stream",
  },
  body: JSON.stringify({
    chatMessages: [
      { type: "user", text: "Summarise my contracts table and add the summary as a new doc in the Legal project." },
    ],
    context: { workspaceId: process.env.HERO_WORKSPACE_ID },
  }),
});

if (!res.ok || !res.body) throw new Error(`Stream failed: ${res.status}`);

const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
let sessionId: string | undefined;

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });

  // SSE frames are separated by a blank line.
  const frames = buffer.split("\n\n");
  buffer = frames.pop() ?? "";

  for (const frame of frames) {
    const line = frame.split("\n").find((l) => l.startsWith("data: "));
    if (!line) continue;

    const event = JSON.parse(line.slice(6));
    switch (event.type) {
      case "delta":
        process.stdout.write(event.data.content);
        break;
      case "tool_call":
        console.log(`\n→ tool: ${event.data?.name ?? "(unknown)"}`);
        break;
      case "tool_result":
        // optional: log a short preview of the result
        break;
      case "done":
        sessionId = event.data.sessionId;
        console.log(`\n\n✓ run complete (session ${sessionId})`);
        if (event.data.hasUndo) {
          console.log(
            `  changed ${event.data.changes?.length ?? 0} entities — undoable via POST /api/ai-agent/undo with { sessionId }`,
          );
        }
        break;
      case "error":
        console.error(`\n${event.data.message}`);
        break;
    }
  }
}

Undo a run

If the agent did something unwanted, ship the sessionId from the done event back:
curl -X POST https://app.myhero.so/api/ai-agent/undo \
  -H "Authorization: Bearer $HERO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sessionId": "<session-id>" }'
Every entity the agent touched (documents, tables, projects) is rolled back to the snapshot it took before the run.

Lighter alternatives

  • For a single-prompt rewrite (no tool use, no streaming), use POST /ai-agent/transform-text with one of the built-in operations (rephrase, fixGrammar, simplify, translate, shorten, summarize, etc.).
  • For an agentic run where you don’t need incremental output, use POST /ai-agent — same body shape, returns the full chatMessages array in one response.

4. Drive HERO from your AI client

The MCP path. After installing for your client, try prompts like these in Cursor, Claude Desktop, or Claude Code — the AI will route them to the right HERO tools automatically.
"List my workspaces and tell me which has the most projects."
"Create a new document called 'Sprint 14 retro' in my Engineering project,
then add an H1 heading 'What went well' and a bulleted list with three items."
"Search my documents for any contracts that mention NDA, and summarise
the renewal dates."
The MCP server exposes 50+ tools across documents, tables, projects, and web search — browse the full Tool catalog.

5. Receive a webhook

Subscribe to events (Webhooks) and accept POSTs at your endpoint.
Node.js / Express
import express from "express";
const app = express();

app.post("/hero-webhook", express.json(), (req, res) => {
  const { event, data } = req.body;
  console.log(`[${event}]`, data);
  // ... your handling
  res.sendStatus(200);
});

app.listen(3000);
Verify the signature header before trusting the payload — see Webhooks for the signing scheme.