> ## 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.

# Working with the API

> Conventions, base URL, and your first request.

<Note>
  This page covers direct HTTP calls to the REST API.

  If you're connecting an AI tool via MCP (Cursor, VS Code, Claude Desktop, Claude Code), see [Connect HERO to your AI tool](mcp/overview) for the client-side setup.
</Note>

## Base URL

```
https://app.myhero.so
```

All endpoints are scoped under `/api`.

Example: `https://app.myhero.so/api/document/{documentId}`.

## Authentication

Every request requires a bearer token:

```http theme={null}
Authorization: Bearer hero_ak_<your-key>
```

See [Authentication](authentication) for how to generate one.

## Your first request

<CodeGroup>
  ```bash cURL theme={null}
  curl https://app.myhero.so/api/workspace/default \
    -H "Authorization: Bearer $HERO_API_KEY"
  ```

  ```ts Node.js theme={null}
  const res = await fetch("https://app.myhero.so/api/workspace/default", {
    headers: { Authorization: `Bearer ${process.env.HERO_API_KEY}` },
  });
  const workspaces = await res.json();
  console.log(workspaces);
  ```

  ```python Python theme={null}
  import os
  import requests

  r = requests.get(
      "https://app.myhero.so/api/workspace/default",
      headers={"Authorization": f"Bearer {os.environ['HERO_API_KEY']}"},
  )
  print(r.json())
  ```
</CodeGroup>

## Conventions

* **HTTP verbs** — standard `GET` / `POST` / `PUT` / `PATCH` / `DELETE`. <br />
  Read endpoints are GET; mutations carry their body as JSON.
* **Content-Type** — set `Content-Type: application/json` on every request with a body. Responses are always JSON unless the endpoint streams (`text/event-stream`) or returns a binary payload (e.g. exports).
* **IDs** — every resource ID is a UUID string. <br />
  Don't assume incrementing integers.

## Response shape

Successful responses wrap the payload in a top-level `data` field:

```json theme={null}
{
  "data": { "_id": "ws_...", "name": "Acme", "isPersonal": false }
}
```

List endpoints return arrays the same way:

```json theme={null}
{
  "data": [ { "_id": "doc_..." }, { "_id": "doc_..." } ]
}
```

A handful of streaming/binary endpoints break this pattern — they're called out per-route in the [API Reference](api-reference).

## Errors

All errors return a uniform shape:

```json theme={null}
{
  "error": "ValidationError",
  "message": "Request failed schema validation",
  "details": [...]
}
```

See [Errors](errors) for the full status code list and `error` codes.

## Rate limiting

Requests are throttled per-IP using IETF [RateLimit headers](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/) — every response includes `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`. <br />
When you exceed a window you get a `429` with a `Retry-After` header.

Default budget is **600 requests per 15 minutes**; specific surfaces are tighter (creation routes, export jobs, auth). Treat the headers as the authoritative source — limits get tuned over time.

## Streaming endpoints

Some routes stream their response as Server-Sent Events (`Content-Type: text/event-stream`) — most notably [`POST /ai-agent/stream`](api-reference/ai/ai-stream). <br />
See the [streaming demo](demos#3-stream-an-ai-agent-and-watch-it-use-tools) for a full Node.js client that parses chunks event-by-event.

## Versioning

The HERO API does not use a version prefix today. <br />
Breaking changes are announced in the [changelog](changelog) and gated behind opt-in headers when introduced.
