Captivate Episodes API

List a show's published and scheduled episodes, read a single episode, and create or update episodes - linking uploaded media, show notes, season and episode numbers, publish date and status, and Apple Podcasts metadata.

OpenAPI Specification

captivate-fm-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Captivate API
  version: '1.0'
  description: >-
    Public REST API for the Captivate podcast hosting, distribution, and
    analytics platform. Authenticate a user with their user ID and API token to
    obtain a Bearer token, then manage shows, episodes, and media and read
    detailed listening analytics (insights). Endpoints, paths, methods, and
    request fields in this document are transcribed from Captivate's public
    Postman documentation at https://docs.captivate.fm. Response schemas are
    modeled honestly - Captivate's public docs describe the requests and fields
    but do not publish full JSON response schemas, so response bodies below are
    generic objects and marked as modeled.
  contact:
    name: Captivate API Support
    email: api@captivate.fm
    url: https://docs.captivate.fm/
  x-endpoints-source: >-
    Paths and request fields confirmed from the public Captivate API Postman
    collection (docs.captivate.fm). Response bodies are modeled.
servers:
- url: https://api.captivate.fm
  description: Captivate production API
tags:
- name: Authentication
  description: Exchange a user ID and API token for a Bearer token.
- name: Users
  description: Read a user and list the shows they can access or manage.
- name: Shows
  description: Read and update shows, upload artwork, get the RSS feed URL.
- name: Episodes
  description: List, read, create, and update episodes.
- name: Media
  description: Upload, read, list, and search a show's audio media.
- name: Analytics
  description: Podcast and episode listening analytics (insights).
paths:
  /authenticate/token:
    post:
      operationId: authenticateUser
      tags:
      - Authentication
      summary: Authenticate User
      description: >-
        All requests must be authenticated using a Bearer token for the user.
        Obtain the token by sending the user's ID and their API token (both
        found in the API section of the Captivate account). Returns a Bearer
        token used in the Authorization header for all other requests.
      security: []
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - username
              - token
              properties:
                username:
                  type: string
                  description: The Captivate user ID (UUID).
                  example: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                token:
                  type: string
                  description: The user's API token from their Captivate account.
      responses:
        '200':
          description: Authentication succeeded; a Bearer token is returned (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthToken'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /users/{id}:
    get:
      operationId: getUser
      tags:
      - Users
      summary: Get User
      description: Get a user record by user ID.
      parameters:
      - $ref: '#/components/parameters/UserId'
      responses:
        '200':
          description: The user record (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /users/{id}/shows:
    get:
      operationId: getUserShows
      tags:
      - Users
      summary: Get Users Shows
      description: The shows that this user can access regardless of their role.
      parameters:
      - $ref: '#/components/parameters/UserId'
      responses:
        '200':
          description: A list of shows the user can access (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /users/{id}/shows/manager:
    get:
      operationId: getUserManagedShows
      tags:
      - Users
      summary: Get Users Managed Shows
      description: >-
        The shows that the user is manager or owner of; they can create and
        invite new users to these shows.
      parameters:
      - $ref: '#/components/parameters/UserId'
      responses:
        '200':
          description: A list of shows the user manages or owns (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /shows/{id}/:
    get:
      operationId: getShow
      tags:
      - Shows
      summary: Get Show
      description: Get the show information by the show ID.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      responses:
        '200':
          description: The show record (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /shows/{id}:
    put:
      operationId: updateShow
      tags:
      - Shows
      summary: Update Show
      description: Update the show's metadata.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                title:
                  type: string
                  example: My Demo Show
                description:
                  type: string
                summary:
                  type: string
                subtitle:
                  type: string
                author:
                  type: string
                name:
                  type: string
                'categories[0]':
                  type: string
                  description: Apple Podcasts category code, e.g. 01.00.
                itunes_email:
                  type: string
                copyright:
                  type: string
                explicit:
                  type: string
                  description: e.g. clean, explicit.
                order:
                  type: string
                  example: DESC
                limit:
                  type: string
                type:
                  type: string
                  description: e.g. episodic or serial.
                language:
                  type: string
                  example: en
                donation_link:
                  type: string
                link:
                  type: string
                third_party_analytics:
                  type: string
                  description: Third-party analytics prefix, e.g. a Chartable tracking URL.
      responses:
        '200':
          description: The updated show (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /shows/{id}/artwork:
    post:
      operationId: createShowArtwork
      tags:
      - Shows
      summary: Create Show Artwork
      description: >-
        Upload the show's artwork. The file must be a JPG or PNG in the RGB
        colorspace (not CMYK), completely square, with a minimum of 1400px
        height.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - file
              properties:
                file:
                  type: string
                  format: binary
                  description: Square JPG or PNG artwork, RGB, minimum 1400px.
      responses:
        '200':
          description: Artwork accepted (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /shows/{id}/feed:
    get:
      operationId: getShowFeedUrl
      tags:
      - Shows
      summary: Get Show Feed URL
      description: Get the public RSS feed URL for this show.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      responses:
        '200':
          description: The RSS feed URL (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /shows/{id}/episodes:
    get:
      operationId: getShowEpisodes
      tags:
      - Episodes
      summary: Get Show Episodes
      description: >-
        A full breakdown of all the episodes for this show plus a count of the
        total number of episodes.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      responses:
        '200':
          description: The show's episodes and a count (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /shows/{id}/episodes/scheduled:
    get:
      operationId: getShowScheduledEpisodes
      tags:
      - Episodes
      summary: Get Show Scheduled Episodes
      description: All scheduled (future) episodes for this show plus a count.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      responses:
        '200':
          description: The show's scheduled episodes and a count (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /episodes/{id}:
    get:
      operationId: getEpisode
      tags:
      - Episodes
      summary: Get Episode
      description: Get the full information for an episode by episode ID.
      parameters:
      - $ref: '#/components/parameters/EpisodeId'
      responses:
        '200':
          description: The episode record (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
    put:
      operationId: updateEpisode
      tags:
      - Episodes
      summary: Update Episode
      description: Update an existing episode.
      parameters:
      - $ref: '#/components/parameters/EpisodeId'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/EpisodeInput'
      responses:
        '200':
          description: The updated episode (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /episodes:
    post:
      operationId: createEpisode
      tags:
      - Episodes
      summary: Create Episode
      description: Create an episode with the following parameters.
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/EpisodeInput'
      responses:
        '200':
          description: The created episode (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /media/{id}:
    get:
      operationId: getMedia
      tags:
      - Media
      summary: Get Media
      description: Get the information for this media ID.
      parameters:
      - $ref: '#/components/parameters/MediaId'
      responses:
        '200':
          description: The media record (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /shows/{id}/media:
    post:
      operationId: uploadMedia
      tags:
      - Media
      summary: Upload Media
      description: >-
        Upload a media (audio) file and assign it to the given show ID.
        Captivate processes the file server-side.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - file
              properties:
                file:
                  type: string
                  format: binary
                  description: The audio media file to upload.
      responses:
        '200':
          description: The uploaded media record (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      operationId: getShowMedia
      tags:
      - Media
      summary: Get Show Media
      description: >-
        Get all media for the given show ID. Media cannot be shared across
        shows, so this is scoped to a single show.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
      - name: order
        in: query
        schema:
          type: string
          default: created_at
      - name: sort
        in: query
        schema:
          type: string
          enum:
          - ASC
          - DESC
          default: DESC
      responses:
        '200':
          description: The show's media list (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /shows/{id}/media/search:
    get:
      operationId: searchShowMedia
      tags:
      - Media
      summary: Search Show Media
      description: Search a show's media by media name.
      parameters:
      - $ref: '#/components/parameters/ShowId'
      - name: search
        in: query
        required: true
        schema:
          type: string
        description: The media name search query.
      - name: offset
        in: query
        schema:
          type: integer
          default: 0
      - name: order
        in: query
        schema:
          type: string
          default: created_at
      - name: sort
        in: query
        schema:
          type: string
          enum:
          - ASC
          - DESC
          default: DESC
      responses:
        '200':
          description: Matching media (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/overview:
    get:
      operationId: getPodcastOverviewAnalytics
      tags:
      - Analytics
      summary: Get Overview Analytics for Podcast
      description: Overview analytics for a podcast over a date range.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      - $ref: '#/components/parameters/StartQuery'
      - $ref: '#/components/parameters/EndQuery'
      - name: includeTopEpisodes
        in: query
        schema:
          type: boolean
          default: true
      responses:
        '200':
          description: Podcast overview analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/overview/{episodeId}:
    get:
      operationId: getEpisodeOverviewAnalytics
      tags:
      - Analytics
      summary: Get Overview Analytics for a specific Episode
      description: Overview analytics for a specific episode over a date range.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      - $ref: '#/components/parameters/InsightsEpisodeId'
      - $ref: '#/components/parameters/StartQuery'
      - $ref: '#/components/parameters/EndQuery'
      responses:
        '200':
          description: Episode overview analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/averages:
    get:
      operationId: getPodcastAverageAnalytics
      tags:
      - Analytics
      summary: Get Average Analytics for Podcast
      description: Average analytics for a podcast over an interval window.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      - name: intervalDays
        in: query
        schema:
          type: integer
          default: 28
      responses:
        '200':
          description: Podcast average analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/total:
    get:
      operationId: getPodcastAllTimeTotal
      tags:
      - Analytics
      summary: Get All-Time Total for Podcast
      description: All-time total analytics for a podcast.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      responses:
        '200':
          description: Podcast all-time total (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/total/{episodeId}:
    get:
      operationId: getEpisodeAllTimeTotal
      tags:
      - Analytics
      summary: Get All-Time Total for Episode
      description: All-time total analytics for a specific episode.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      - $ref: '#/components/parameters/InsightsEpisodeId'
      responses:
        '200':
          description: Episode all-time total (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/monthly:
    get:
      operationId: getPodcastMonthlyAnalytics
      tags:
      - Analytics
      summary: Get Month-by-Month Analytics for Podcast
      description: Month-by-month analytics series for a podcast.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      responses:
        '200':
          description: Podcast monthly analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/monthly/{episodeId}:
    get:
      operationId: getEpisodeMonthlyAnalytics
      tags:
      - Analytics
      summary: Get Month-by-Month Analytics for Episode
      description: Month-by-month analytics series for a specific episode.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      - $ref: '#/components/parameters/InsightsEpisodeId'
      responses:
        '200':
          description: Episode monthly analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/range:
    post:
      operationId: getPodcastRangeAnalytics
      tags:
      - Analytics
      summary: Get Analytics in Range for Podcast
      description: >-
        Analytics for a podcast over an arbitrary date range, broken down by the
        requested dimension types.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RangeRequest'
      responses:
        '200':
          description: Podcast range analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/range/{episodeId}:
    post:
      operationId: getEpisodeRangeAnalytics
      tags:
      - Analytics
      summary: Get Analytics in Range for Episode
      description: >-
        Analytics for a specific episode over an arbitrary date range, broken
        down by the requested dimension types.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      - $ref: '#/components/parameters/InsightsEpisodeId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RangeRequest'
      responses:
        '200':
          description: Episode range analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/compare:
    post:
      operationId: compareEpisodeAnalytics
      tags:
      - Analytics
      summary: Get Analytics Comparison between Episodes
      description: Compare analytics across a set of episodes.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                  title:
                    type: string
                  published_date:
                    type: string
                    format: date-time
      responses:
        '200':
          description: Episode comparison analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /insights/{showId}/web-player/{episodeId}:
    post:
      operationId: getWebPlayerAnalytics
      tags:
      - Analytics
      summary: Get Web Player Analytics for Podcast
      description: Web-player analytics for a podcast, scoped to an episode context.
      parameters:
      - $ref: '#/components/parameters/InsightsShowId'
      - $ref: '#/components/parameters/InsightsEpisodeId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                dateRange:
                  type: object
                  properties:
                    gte:
                      type: string
                      format: date-time
                    lte:
                      type: string
                      format: date-time
                duration:
                  type: string
                timezone:
                  type: string
                  example: America/New_York
      responses:
        '200':
          description: Web-player analytics (modeled).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenericObject'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Bearer token obtained from POST /authenticate/token. Sent as
        Authorization: Bearer {token}.
  parameters:
    UserId:
      name: id
      in: path
      required: true
      description: The Captivate user ID (UUID).
      schema:
        type: string
    ShowId:
      name: id
      in: path
      required: true
      description: The show ID (UUID).
      schema:
        type: string
    EpisodeId:
      name: id
      in: path
      required: true
      description: The episode ID (UUID).
      schema:
        type: string
    MediaId:
      name: id
      in: path
      required: true
      description: The media ID (UUID).
      schema:
        type: string
    InsightsShowId:
      name: showId
      in: path
      required: true
      description: The show ID (UUID) for insights.
      schema:
        type: string
    InsightsEpisodeId:
      name: episodeId
      in: path
      required: true
      description: The episode ID (UUID) for insights.
      schema:
        type: string
    StartQuery:
      name: start
      in: query
      schema:
        type: string
        format: date-time
        example: '2022-09-01T00:00:00.000Z'
    EndQuery:
      name: end
      in: query
      schema:
        type: string
        format: date-time
        example: '2022-09-01T00:00:00.000Z'
  responses:
    Unauthorized:
      description: Missing or invalid Bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/GenericObject'
  schemas:
    AuthToken:
      type: object
      description: >-
        Modeled authentication response. Captivate returns a Bearer token used
        for all subsequent requests; the exact envelope is not published.
      properties:
        success:
          type: boolean
        user:
          type: object
        token:
          type: string
    EpisodeInput:
      type: object
      description: Fields for creating or updating an episode (multipart form-data).
      required:
      - shows_id
      - title
      properties:
        shows_id:
          type: string
          description: The show ID (UUID) the episode belongs to.
        title:
          type: string
          example: My Demo Episode
        itunes_title:
          type: string
        media_id:
          type: string
          description: The uploaded media ID (UUID) to attach as the episode audio.
        date:
          type: string
          description: Publish date, format YYYY-MM-DD HH:mm:ss.
        status:
          type: string
          description: e.g. Draft, Published.
          example: Draft
        shownotes:
          type: string
        summary:
          type: string
        itunes_subtitle:
          type: string
        author:
          type: string
        episode_art:
          type: string
          description: URL to episode artwork.
        explicit:
          type: string
        episode_type:
          type: string
          description: e.g. full, trailer, bonus.
        episode_season:
          type: string
        episode_number:
          type: string
        donation_link:
          type: string
        donation_text:
          type: string
        link:
          type: string
        itunes_block:
          type: string
          description: 'true or false: whether to block the episode from Apple Podcasts.'
    RangeRequest:
      type: object
      description: Request body for range analytics.
      properties:
        start:
          type: string
          format: date-time
        end:
          type: string
          format: date-time
        interval:
          type: string
          example: 1d
        timezone:
          type: string
          example: America/New_York
        countryCode:
          type:
          - string
          - 'null'
        types:
          type: array
          items:
            type: string
            enum:
            - byLocation
            - byUserAgentBrowser
            - byUserAgentOs
            - byUserAgentDevice
            - byEpisode
            - byPrivateSubscriber
    GenericObject:
      type: object
      description: >-
        Modeled response object. Captivate's public documentation describes
        requests and fields but does not publish full JSON response schemas, so
        response bodies are represented generically.
      additionalProperties: true
security:
- bearerAuth: []