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

# Get Brand Intelligence Content Publisher Context Route

> What this brand's content research says about each requested PUBLISHER.

Feeds the Content Details workspace's publisher panel. §4 of the Content
redesign design assumed the workspace needed no new data; it was wrong —
lead-magnet types, content sources and content-source URLs live on
``CompetitorContentMetric`` at publisher grain and reach no content item.

Every requested domain comes back, measured or not: a publisher this brand
has never researched returns ``measured=false`` with a reason rather than
being omitted, so "we never looked" can never render as "there is nothing
there". One query serves the whole list, so a page of items costs the same
as a single open item.



## OpenAPI

````yaml /openapi.json get /api/v1/brands/{brand_id}/brand-intelligence/content-publisher-context
openapi: 3.1.0
info:
  title: AITasker
  version: 0.1.0
servers: []
security: []
paths:
  /api/v1/brands/{brand_id}/brand-intelligence/content-publisher-context:
    get:
      tags:
        - Brand Intelligence
        - Brand Intelligence
      summary: Get Brand Intelligence Content Publisher Context Route
      description: >-
        What this brand's content research says about each requested PUBLISHER.


        Feeds the Content Details workspace's publisher panel. §4 of the Content

        redesign design assumed the workspace needed no new data; it was wrong —

        lead-magnet types, content sources and content-source URLs live on

        ``CompetitorContentMetric`` at publisher grain and reach no content
        item.


        Every requested domain comes back, measured or not: a publisher this
        brand

        has never researched returns ``measured=false`` with a reason rather
        than

        being omitted, so "we never looked" can never render as "there is
        nothing

        there". One query serves the whole list, so a page of items costs the
        same

        as a single open item.
      operationId: >-
        get_brand_intelligence_content_publisher_context_route_api_v1_brands__brand_id__brand_intelligence_content_publisher_context_get
      parameters:
        - name: brand_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
            title: Brand Id
        - name: domains
          in: query
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 25600
            description: >-
              Comma-separated PUBLISHER domains (max 100) — normally each open
              item's `publisher.domain`. Deliberately NOT item ids: everything
              this route returns is a site-wide aggregate for the domain, never
              a property of one piece of content.
            title: Domains
          description: >-
            Comma-separated PUBLISHER domains (max 100) — normally each open
            item's `publisher.domain`. Deliberately NOT item ids: everything
            this route returns is a site-wide aggregate for the domain, never a
            property of one piece of content.
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentPublisherContextResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - HTTPBearer: []
components:
  schemas:
    ContentPublisherContextResponse:
      properties:
        brand_id:
          type: string
          format: uuid
          title: Brand Id
        brand_domain:
          anyOf:
            - type: string
            - type: 'null'
          title: Brand Domain
        generated_at:
          type: string
          format: date-time
          title: Generated At
        publishers:
          items:
            $ref: '#/components/schemas/ContentPublisherContext'
          type: array
          title: Publishers
        unreadable_domains:
          items:
            type: string
          type: array
          title: Unreadable Domains
      type: object
      required:
        - brand_id
        - generated_at
      title: ContentPublisherContextResponse
      description: >-
        One row per DISTINCT readable domain requested, in first-asked order.


        The 1:1 request-to-response contract is deliberate: a domain the brand
        has

        never researched still comes back, as a ``measured=False`` row, so the

        client never has to diff two sets to discover that a publisher is

        unmeasured rather than empty. It is the per-row twin of

        ``CompetitorContentCoverage.missing_domains``.


        Note this diverges from its sibling ``publisher_stats_by_domain``, which

        OMITS a domain it has nothing for. That is correct there (the caller

        renders em dashes into a table cell it already drew) and wrong here (a

        missing key would render as an absent panel, i.e. as "no lead magnets").

        Do not "fix" one to match the other.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ContentPublisherContext:
      properties:
        publisher_domain:
          type: string
          title: Publisher Domain
        grain:
          type: string
          const: publisher_domain
          title: Grain
          default: publisher_domain
        is_own_brand:
          type: boolean
          title: Is Own Brand
          default: false
        measured:
          type: boolean
          title: Measured
          default: false
        not_measured_reason:
          anyOf:
            - type: string
              const: publisher_not_in_brand_content_research
            - type: 'null'
          title: Not Measured Reason
        measured_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Measured At
        publisher_content_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Publisher Content Url
        publisher_content_types:
          additionalProperties:
            type: integer
          type: object
          title: Publisher Content Types
        publisher_lead_magnet_types:
          additionalProperties:
            type: integer
          type: object
          title: Publisher Lead Magnet Types
        publisher_content_sources:
          items:
            $ref: '#/components/schemas/ContentPublisherSource'
          type: array
          title: Publisher Content Sources
        publisher_lead_magnet_links:
          items:
            $ref: '#/components/schemas/ContentPublisherLeadMagnet'
          type: array
          title: Publisher Lead Magnet Links
        publisher_source_coverage:
          $ref: '#/components/schemas/ContentSourceCoverage'
        publisher_posts_last_30d:
          anyOf:
            - type: integer
            - type: 'null'
          title: Publisher Posts Last 30D
        publisher_posts_measured:
          type: boolean
          title: Publisher Posts Measured
          default: false
        publisher_avg_cadence_days:
          anyOf:
            - type: number
            - type: 'null'
          title: Publisher Avg Cadence Days
        publisher_has_ebooks:
          type: boolean
          title: Publisher Has Ebooks
          default: false
        publisher_has_webinars:
          type: boolean
          title: Publisher Has Webinars
          default: false
        publisher_has_whitepapers:
          type: boolean
          title: Publisher Has Whitepapers
          default: false
        publisher_strategy_summary:
          anyOf:
            - type: string
            - type: 'null'
          title: Publisher Strategy Summary
      type: object
      required:
        - publisher_domain
      title: ContentPublisherContext
      description: >-
        What this brand has measured about ONE publisher domain.


        Read the module docstring before rendering any field: these are
        site-wide

        aggregates over everything the content refresh could read from the
        domain,

        not facts about a single piece of content.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    ContentPublisherSource:
      properties:
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: Url
        source_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Source Type
        status:
          type: string
          enum:
            - fetched
            - failed
            - empty
          title: Status
          default: fetched
        error:
          anyOf:
            - type: string
            - type: 'null'
          title: Error
        item_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Item Count
        recent_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Recent Count
      type: object
      title: ContentPublisherSource
      description: >-
        One content source read for this publisher — a feed, sitemap, or index.


        ``source_type`` here is the KIND of source that was fetched (``rss``,

        ``sitemap``, ``blog`` …). It is emphatically NOT

        ``GlobalContentItemSource.source_type``, which is ingest provenance and
        is

        always the constant ``'content_snapshot'``. The two share a name and
        mean

        different things; never render one where the other is expected.


        ``status="empty"`` is a measured zero (a source WAS read and held
        nothing)

        and is kept distinct from ``"failed"`` (we never got to look).
    ContentPublisherLeadMagnet:
      properties:
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: Url
        label:
          anyOf:
            - type: string
            - type: 'null'
          title: Label
        type:
          anyOf:
            - type: string
            - type: 'null'
          title: Type
      type: object
      title: ContentPublisherLeadMagnet
      description: |-
        One gated asset found somewhere on the PUBLISHER'S site.

        Not an attachment of whichever content item the workspace has open. The
        link may point at a page entirely unrelated to that item.
    ContentSourceCoverage:
      properties:
        sources_total:
          type: integer
          title: Sources Total
          default: 0
        sources_fetched:
          type: integer
          title: Sources Fetched
          default: 0
        sources_failed:
          type: integer
          title: Sources Failed
          default: 0
        failures:
          items:
            $ref: '#/components/schemas/ContentSourceFailure'
          type: array
          title: Failures
      type: object
      title: ContentSourceCoverage
      description: >-
        N-of-M fetch coverage over one competitor's managed content sources.


        Pre-fix the UI silently dropped every failed source, so a brand whose
        blog

        was blocked looked identical to one with no blog. ``sources_failed`` and

        ``failures`` make the hole visible and retryable.
    ContentSourceFailure:
      properties:
        url:
          type: string
          title: Url
        source_type:
          type: string
          title: Source Type
          default: unknown
        error:
          anyOf:
            - type: string
            - type: 'null'
          title: Error
      type: object
      required:
        - url
      title: ContentSourceFailure
      description: One managed content source we could not read, with why.
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer

````