---
title: LLM Enrichment
api: POST /brands/{brand_id}/enrich/llm
description: "Pull LLM citation metrics via DataForSEO: AI search volume, citation gaps, and competitor comparison. Populates brand.llm_context."
---

> **For AI agents:** the complete documentation index is at [llms.txt](https://docs.boringmarketing.com/llms.txt). Append `.md` to any page URL for its markdown version.

Runs LLM citation enrichment: pulls per-platform citation metrics from DataForSEO's aggregated LLM data, computes citation gaps vs competitors, and populates `brand.llm_context`. Also creates `llm_gap` and `llm_citation` evidence that feed opportunity synthesis.

**Duration:** 1-3 minutes.

## Path parameters

<ParamField path="brand_id" type="string" required>
  The brand UUID.
</ParamField>

## Request body

None — this endpoint takes no body.

## Response (202 Accepted)

```json
{
  "run_id": "run-uuid",
  "status": "queued"
}
```

Poll `GET /brands/{brand_id}/runs/{run_id}` until `status` is `done`. After completion:

- `GET /brands/{brand_id}` returns a populated `llm_context` field
- `GET /brands/{brand_id}/evidence?type=llm_gap` returns per-keyword citation gap evidence
- `GET /brands/{brand_id}/evidence?type=llm_citation` returns per-keyword citation events

## Example

```bash
curl -X POST \
  -H "X-API-Key: $BM_API_KEY" \
  https://api.boringmarketing.com/brands/$BRAND_ID/enrich/llm
```

<Tip>
Run LLM enrichment after `POST /brands/{id}/discover` so the pipeline has topic families to check citation coverage against. Standalone calls still work, but the gap analysis is richer when families are populated.
</Tip>

## Errors

| Status | Meaning |
|---|---|
| `404` | Brand not found, or not owned by the caller. |
| `409` | Returned when **(a)** another `llm_enrichment` run is already active for this brand, or **(b)** a `full` (`/analyze`) run is currently writing to all tables. Other partial runs do **not** block this endpoint. Response carries an `X-Running-Run-Id` header with the existing run's UUID. Active runs older than 15 minutes are auto-expired before the conflict check. |
| `422` | `brand_id` is not a valid UUID. |
