---
title: Technical Enrichment
api: POST /brands/{brand_id}/enrich/technical
description: "Run a technical site audit via GemMiner or upload an existing audit. Populates brand.technical_context plus technical_issue insights and evidence."
---

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

Triggers a technical audit of the brand's site, or accepts an already-run audit as JSON. Populates `brand.technical_context` (health score, pages crawled, issues by severity, crawl date), plus creates `technical_issue` insights and evidence that feed the leverage scoring multiplier for the `technical_gap` category (1.30x).

**Duration:** 5-20 minutes for a triggered audit, seconds for an upload.

## Path parameters

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

## Request body

You must provide one of the two modes below. **Posting with no body, or with both fields omitted, accepts the request and returns 202 — but the background run will fail almost immediately** because there is nothing to process. Always include either `trigger: true` or `audit_data`.

<ParamField body="trigger" type="boolean" default="false">
  Set to `true` to run a fresh GemMiner audit crawl (up to 500 pages, 30-minute poll timeout).
</ParamField>

<ParamField body="audit_data" type="object">
  Pre-collected audit data to upload instead of triggering a fresh crawl. Accepts either a GemMiner-format audit (object with `categories` key) or a generic audit shape.
</ParamField>

## Response (202 Accepted)

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

Poll `GET /brands/{brand_id}/runs/{run_id}` until `status` is `done`. On success, the run's `meta` contains:

```json
{
  "insights_count": 47,
  "evidence_count": 47,
  "health_score": 87
}
```

And `GET /brands/{brand_id}` will now include a populated `technical_context` field.

## Example — trigger a fresh audit

```bash
curl -X POST \
  -H "X-API-Key: $BM_API_KEY" \
  -H "Content-Type: application/json" \
  https://api.boringmarketing.com/brands/$BRAND_ID/enrich/technical \
  -d '{"trigger": true}'
```

## Example — upload pre-collected audit

```bash
curl -X POST \
  -H "X-API-Key: $BM_API_KEY" \
  -H "Content-Type: application/json" \
  https://api.boringmarketing.com/brands/$BRAND_ID/enrich/technical \
  -d @audit.json
```

<Note>
Stuck runs are auto-expired after 15 minutes. If a previous technical enrichment run got stuck, this endpoint will fail it automatically before starting a new one.
</Note>

## Errors

| Status | Meaning |
|---|---|
| `404` | Brand not found, or not owned by the caller. |
| `422` | `brand_id` is not a valid UUID, or request body failed validation. |

<Note>
Unlike the other pipeline triggers, **`enrich/technical` does not return 409 on overlapping runs**. The handler auto-expires stale runs older than 15 minutes but always proceeds to create a new `technical_enrichment` run, even if another run (technical or otherwise) is already active for this brand. If you need to coordinate multiple technical audits, do that on the caller side.
</Note>
