Planable Social Listening API

The Social Listening API from Planable — 7 operation(s). Track brand and topic keywords for a workspace, then read matched mentions, daily metrics, aggregated summaries and sync status.

OpenAPI Specification

planable-social-listening-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Planable Public Social Listening 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: Social Listening
paths:
  /keywords:
    get:
      tags:
      - Social Listening
      summary: List tracked keywords
      description: Lists the keywords tracked for a workspace, optionally filtered by type.
      parameters:
      - name: workspaceId
        in: query
        required: true
        schema:
          type: string
      - name: type
        in: query
        required: false
        schema:
          type: string
          enum:
          - brand
          - topic
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Tracked keywords
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        keywordId:
                          type: string
                        text:
                          type: string
                        type:
                          type: string
                          enum:
                          - brand
                          - topic
                        createdAt:
                          type: string
                          format: date-time
                      required:
                      - keywordId
                      - text
                      - type
                      - createdAt
                required:
                - data
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this workspace
        '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:
      - Social Listening
      summary: Track a keyword
      description: Starts tracking a keyword for a workspace. Re-adding an already-tracked keyword is
        idempotent — it returns 200 with the existing row instead of creating a duplicate. The response
        contains the keyword object only (no sync state); poll `GET /keywords/{keywordId}/sync-status`
        until the sync completes, same contract as `POST /pages/{id}/sync` → `GET /pages/{id}/sync-status`.
      security:
      - bearerAuth:
        - write
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                workspaceId:
                  type: string
                  minLength: 1
                keyword:
                  type: string
                  minLength: 1
                  maxLength: 200
                type:
                  type: string
                  enum:
                  - brand
                  - topic
                  default: topic
              required:
              - workspaceId
              - keyword
      responses:
        '200':
          description: Keyword was already tracked (idempotent re-add)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      keywordId:
                        type: string
                      text:
                        type: string
                      type:
                        type: string
                        enum:
                        - brand
                        - topic
                      createdAt:
                        type: string
                        format: date-time
                    required:
                    - keywordId
                    - text
                    - type
                    - createdAt
                required:
                - data
        '201':
          description: Keyword is now tracked
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      keywordId:
                        type: string
                      text:
                        type: string
                      type:
                        type: string
                        enum:
                        - brand
                        - topic
                      createdAt:
                        type: string
                        format: date-time
                    required:
                    - keywordId
                    - text
                    - type
                    - createdAt
                required:
                - data
        '400':
          description: Keyword limit reached, brand limit reached, or type conflict with an existing listener
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token lacks the write scope, workspace is outside token scope, or workspace is
            a sample workspace
        '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'
  /keywords/{keywordId}:
    delete:
      tags:
      - Social Listening
      summary: Stop tracking a keyword
      description: Stops tracking a keyword on a workspace. Returns 204 when the listener is removed.
      security:
      - bearerAuth:
        - write
      parameters:
      - name: keywordId
        in: path
        required: true
        schema:
          type: string
      - name: workspaceId
        in: query
        required: true
        schema:
          type: string
      responses:
        '204':
          description: Keyword untracked
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token lacks the write scope, workspace is outside token scope, or workspace is
            a sample workspace
        '404':
          description: Keyword is not tracked by this workspace
        '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'
  /keywords/{keywordId}/mentions:
    get:
      tags:
      - Social Listening
      summary: List mentions for a tracked keyword
      description: Windowed mentions for a keyword, with optional platform/sentiment filter and sort.
        Brand listeners only return brand mentions. Mentions are returned as a curated, typed shape —
        common fields plus per-platform metric fields as optional properties.
      parameters:
      - name: keywordId
        in: path
        required: true
        schema:
          type: string
      - name: workspaceId
        in: query
        required: true
        schema:
          type: string
      - name: range
        in: query
        required: false
        schema:
          type: string
          enum:
          - 7d
          - 14d
          - 30d
          default: 7d
      - name: startDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
      - name: endDate
        in: query
        required: false
        schema:
          type: string
          format: date-time
      - name: platform
        in: query
        required: false
        schema:
          type: string
          enum:
          - twitter
          - youtube
          - reddit
          - tiktok
          - facebook
          - instagram
      - name: sentiment
        in: query
        required: false
        schema:
          type: string
          enum:
          - all
          - positive
          - negative
          - neutral
          default: all
      - name: sortBy
        in: query
        required: false
        schema:
          type: string
          enum:
          - engagement
          - recency
          default: engagement
      - name: cursor
        in: query
        required: false
        schema:
          type: integer
          minimum: 0
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Mentions for the keyword
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        platform:
                          type: string
                        publishedAt:
                          type: string
                          format: date-time
                        engagement:
                          type: number
                        sentiment:
                          type: string
                          enum:
                          - positive
                          - negative
                          - neutral
                        url:
                          type: string
                        text:
                          type: string
                        author:
                          type: object
                          properties:
                            name:
                              type: string
                            username:
                              type:
                              - string
                              - 'null'
                            profileImageUrl:
                              type:
                              - string
                              - 'null'
                          required:
                          - name
                          - username
                          - profileImageUrl
                        likes:
                          type: number
                        comments:
                          type: number
                        shares:
                          type: number
                        views:
                          type: number
                        upvotes:
                          type: number
                        replies:
                          type: number
                        retweets:
                          type: number
                        quotes:
                          type: number
                        bookmarks:
                          type: number
                        impressions:
                          type: number
                        plays:
                          type: number
                        saves:
                          type: number
                      required:
                      - platform
                      - publishedAt
                      - engagement
                      - url
                      - text
                      - author
                  pagination:
                    type: object
                    properties:
                      nextCursor:
                        type:
                        - number
                        - 'null'
                      total:
                        type: number
                    required:
                    - nextCursor
                    - total
                required:
                - data
                - pagination
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this workspace
        '404':
          description: Keyword is not tracked by this workspace
        '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'
  /keywords/{keywordId}/metrics/summary:
    get:
      tags:
      - Social Listening
      summary: Aggregated metrics for a tracked keyword
      description: Aggregated mention, engagement, sentiment, and per-platform totals for a keyword over
        a window. Internal API-spend fields are never exposed.
      parameters:
      - name: keywordId
        in: path
        required: true
        schema:
          type: string
      - name: workspaceId
        in: query
        required: true
        schema:
          type: string
      - name: range
        in: query
        required: false
        schema:
          type: string
          enum:
          - 7d
          - 14d
          - 30d
          default: 7d
      - 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: Aggregated metrics summary
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mentions:
                        type: number
                      engagement:
                        type: number
                      sentiment:
                        type: object
                        properties:
                          positive:
                            type: number
                          negative:
                            type: number
                          neutral:
                            type: number
                        required:
                        - positive
                        - negative
                        - neutral
                      platformBreakdown:
                        type: object
                        additionalProperties:
                          type: object
                          properties:
                            mentions:
                              type: number
                            engagement:
                              type: number
                          required:
                          - mentions
                          - engagement
                      daysWithData:
                        type: number
                    required:
                    - mentions
                    - engagement
                    - sentiment
                    - platformBreakdown
                    - daysWithData
                required:
                - data
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this workspace
        '404':
          description: Keyword is not tracked by this workspace
        '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'
  /keywords/{keywordId}/metrics:
    get:
      tags:
      - Social Listening
      summary: Daily metrics for a tracked keyword
      description: Daily mention, engagement, sentiment, and per-platform breakdown for a keyword over
        a window. Internal API-spend fields (costs/totalCost) are never exposed.
      parameters:
      - name: keywordId
        in: path
        required: true
        schema:
          type: string
      - name: workspaceId
        in: query
        required: true
        schema:
          type: string
      - name: range
        in: query
        required: false
        schema:
          type: string
          enum:
          - 7d
          - 14d
          - 30d
          default: 7d
      - 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: Daily metrics series
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        date:
                          type: string
                          format: date-time
                        mentions:
                          type: number
                        engagement:
                          type: number
                        sentiment:
                          type: object
                          properties:
                            positive:
                              type: number
                            negative:
                              type: number
                            neutral:
                              type: number
                          required:
                          - positive
                          - negative
                          - neutral
                        platformBreakdown:
                          type: object
                          additionalProperties:
                            type: object
                            properties:
                              mentions:
                                type: number
                              engagement:
                                type: number
                            required:
                            - mentions
                            - engagement
                      required:
                      - date
                      - mentions
                      - engagement
                      - platformBreakdown
                required:
                - data
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this workspace
        '404':
          description: Keyword is not tracked by this workspace
        '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'
  /keywords/{keywordId}/sync-status:
    get:
      tags:
      - Social Listening
      summary: Get keyword sync status
      description: Polls the sync job status for a tracked keyword. After `POST /keywords`, poll this
        endpoint until `status` is `complete` (or `removed` if the keyword was deleted mid-poll). Mirrors
        `GET /pages/{id}/sync-status`.
      parameters:
      - name: keywordId
        in: path
        required: true
        schema:
          type: string
      - name: workspaceId
        in: query
        required: true
        schema:
          type: string
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Keyword sync status
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      keywordId:
                        type: string
                      status:
                        type: string
                        enum:
                        - running
                        - complete
                        - removed
                      totalJobs:
                        type: integer
                        minimum: 0
                      completedJobs:
                        type: integer
                        minimum: 0
                    required:
                    - keywordId
                    - status
                    - totalJobs
                    - completedJobs
                required:
                - data
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Token cannot read this workspace
        '404':
          description: Keyword has a listener but no sync jobs were 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'
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