openapi: 3.0.0
info:
  title: YouTube Channel Posts API
  description: |
    List the community posts of a YouTube channel from its Posts tab. Posts can include the full
    text with resolved links, exact like counts, polls, quizzes with correct answers, and image,
    video, and playlist attachments. Reposts embed the original post. Use
    `pagination.next_page_token` to page through the channel's post history.

    **Cross-linking**: Each post's `id` can be used with the YouTube Post API (`post_id`
    parameter), or its `link` as `url`. The `channel.id` works with the YouTube Channel API (`channel_id` parameter), and
    video attachment `id` values work with the YouTube Video API (`video_id` parameter).

    **Limitations**: The Posts tab only exposes relative publish times (e.g. "1 month ago"). Use the
    YouTube Post API for a post's exact `publish_date`. Poll results are limited to total votes and choices.
  version: 1.0.0
servers:
  - url: https://www.searchapi.io/api/v1
paths:
  /search:
    get:
      summary: YouTube Channel Posts
      security:
        - ApiKeyAuth: []
        - ApiKeyQuery: []
      parameters:
        - name: engine
          in: query
          required: true
          description: Parameter defines the engine that will be used to retrieve real-time data. It must be set to `youtube_channel_posts`.
          schema:
            type: string
            default: "youtube_channel_posts"
        - name: channel_id
          in: query
          required: true
          description: 'The YouTube channel to query. Accepts a channel ID (e.g. `UCX6OQ3DkcsbYNE6H8uQQuVA`) or an `@` handle (e.g. `@MrBeast`).'
          schema:
            type: string
        - name: gl
          in: query
          required: false
          description: Defines the country of the search.
          schema:
            type: string
            enum: ["DZ", "AR", "AU", "AT", "AZ", "BH", "BD", "BY", "BE", "BO", "BA", "BR", "BG", "KH", "CA", "CL", "CO", "CR", "HR", "CY", "CZ", "DK", "DO", "EC", "EG", "SV", "EE", "FI", "FR", "GE", "DE", "GH", "GR", "GT", "HN", "HK", "HU", "IS", "IN", "ID", "IQ", "IE", "IL", "IT", "JM", "JP", "JO", "KZ", "KE", "KW", "LA", "LV", "LB", "LY", "LI", "LT", "LU", "MY", "MT", "MX", "ME", "MA", "NP", "NL", "NZ", "NI", "NG", "MK", "NO", "OM", "PK", "PA", "PG", "PY", "PE", "PH", "PL", "PT", "PR", "QA", "RO", "RU", "SA", "SN", "RS", "SG", "SK", "SI", "ZA", "KR", "ES", "LK", "SE", "CH", "TW", "TZ", "TH", "TN", "TR", "UG", "UA", "AE", "GB", "US", "UY", "VE", "VN", "YE", "ZW"]
            default: "US"
        - name: hl
          in: query
          required: false
          description: Defines the interface language of the search.
          schema:
            type: string
            enum: ["af", "az", "id", "ms", "bs", "ca", "cs", "da", "de", "et", "en-in", "en-gb", "en", "es", "es-419", "es-us", "eu", "fil", "fr", "fr-ca", "gl", "hr", "zu", "is", "it", "sw", "lv", "lt", "hu", "nl", "no", "uz", "pl", "pt-pt", "pt", "ro", "sq", "sk", "sl", "sr-latn", "fi", "sv", "vi", "tr", "be", "bg", "ky", "kk", "mk", "mn", "ru", "sr", "uk", "el", "hy", "iw", "ur", "ar", "fa", "ne", "mr", "hi", "as", "bn", "pa", "gu", "or", "ta", "te", "kn", "ml", "si", "th", "lo", "my", "ka", "am", "km", "zh-cn", "zh-tw", "zh-hk", "ja", "ko"]
            default: "en"
        - name: next_page_token
          in: query
          required: false
          description: 'Token from a previous response''s `pagination.next_page_token`, used to retrieve the next page of posts. Must be sent with the same `channel_id`.'
          schema:
            type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          description: Validation Error. There is an issue with query parameters, such as missing required parameters, invalid values, a `next_page_token` that could not be decoded or belongs to another channel, or a `channel_id` that is a legacy custom URL redirecting elsewhere. The request is not billed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Authentication Error. The API key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found. The channel does not exist, so retrying cannot return results. The request is not billed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate Limit Exceeded. The number of allowed requests has been exceeded. Consider upgrading your plan or waiting for the limit to reset.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Server Error. Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: The `next_page_token` was rejected, or we could not retrieve results in 90 seconds. A rejected `next_page_token` needs a fresh first-page request. The request is not billed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: 'Use Bearer authentication. Format: "Bearer YOUR_API_KEY"'
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api_key
      description: Pass API key as query parameter
  schemas:
    SearchResponse:
      type: object
      properties:
        search_metadata:
          $ref: '#/components/schemas/SearchMetadata'
        search_parameters:
          $ref: '#/components/schemas/SearchParameters'
        channel:
          $ref: '#/components/schemas/Channel'
        posts:
          type: array
          description: Community posts on this page, around 10 per request
          items:
            $ref: '#/components/schemas/Post'
        pagination:
          $ref: '#/components/schemas/Pagination'
        error:
          type: string
          description: Message returned instead of posts when the channel has no community posts
    SearchMetadata:
      type: object
      required: [id, status, created_at]
      properties:
        id:
          type: string
          description: "Unique identifier for the search request"
        status:
          type: string
          description: "Status of the search request"
        created_at:
          type: string
          format: date-time
          description: "Timestamp when the search was created"
        request_time_taken:
          type: number
          description: "Time taken to make the request in seconds"
        parsing_time_taken:
          type: number
          description: "Time taken to parse the results in seconds"
        total_time_taken:
          type: number
          description: "Total time taken for the search in seconds"
        request_url:
          type: string
          description: "YouTube channel posts URL for this search"
        html_url:
          type: string
          description: "URL to view HTML results"
        json_url:
          type: string
          description: "URL to view JSON results"
    SearchParameters:
      type: object
      properties:
        engine:
          type: string
          description: The search engine used
        channel_id:
          type: string
          description: The channel ID or '@' handle queried
        gl:
          type: string
          description: Country of the search
        hl:
          type: string
          description: Interface language of the search
        next_page_token:
          type: string
          description: Pagination token used for this page
    Channel:
      type: object
      description: Metadata of the queried channel
      properties:
        id:
          type: string
          description: Channel identifier
        title:
          type: string
          description: Channel name
        handle:
          type: string
          description: 'Channel handle including the `@` prefix'
        subscribers:
          type: integer
          description: Subscriber count
        videos:
          type: integer
          description: Video count
        description:
          type: string
          description: Channel description
        keywords:
          type: string
          description: Channel keywords
        tags:
          type: array
          items:
            type: string
          description: Channel tags
        available_countries:
          type: array
          items:
            type: string
          description: Countries where the channel is available
        badges:
          type: array
          items:
            type: string
          description: Channel badges and certifications
        first_link:
          type: string
          description: First external link on the channel header
        is_verified:
          type: boolean
          description: Whether the channel is verified
        is_family_safe:
          type: boolean
          description: Whether the channel is family-safe
        is_unlisted:
          type: boolean
          description: Whether the channel is unlisted
        facebook_profile_id:
          type: string
          description: Associated Facebook profile ID
        banner:
          type: string
          description: Channel banner image URL
        avatar:
          type: string
          description: Channel avatar URL
    Post:
      allOf:
        - $ref: '#/components/schemas/PostBody'
        - type: object
          required: [position]
          properties:
            position:
              type: integer
              description: Position of the post on the current page, starting at 1
    PostBody:
      type: object
      required: [id, link]
      properties:
        id:
          type: string
          description: Community post identifier
        link:
          type: string
          description: Canonical URL of the post
        channel:
          $ref: '#/components/schemas/PostChannel'
        content:
          type: string
          description: Full post text
        content_links:
          type: array
          description: Links found in the post text with full destination URLs resolved (post text truncates long URLs)
          items:
            $ref: '#/components/schemas/ContentLink'
        hashtags:
          type: array
          description: Hashtags used in the post text, without the leading `#`
          items:
            type: string
        likes:
          type: string
          description: Abbreviated like count as displayed (e.g. "98K")
        extracted_likes:
          type: integer
          description: Exact like count
        comments:
          type: string
          description: Abbreviated comment count as displayed (e.g. "3.6K")
        extracted_comments:
          type: integer
          description: Approximate comment count expanded from the abbreviated label (e.g. "3.6K" becomes 3600)
        published_time:
          type: string
          description: Relative publish time as YouTube labels it in the requested `hl` (e.g. "1 month ago")
        is_edited:
          type: boolean
          description: Whether the post was edited after publishing
        is_members_only:
          type: boolean
          description: Whether the post is visible to channel members only
        poll:
          $ref: '#/components/schemas/Poll'
        quiz:
          $ref: '#/components/schemas/Quiz'
        attachments:
          type: array
          description: Image, video, or playlist attachments
          items:
            oneOf:
              - $ref: '#/components/schemas/ImageAttachment'
              - $ref: '#/components/schemas/VideoAttachment'
              - $ref: '#/components/schemas/PlaylistAttachment'
        is_repost:
          type: boolean
          description: Whether the post is a repost of another community post
        original_post:
          allOf:
            - $ref: '#/components/schemas/PostBody'
          description: The original post of a repost, without a `position`
    PostChannel:
      type: object
      required: [id, title, link]
      properties:
        id:
          type: string
          description: Channel identifier
        title:
          type: string
          description: Channel name
        handle:
          type: string
          description: 'Channel handle including the `@` prefix (e.g. "@MrBeast")'
        link:
          type: string
          description: Channel URL
        thumbnail:
          type: string
          description: Channel avatar URL
    ContentLink:
      type: object
      properties:
        text:
          type: string
          description: The link text as displayed in the post (may be truncated)
        link:
          type: string
          description: Full destination URL
    Poll:
      type: object
      properties:
        total_votes:
          type: string
          description: Total votes as displayed (e.g. "1.7M votes")
        extracted_total_votes:
          type: integer
          description: Approximate total votes expanded from the abbreviated label (e.g. "23K votes" becomes 23000)
        choices:
          type: array
          items:
            $ref: '#/components/schemas/PollChoice'
    PollChoice:
      type: object
      properties:
        text:
          type: string
          description: Choice text
        image:
          type: string
          description: Choice image URL
    Quiz:
      type: object
      properties:
        total_answers:
          type: string
          description: Total answers as displayed (e.g. "17K answered")
        extracted_total_answers:
          type: integer
          description: Approximate total answers expanded from the abbreviated label (e.g. "17K answered" becomes 17000)
        explanation:
          type: string
          description: Explanation shown after answering
        choices:
          type: array
          items:
            $ref: '#/components/schemas/QuizChoice'
    QuizChoice:
      type: object
      properties:
        text:
          type: string
          description: Choice text
        is_correct:
          type: boolean
          description: Whether this choice is the correct answer
    ImageAttachment:
      type: object
      properties:
        type:
          type: string
          enum: ["image"]
        image:
          type: string
          description: Image URL in the highest available resolution
    VideoAttachment:
      type: object
      properties:
        type:
          type: string
          enum: ["video"]
        id:
          type: string
          description: Video identifier
        title:
          type: string
          description: Video title
        description:
          type: string
          description: Video description snippet
        link:
          type: string
          description: Video URL
        is_unavailable:
          type: boolean
          description: Whether the video is no longer publicly available
        length:
          type: string
          description: 'Video duration (e.g. "14:17")'
        length_seconds:
          type: integer
          description: Video duration in seconds
        views:
          type: integer
          description: View count
        published_time:
          type: string
          description: Relative publish time of the video
        thumbnail:
          type: string
          description: Video thumbnail URL
        channel:
          $ref: '#/components/schemas/VideoChannel'
        collaborators:
          type: array
          description: Channels credited on a collaboration video, starting with channel
          items:
            $ref: '#/components/schemas/VideoChannel'
    VideoChannel:
      type: object
      description: Channel the video belongs to
      properties:
        id:
          type: string
          description: Channel identifier
        title:
          type: string
          description: Channel name
        link:
          type: string
          description: Channel URL
        thumbnail:
          type: string
          description: Channel avatar URL
        is_verified:
          type: boolean
          description: Whether the channel is verified
    PlaylistAttachment:
      type: object
      properties:
        type:
          type: string
          enum: ["playlist"]
        id:
          type: string
          description: Playlist identifier
        title:
          type: string
          description: Playlist title
        link:
          type: string
          description: Playlist URL
        video_count:
          type: integer
          description: Number of videos in the playlist
        thumbnail:
          type: string
          description: Playlist thumbnail URL
        channel:
          type: object
          description: Channel the playlist belongs to
          properties:
            id:
              type: string
              description: Channel identifier
            title:
              type: string
              description: Channel name
            link:
              type: string
              description: Channel URL
            is_verified:
              type: boolean
              description: Whether the channel is verified
        videos:
          type: array
          description: Preview of the playlist's videos
          items:
            type: object
            properties:
              id:
                type: string
                description: Video identifier
              title:
                type: string
                description: Video title
              length:
                type: string
                description: Video duration
    Pagination:
      type: object
      properties:
        next_page_token:
          type: string
          description: Token to retrieve the next page of posts
    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: string
          description: Error message describing what went wrong
