Skip to main content
GET
Get Audit Competitor Benchmark Route

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

brand_id
string<uuid>
required

Query Parameters

audit_type
string
required
Maximum string length: 50

Response

Successful Response

The audited brand's standing against the competitors IT named (R17).

available=False is a first-class, renderable answer — reason names which one so the report can offer the matching next step instead of a blank panel. It is NEVER an error: a brand with no competitors yet, or a Website audit (which has no same-basis competitor measure at all), is a normal state.

These are MEASURED dimensions on an identical basis for both sides, not audit scores — no competitor is ever audited, so no competitor has a dimension score to average. See services/audit_competitor_benchmark.py for why.

audit_type
string
required
available
boolean
required
reason
string | null
basis
string | null
basis_label
string | null
brand_domain
string | null
coverage
ModuleCoverageStrip · object | null

N-of-M acquisition coverage for one module's cohort (the ★S0/★C0 strip).

measured counts cohort domains that produced a stored metric row. missing are targets that never did — their fetch or persist failed, or they have not been acquired yet. For Content, fetch_failed is a typed subset of missing, not an additional shortfall, so clients must de-duplicate rather than sum those lengths. A competitor with a failed acquisition must render as a failure chip, never as a measured zero.

measured_competitors
integer
default:0
min_measured_competitors
integer
default:0
dimensions
ModuleDimensionRank · object[]
authority_dimensions
ModuleDimensionRank · object[]
authority_not_measured_reason
string | null
keyword_gaps
SeoGapsPanel · object | null

★S9 — the cohort ranks, you don't.

Rows come from DataForSEO's own server-side exclusion query (domain_intersection with intersections: false), so a keyword the brand ranks for at position 240 is not reported as a gap. semantics names that contract; an empty string means the stored snapshot predates it.

keyword_weaknesses
SeoWeaknessesPanel · object | null

★S10 — shared keywords where a competitor MATERIALLY outranks the brand.

The thresholds are the free SEO audit's, imported rather than copied, so BI and the audit can never disagree on what "materially outranks" means.

table_stakes
SeoTableStakesPanel · object | null

★S3 — keywords the WHOLE measured cohort ranks for: the must-haves.

content_type_mix
SeoContentTypeMixPanel · object | null

★S6 — what KIND of page wins in this niche (classified ranking URLs).

Two classifiers feed one set of counts, and the split is published. Most labels come from the URL's own path (free, deterministic, and right whenever the path carries a recognisable token). ★S13b adds a second source for the paths that carry no such token: the page's actual parsed content, bought per URL. urls_labeled_from_content is how many labels came from the paid source across BOTH denominators — cohort_urls_classified plus brand_urls_classified, summed. The brand's own benchmark row spends its own budget exactly as each competitor row does, so a cohort-only count would understate the provenance and could not be rendered against either number alone.

That count is NOT a quality score and must not be rendered as one. It is bounded by a per-refresh budget spent only on URLs the free path could not read, so a LOW number means "the free classifier handled almost everything" — the good case — and is indistinguishable, by design, from "the paid leg is switched off". content_labeling_enabled is what separates them.

keyword_intent_mix
SeoKeywordIntentMixPanel · object | null

★S5 — classified intent mix over the stored cohort keyword samples.

keywords_unclassified is a separate denominator: missing labels are not folded into a bucket and domains whose classification call failed are named under domains_not_measured rather than represented as zeros.

cohort_domains
string[]
measured_at
string<date-time> | null