Planable Competitors API

The Competitors API from Planable — 6 operation(s). Track up to five competitor social pages per page and pull comparison tables, follower/engagement trends and competitor top posts. Requires the Analytics add-on.

OpenAPI Specification

planable-competitors-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Planable Public Competitors API
  version: 1.0.0
  description: 'REST API for managing Planable companies, workspaces, pages, posts and more.


    **Plan eligibility:** new API tokens can only be generated by companies on the **Pro** and **Enterprise**
    plans. Tokens that have already been generated continue to work regardless of plan.'
servers:
- url: https://api.planable.io/api/v1
security:
- bearerAuth: []
tags:
- name: Competitors
paths:
  /pages/{id}/competitors:
    get:
      tags:
      - Competitors
      summary: List tracked competitors
      description: Lists the competitors tracked for one of your pages. Instagram, Facebook, YouTube,
        TikTok, LinkedIn pages only.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Tracked competitors
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        trackedCompetitorId:
                          type: string
                        scrapedPageId:
                          type:
                          - string
                          - 'null'
                        handle:
                          type: string
                        displayName:
                          type: string
                        platform:
                          type: string
                        profileImageUrl:
                          type:
                          - string
                          - 'null'
                        syncStatus:
                          type: string
                        lastSyncedAt:
                          type:
                          - string
                          - 'null'
                          format: date-time
                      required:
                      - trackedCompetitorId
                      - scrapedPageId
                      - handle
                      - displayName
                      - platform
                      - profileImageUrl
                      - syncStatus
                      - lastSyncedAt
                required:
                - data
        '400':
          description: Page type does not support competitor analytics
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this page or the Analytics add-on is inactive
        '404':
          description: Page not found
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      tags:
      - Competitors
      summary: Track a competitor
      description: Starts tracking a competitor for one of your pages, identified by @handle or profile
        URL. Capped at 5 competitors per page. Re-adding an already-tracked competitor is idempotent —
        it returns 200 with the existing row instead of creating a duplicate. Instagram, Facebook, YouTube,
        TikTok, LinkedIn pages only.
      security:
      - bearerAuth:
        - write
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                handle:
                  type: string
                  minLength: 1
                url:
                  type: string
                  minLength: 1
      responses:
        '200':
          description: Competitor was already tracked (idempotent re-add)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      trackedCompetitorId:
                        type: string
                      scrapedPageId:
                        type:
                        - string
                        - 'null'
                      handle:
                        type: string
                      displayName:
                        type: string
                      platform:
                        type: string
                      profileImageUrl:
                        type:
                        - string
                        - 'null'
                      syncStatus:
                        type: string
                      lastSyncedAt:
                        type:
                        - string
                        - 'null'
                        format: date-time
                    required:
                    - trackedCompetitorId
                    - scrapedPageId
                    - handle
                    - displayName
                    - platform
                    - profileImageUrl
                    - syncStatus
                    - lastSyncedAt
                required:
                - data
        '201':
          description: Competitor is now tracked
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      trackedCompetitorId:
                        type: string
                      scrapedPageId:
                        type:
                        - string
                        - 'null'
                      handle:
                        type: string
                      displayName:
                        type: string
                      platform:
                        type: string
                      profileImageUrl:
                        type:
                        - string
                        - 'null'
                      syncStatus:
                        type: string
                      lastSyncedAt:
                        type:
                        - string
                        - 'null'
                        format: date-time
                    required:
                    - trackedCompetitorId
                    - scrapedPageId
                    - handle
                    - displayName
                    - platform
                    - profileImageUrl
                    - syncStatus
                    - lastSyncedAt
                required:
                - data
        '400':
          description: Missing handle/url, unsupported page type, or the profile is currently unavailable
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token lacks the write scope, the Analytics add-on is inactive, or the competitor
            cap is reached
        '404':
          description: Page not found, or the handle could not be found on the platform
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /pages/{id}/competitors/comparison:
    get:
      tags:
      - Competitors
      summary: Compare your page against its competitors
      description: Your page and its tracked competitors over a window — followers, posts, total and average
        engagement. Own and competitor engagement use slightly different bases (own = platform-reported,
        competitor = scraped). Instagram, Facebook, YouTube, TikTok, LinkedIn pages only.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      - name: range
        in: query
        required: false
        schema:
          type: string
          enum:
          - 7d
          - 30d
          - 90d
          - all
          default: 30d
      - name: startDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
      - name: endDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Own + competitor comparison rows
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        isOwn:
                          type: boolean
                        displayName:
                          type: string
                        handle:
                          type: string
                        platform:
                          type: string
                        profileImageUrl:
                          type:
                          - string
                          - 'null'
                        followers:
                          type:
                          - number
                          - 'null'
                        posts:
                          type:
                          - number
                          - 'null'
                        totalEngagement:
                          type:
                          - number
                          - 'null'
                        avgEngagement:
                          type:
                          - number
                          - 'null'
                      required:
                      - id
                      - isOwn
                      - displayName
                      - handle
                      - platform
                      - profileImageUrl
                      - followers
                      - posts
                      - totalEngagement
                      - avgEngagement
                required:
                - data
        '400':
          description: Page type does not support competitor analytics
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this page or the Analytics add-on is inactive
        '404':
          description: Page not found
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /pages/{id}/competitors/metrics:
    get:
      tags:
      - Competitors
      summary: Follower & engagement trend for your page and its competitors
      description: Daily follower and engagement series for your page and each tracked competitor over
        a window. Own and competitor engagement use slightly different bases (own = platform-reported,
        competitor = scraped). Instagram, Facebook, YouTube, TikTok, LinkedIn pages only.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      - name: range
        in: query
        required: false
        schema:
          type: string
          enum:
          - 7d
          - 30d
          - 90d
          - all
          default: 30d
      - name: scrapedPageIds
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Optional competitor scrapedPageIds filter. Repeat the query param or pass a comma-separated
          list.
      - name: startDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
      - name: endDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Own + competitor trend series
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        isOwn:
                          type: boolean
                        handle:
                          type: string
                        displayName:
                          type: string
                        platform:
                          type: string
                        profileImageUrl:
                          type:
                          - string
                          - 'null'
                        points:
                          type: array
                          items:
                            type: object
                            properties:
                              date:
                                type: string
                                format: date-time
                              followers:
                                type:
                                - number
                                - 'null'
                              engagement:
                                type:
                                - number
                                - 'null'
                            required:
                            - date
                            - followers
                            - engagement
                      required:
                      - id
                      - isOwn
                      - handle
                      - displayName
                      - platform
                      - profileImageUrl
                      - points
                required:
                - data
        '400':
          description: Page type does not support competitor analytics
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this page or the Analytics add-on is inactive
        '404':
          description: Page not found
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /pages/{id}/competitors/top-posts:
    get:
      tags:
      - Competitors
      summary: Top posts across your page's competitors
      description: Top posts across all tracked competitors, merged and ranked by sortBy (descending),
        each tagged with its competitor. Competitors only — your own posts are available via /posts. Instagram,
        Facebook, YouTube, TikTok, LinkedIn pages only.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      - name: sortBy
        in: query
        required: true
        schema:
          type: string
          enum:
          - engagementRate
          - likes
          - views
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: range
        in: query
        required: false
        schema:
          type: string
          enum:
          - 7d
          - 30d
          - 90d
          - all
          default: 30d
      - name: scrapedPageIds
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Optional competitor scrapedPageIds filter. Repeat the query param or pass a comma-separated
          list.
      - name: startDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
      - name: endDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Top competitor posts
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        scrapedPageId:
                          type: string
                        handle:
                          type: string
                        url:
                          type: string
                        content:
                          type:
                          - string
                          - 'null'
                        mediaType:
                          type:
                          - string
                          - 'null'
                        postedAt:
                          type: string
                          format: date-time
                        likes:
                          type: number
                        comments:
                          type: number
                        shares:
                          type:
                          - number
                          - 'null'
                        views:
                          type:
                          - number
                          - 'null'
                        engagementRate:
                          type:
                          - number
                          - 'null'
                        hashtags:
                          type: array
                          items:
                            type: string
                      required:
                      - scrapedPageId
                      - handle
                      - url
                      - content
                      - mediaType
                      - postedAt
                      - likes
                      - comments
                      - shares
                      - views
                      - engagementRate
                      - hashtags
                required:
                - data
        '400':
          description: Validation error or page type does not support competitor analytics
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this page or the Analytics add-on is inactive
        '404':
          description: Page not found
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /pages/{id}/competitors/{scrapedPageId}:
    delete:
      tags:
      - Competitors
      summary: Stop tracking a competitor
      description: Stops tracking a competitor on your page. Re-adding within the cooling window restores
        its history. Instagram, Facebook, YouTube, TikTok, LinkedIn pages only.
      security:
      - bearerAuth:
        - write
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      - name: scrapedPageId
        in: path
        required: true
        schema:
          type: string
      responses:
        '204':
          description: Competitor untracked
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token lacks the write scope or the Analytics add-on is inactive
        '404':
          description: Page not found, or the competitor is not tracked by this page
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: pln_*
  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
              - VALIDATION_ERROR
              - UNAUTHORIZED
              - FORBIDDEN
              - NOT_FOUND
              - METHOD_NOT_ALLOWED
              - RATE_LIMITED
              - POST_ALREADY_PUBLISHED
              - PUBLISHING_IN_PROGRESS
              - WORKSPACE_LIMIT_REACHED
              - INTERNAL
            message:
              type: string
            requestId:
              type: string
          required:
          - code
          - message
          - requestId
      required:
      - error