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

# Channels

> Rank the YouTube channels cited in a category, or the video categories they publish in.

Rank the YouTube channels cited in a category, or the video categories they
publish in. Calculated from Profound's citation data, not YouTube analytics.

* **Source types:** `video`, `short`, `channel`, `playlist`, or `other`.
  Omit `source_types` to include `video`, `short`, `channel`, and `playlist`.
  Provide a non-empty list; duplicate values are de-duplicated. Rollups
  cannot include `other`, because those citations have no channel.
* **`group_by`:** `channel` (the default), `video_category`, or `source_type`.
  Supported cross-tabs are `["channel", "video_category"]`,
  `["channel", "source_type"]`, and `["channel", "model"]`. Duplicate
  dimensions are rejected.
* **Time series:** Set `interval` to `day`, `week`, or `month` to return one
  row per entity per period. `date` is the bucket start in ET, so a weekly or
  monthly bucket can start before `start_date`. Omit it for window totals.
* **Rows:** Fields are conditional: `date`, `model`, `source_type`, and
  `video_category` appear only with the matching `interval` or `group_by`.
  With `group_by: ["video_category"]`, the category is returned in `name`, not
  `video_category`. An unresolved video category is returned as `""`, not
  `null`. `rank` is the leading channel's rank in the full ranked set and is
  repeated across that channel's cross-tab rows.
* **Pagination:** `limit` defaults to 10 and accepts 1–50. Pass the opaque
  `info.next_cursor` back as the request `cursor` to get the next page;
  `info` echoes your `cursor` on pages after the first. The response `info`
  echoes `category_id`, the effective `limit`, and `interval`.
* **Totals:** `total_results` counts distinct channels in the window, while
  `count` is the number of rows returned; they use different units.
* **Filters:** Prompt-level fields are `model`, `topic`, `region`, `prompt`,
  `persona`, `tag`, and `analysis_type`. The `channel` filter accepts `is`,
  `in`, `contains`, `not_contains`, `contains_case_insensitive`, and
  `not_contains_case_insensitive`: `is`/`in` select exact handles, while the
  other operators match channel titles or handles.
  `domain` and `page` are rejected. A `channel` leaf cannot share an `or` or
  `not` with a prompt-level leaf; put separate layers in `and` clauses.

<Warning>
  For cross-tabs, `limit` counts leading channels, not returned rows. For
  example, `limit: 25` with `group_by: ["channel", "video_category"]` returns
  25 channels but can return more than 25 rows.
</Warning>

<Note>
  The v2 reports share a request shape and filter tree. See
  [Filtering & concepts](/rest-api/reports/reports-v2-overview) for filter
  operators, grouping, date ranges, pagination, and filter depth.
</Note>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.tryprofound.com/v2/reports/social/youtube/channels \
    -H "X-API-Key: <your-api-key>" \
    -H "Content-Type: application/json" \
    -d '{
      "category_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
      "start_date": "2026-06-01",
      "end_date": "2026-06-30",
      "group_by": ["channel", "source_type"],
      "source_types": ["video", "short"],
      "limit": 10
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "info": {
      "category_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
      "total_results": 137,
      "count": 2,
      "next_cursor": "eyJvIjoxMH0",
      "limit": 10,
      "interval": null,
      "group_by": ["channel", "source_type"],
      "models": ["ChatGPT", "Google Gemini"],
      "start_date": "2026-06-01",
      "end_date": "2026-06-30",
      "filter": null,
      "source_types": ["video", "short"]
    },
    "data": [
      {
        "name": "Example Channel",
        "handle": "examplechannel",
        "url": "https://www.youtube.com/@examplechannel",
        "rank": 1,
        "source_type": "video",
        "count": 128,
        "videos": 14,
        "citation_share": 0.37
      },
      {
        "name": "Example Channel",
        "handle": "examplechannel",
        "url": "https://www.youtube.com/@examplechannel",
        "rank": 1,
        "source_type": "short",
        "count": 42,
        "videos": 8,
        "citation_share": 0.12
      }
    ]
  }
  ```
</ResponseExample>


## OpenAPI

````yaml POST /v2/reports/social/youtube/channels
openapi: 3.1.0
info:
  title: External API
  version: 86af1652d4f82e2143ff2f8a2c82349f124e7999
servers:
  - url: https://api.tryprofound.com
    description: Production Server
security: []
paths:
  /v2/reports/social/youtube/channels:
    post:
      tags:
        - Reports
        - Reports
      summary: Query Youtube Channels
      description: >-
        Rank the YouTube channels cited in a category, or the video categories
        they publish in.
      operationId: query_youtube_channels_v2_reports_social_youtube_channels_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/YoutubeChannelsQuery'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YoutubeChannelsResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - APIKeyHeader: []
        - BearerAuth: []
      x-codeSamples:
        - lang: JavaScript
          source: |-
            import Profound from '@profoundai/client';

            const client = new Profound({
              apiKey: process.env['PROFOUND_API_KEY'], // This is the default and can be omitted
            });

            const response = await client.reports.social.youtube.getChannels({
              category_id: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e',
              end_date: 'end_date',
              start_date: 'start_date',
            });

            console.log(response.data);
        - lang: Python
          source: |-
            import os
            from profound import Profound

            client = Profound(
                api_key=os.environ.get("PROFOUND_API_KEY"),  # This is the default and can be omitted
            )
            response = client.reports.social.youtube.get_channels(
                category_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
                end_date="end_date",
                start_date="start_date",
            )
            print(response.data)
components:
  schemas:
    YoutubeChannelsQuery:
      properties:
        category_id:
          type: string
          format: uuid
          title: Category Id
        start_date:
          type: string
          title: Start Date
          description: YYYY-MM-DD, ET, inclusive
        end_date:
          type: string
          title: End Date
          description: YYYY-MM-DD, ET, inclusive
        filter:
          anyOf:
            - $ref: '#/components/schemas/FilterNode'
            - type: 'null'
          description: >-
            Advanced filter tree. Prompt-level dimensions are `model`, `topic`,
            `region`, `prompt`, `persona`, `tag`, `analysis_type`. `channel`
            covers both channel cases: `in` with a list of handles selects
            exactly those channels, resolving each handle to its channel so a
            renamed channel is never returned in pieces; `contains` matches a
            channel's title or handle by name. Combine with `and`/`or`/`not` up
            to 3 deep. An exact `channel` selection must be its own `and`
            clause, and a `channel` leaf cannot share an `or` or `not` with a
            prompt-level leaf, because those compile at different stages of the
            query. `domain` and `page` are rejected rather than approximated:
            every row here is one domain, and `page` is not a video id.
        limit:
          anyOf:
            - type: integer
              maximum: 50
              exclusiveMinimum: 0
            - type: 'null'
          title: Limit
          description: Page size; default 10, max 50.
        cursor:
          anyOf:
            - type: string
            - type: 'null'
          title: Cursor
        source_types:
          anyOf:
            - items:
                type: string
                enum:
                  - video
                  - short
                  - channel
                  - playlist
                  - other
              type: array
            - type: 'null'
          title: Source Types
          description: >-
            Limit results to YouTube source types: `video`, `short`, `channel`,
            `playlist`, or `other`. Omit to include `video`, `short`, `channel`,
            and `playlist`; `other` is excluded because those citations have no
            channel. Requests containing `other` are rejected.
        group_by:
          items:
            type: string
            enum:
              - channel
              - video_category
              - model
              - source_type
          type: array
          title: Group By
          description: >-
            What each row represents. Empty or `["channel"]` ranks channels;
            `["video_category"]` ranks content categories; `["source_type"]`
            ranks source types; `["channel", "video_category"]`, `["channel",
            "source_type"]` and `["channel", "model"]` return cross-tabs — a row
            per channel per category, or per answer engine. `limit` counts
            leading channels in every case, so ten channels across nine engines
            is ten channels and ninety rows.
        interval:
          anyOf:
            - type: string
              enum:
                - day
                - week
                - month
            - type: 'null'
          title: Interval
          description: >-
            Return a time series instead of window totals: one row per entity
            per period, each carrying `date`. `citation_share` is then relative
            to that period, so the series is comparable across periods. Omit for
            window totals.
      additionalProperties: false
      type: object
      required:
        - category_id
        - start_date
        - end_date
      title: YoutubeChannelsQuery
      description: Channel and category rollups.
    YoutubeChannelsResponse:
      properties:
        info:
          $ref: '#/components/schemas/YoutubeChannelsInfo'
        data:
          items:
            $ref: '#/components/schemas/YoutubeChannelRow'
          type: array
          title: Data
      type: object
      required:
        - info
        - data
      title: YoutubeChannelsResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    FilterNode:
      properties:
        and:
          anyOf:
            - items:
                $ref: '#/components/schemas/FilterNode'
              type: array
            - type: 'null'
          title: And
        or:
          anyOf:
            - items:
                $ref: '#/components/schemas/FilterNode'
              type: array
            - type: 'null'
          title: Or
        not:
          anyOf:
            - $ref: '#/components/schemas/FilterNode'
            - type: 'null'
        field:
          anyOf:
            - type: string
            - type: 'null'
          title: Field
        op:
          anyOf:
            - type: string
            - type: 'null'
          title: Op
        value:
          title: Value
      additionalProperties: false
      type: object
      title: FilterNode
      description: A leaf (`field`/`op`/`value`) or an `and`/`or`/`not` group.
    YoutubeChannelsInfo:
      properties:
        total_results:
          type: integer
          title: Total Results
          description: >-
            Distinct leading channels matching the window; this can differ from
            the number of rows returned.
        count:
          type: integer
          title: Count
          description: Number of rows returned in `data` for this page.
        next_cursor:
          anyOf:
            - type: string
            - type: 'null'
          title: Next Cursor
          description: Opaque cursor for the next page; null on the last page.
        models:
          items:
            type: string
          type: array
          title: Models
          description: Display names of the models the report covers.
        start_date:
          type: string
          title: Start Date
          description: Echoed request start date (YYYY-MM-DD, ET).
        end_date:
          type: string
          title: End Date
          description: Echoed request end date (YYYY-MM-DD, ET).
        filter:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Filter
          description: Echoed normalized filter tree, or null when no filter was sent.
        category_id:
          type: string
          format: uuid
          title: Category Id
          description: Echoed category id this report covers.
        source_types:
          items:
            type: string
            enum:
              - video
              - short
              - channel
              - playlist
              - other
          type: array
          title: Source Types
          description: >-
            Source types this report covers. Derived from the request, not
            returned rows, so a listed type may have no rows.
        cursor:
          anyOf:
            - type: string
            - type: 'null'
          title: Cursor
          description: Echoed request cursor; omitted on the first page.
        limit:
          type: integer
          title: Limit
          description: Effective page size in leading channels, not returned rows.
        interval:
          anyOf:
            - type: string
              enum:
                - day
                - week
                - month
            - type: 'null'
          title: Interval
          description: >-
            Effective channel time-series interval, or null when the channel
            report covers the full window.
        group_by:
          items:
            type: string
          type: array
          title: Group By
          description: >-
            Echoed dimensions that define a row. Channel reports echo
            `["channel"]` when group_by is omitted.
      additionalProperties: true
      type: object
      required:
        - total_results
        - count
        - models
        - start_date
        - end_date
        - category_id
        - source_types
        - limit
        - group_by
      title: YoutubeChannelsInfo
      description: >-
        Channel report metadata, including effective paging and grouping
        settings.
    YoutubeChannelRow:
      properties:
        name:
          type: string
          title: Name
          description: >-
            Channel title when grouped by channel, or the handle when no title
            resolved; category name when grouped by `["video_category"]`; source
            type when grouped by `["source_type"]`.
        handle:
          anyOf:
            - type: string
            - type: 'null'
          title: Handle
          description: >-
            Channel handle without the `@`, and the identifier this API exposes.
            Pass it to /videos as `channel_handle`. Null for the rare channel
            whose handle did not resolve.
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: Url
          description: Openable channel URL. Null for video-category rows.
        rank:
          type: integer
          title: Rank
          description: >-
            Leading channel's 1-based position in the full ranked set,
            continuing across pages; repeated across that channel's cross-tab
            rows rather than numbering rows.
        date:
          anyOf:
            - type: string
            - type: 'null'
          title: Date
          description: Period start. Present when `interval` is set.
        video_category:
          anyOf:
            - type: string
            - type: 'null'
          title: Video Category
          description: >-
            Populated for a secondary video-category slice; with group_by
            `["video_category"]`, the category is returned in `name` instead. An
            unresolved category is returned as an empty string.
        model:
          anyOf:
            - $ref: '#/components/schemas/DimensionRef'
            - type: 'null'
          description: >-
            Answer engine as an object `{id, name}`, present when grouped by
            model. The name matches `info.models`; the id is the model id the
            other reports accept.
        source_type:
          anyOf:
            - type: string
              enum:
                - video
                - short
                - channel
                - playlist
                - other
            - type: 'null'
          title: Source Type
          description: >-
            YouTube source type, present when grouped by source type, including
            as the second dimension of a cross-tab.
        count:
          type: integer
          title: Count
          description: Citations attributed to this row.
        videos:
          type: integer
          title: Videos
          description: Distinct videos of this channel that were cited.
        citation_share:
          type: number
          title: Citation Share
          description: >-
            Share of every YouTube citation in the window (attributed and
            unattributed alike), or the period when `interval` is set,
            regardless of `source_types`. An unnarrowed complete ranking sums to
            slightly less than 1 because unattributed citations cannot appear in
            channel rows; a narrowed ranking sums to its slice's share.
      additionalProperties: true
      type: object
      required:
        - name
        - rank
        - count
        - videos
        - citation_share
      title: YoutubeChannelRow
      description: One channel (or video category) row, optionally sliced.
    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
    DimensionRef:
      properties:
        id:
          anyOf:
            - type: string
            - type: 'null'
          title: Id
        name:
          anyOf:
            - type: string
            - type: 'null'
          title: Name
      type: object
      title: DimensionRef
      description: An ``{id, name}`` reference for a grouped dimension value.
  securitySchemes:
    APIKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
    BearerAuth:
      type: http
      scheme: bearer

````