> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fixaeo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Customer API

> A read API over your FixAEO workspace, authed with a bearer key.

The Customer API returns the same numbers your dashboard shows, as JSON. You send an API key, you get your own workspace back.

The base URL is `https://api.fixaeo.com`. Every route starts with `/api/public/v1`.

```bash theme={null}
curl https://api.fixaeo.com/api/public/v1/brands \
  -H "Authorization: Bearer fixaeo_xxx"
```

## Who is this for?

Three jobs come up most often:

* Pulling your visibility numbers into a warehouse or BI tool.
* Building an internal dashboard your team already lives in.
* Pushing server logs to FixAEO so it counts crawlers the browser beacon can't see.

If you'd rather query this data conversationally, use the [MCP server](/mcp/introduction) instead. It wraps the same reads as tools and takes the same key.

## Is it read-only?

Almost entirely. Of the 21 paths, 19 are read-only. Two accept writes, and both of them take agent traffic:

* `POST /agents/ingest` — batches of raw request records from your edge.
* `POST /agents/ingest/vercel` — the same records in Vercel's own log-drain format.

That Vercel path also answers `GET` and `HEAD`, unauthenticated, so Vercel's endpoint-verification probe can reach it before the drain exists. It echoes back only what the caller put in the URL.

Nothing here starts a scan, edits a brand, or changes a prompt. Those actions stay in the app.

## What's in it?

Every path is documented under **Endpoints** in this tab, generated from the server's own spec. Here's the shape of it.

| Theme                    | Paths                                                                                                                                       | What you get                                                                             |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| Brands and trends        | `/brands`, `/brands/{slug}`, `/brands/{slug}/snapshots`, `/brands/{slug}/prompts`, `/portfolio`                                             | Your tracked brands, their daily time series, their prompts, and one cross-brand roll-up |
| Answers and citations    | `/brands/{slug}/mentions`, `/citations`, `/citations/fanouts`, `/topics`, `/model`                                                          | Individual mentions, cited domains, fan-out sub-queries, topic themes, per-engine scores |
| Industry and competitors | `/industry/metrics`, `/industry/ranking`, `/industry/gap`, `/industry/competitors/{name}/citations`, `/industry/competitors/{name}/prompts` | Share of voice, ranking, the sources you're missing, per-rival drilldowns                |
| Agent traffic            | `/brands/{slug}/agents`, `/brands/{slug}/agents/pages`, `/agents/ingest`, `/agents/ingest/vercel`                                           | Which AI crawlers hit you, which pages they took, plus the two ingest endpoints          |
| Traffic joins            | `/brands/{slug}/attribution`, `/brands/{slug}/search-performance`                                                                           | Your Google Analytics and Search Console data, joined to AI referrals                    |

<Tip>
  `/industry/metrics` is the one-call endpoint. It returns the ranking, the time series, per-competitor sentiment and your own aggregates in a single payload, which saves a reporting job five round trips.
</Tip>

## Which plans can call it?

Any plan can create a key and call the read endpoints, including Free. Free accounts get no scheduled scans though, so those reads come back empty until you upgrade. [Plans and limits](/plans-and-limits) has the full matrix.

The two ingest endpoints are gated harder. They need a paid plan, and server-log ingestion needs Growth or higher. A key without the right plan gets a `403` naming the plan it wants.

`POST /agents/ingest` caps a batch at 2000 records, and returns `413` telling you to split when you exceed that. The body is separately capped at 4 MB, which surfaces as `400 invalid JSON body` because the read is cut short. Chunk to stay under both.

## How is a key scoped?

To one account: the one that owns the key. There's no account parameter and no way to widen the scope.

Cookie sessions are rejected on this surface deliberately. Keeping the two auth paths separate makes "what can an API key reach" a single answer rather than an audit exercise.

If you track several brands, the account-wide endpoints default to your newest one. Pass `brand_slug` to pick another — see [Filters and time ranges](/api/filters).

## What do errors look like?

Every failure returns JSON with a single `error` string.

| Status | You'll see it when                                                    |
| ------ | --------------------------------------------------------------------- |
| `400`  | A parameter is malformed or a required one is missing                 |
| `401`  | The key is missing, revoked, or unknown                               |
| `403`  | Your plan doesn't cover the endpoint, or the `site_id` isn't yours    |
| `404`  | The brand slug or `site_id` doesn't exist on your account             |
| `413`  | A `POST /agents/ingest` batch exceeded 2000 records                   |
| `429`  | You went past the rate limit                                          |
| `500`  | Something broke server-side. Retry, then email support if it persists |

There's no error code field yet, so match on the status first and the string second.

## Next

<CardGroup cols={2}>
  <Card icon="key" title="Authentication" href="/api/authentication">
    Creating a key, its format, and what a bad one returns.
  </Card>

  <Card icon="gauge-high" title="Rate limits" href="/api/rate-limits">
    120 requests a minute, and how you find out you've hit it.
  </Card>

  <Card icon="filter" title="Filters and time ranges" href="/api/filters">
    The `range`, `region` and `engines` vocabulary, plus one scale trap.
  </Card>

  <Card icon="plug" title="MCP server" href="/mcp/introduction">
    The same reads, as tools your AI assistant can call.
  </Card>
</CardGroup>
