{
  "openapi": "3.1.0",
  "info": {
    "title": "Subalytics API",
    "version": "1.0.0",
    "description": "Read-only JSON API over HTTPS for creators and publications on Substack, Medium and Bluesky, podcasts with episodes and full transcripts, and company mentions in Substack posts, Bluesky posts and podcasts. Human-readable reference: https://subalytics.com/docs/. All endpoints use GET; paths end with a trailing slash. Any query parameter not listed for an endpoint is rejected with 400.",
    "contact": {
      "name": "Subalytics",
      "email": "team@subalytics.com",
      "url": "https://subalytics.com/request-access/"
    }
  },
  "servers": [
    {
      "url": "https://subalytics.com"
    }
  ],
  "externalDocs": {
    "description": "API documentation",
    "url": "https://subalytics.com/docs/"
  },
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Creators",
      "description": "Substack, Medium and Bluesky creators, their history and posts"
    },
    {
      "name": "Podcasts",
      "description": "Podcasts, episodes and transcripts. Only the podcasts your key includes are returned; any other sub_id or episode_sub_id returns 403."
    },
    {
      "name": "Entity mentions",
      "description": "Company mentions in Substack posts, Bluesky posts and podcasts. A separate product with its own access: keys for other endpoints don't include the entity-* endpoints, and the reverse."
    }
  ],
  "paths": {
    "/api/v1/influencers/": {
      "get": {
        "operationId": "listInfluencers",
        "tags": [
          "Creators"
        ],
        "summary": "Influencers",
        "description": "The latest weekly snapshot of each creator: platform, subscriber counts, publication details and more. Cursor pagination.",
        "parameters": [
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Subalytics ID of one creator",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "social",
            "in": "query",
            "required": false,
            "description": "Platform",
            "schema": {
              "type": "string",
              "enum": [
                "substack",
                "medium",
                "bluesky"
              ]
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Year of the snapshot",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "free_subscribers",
            "in": "query",
            "required": false,
            "description": "Minimum number of free subscribers",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "paid_subscribers",
            "in": "query",
            "required": false,
            "description": "Minimum number of paid subscribers",
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CreatorRecord"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/creators-historical/": {
      "get": {
        "operationId": "listCreatorsHistorical",
        "tags": [
          "Creators"
        ],
        "summary": "Creators (historical)",
        "description": "Weekly creator records by Subalytics ID, platform, week/year or date range. Offset pagination.",
        "parameters": [
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Subalytics ID of one creator",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "social",
            "in": "query",
            "required": false,
            "description": "Platform",
            "schema": {
              "type": "string",
              "enum": [
                "substack",
                "medium",
                "bluesky"
              ]
            }
          },
          {
            "name": "week_number",
            "in": "query",
            "required": false,
            "description": "ISO week number (1–53)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 53
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Year, e.g. 2025",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Start date of the week, from (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Start date of the week, to (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/offset"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/OffsetPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CreatorRecord"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/subscribers-historical/": {
      "get": {
        "operationId": "listSubscribersHistorical",
        "tags": [
          "Creators"
        ],
        "summary": "Subscribers (historical)",
        "description": "Weekly subscriber statistics by Subalytics ID, platform and date. Offset pagination.",
        "parameters": [
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Subalytics ID of one creator",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "social",
            "in": "query",
            "required": false,
            "description": "Platform",
            "schema": {
              "type": "string",
              "enum": [
                "substack",
                "medium",
                "bluesky"
              ]
            }
          },
          {
            "name": "week_number",
            "in": "query",
            "required": false,
            "description": "ISO week number (1–53)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 53
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Year, e.g. 2025",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "free_subscribers",
            "in": "query",
            "required": false,
            "description": "Minimum number of free subscribers",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "paid_subscribers",
            "in": "query",
            "required": false,
            "description": "Minimum number of paid subscribers",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Start date of the week, from (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Start date of the week, to (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/offset"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/OffsetPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CreatorRecord"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/substack-posts/": {
      "get": {
        "operationId": "listSubstackPosts",
        "tags": [
          "Creators"
        ],
        "summary": "Substack posts",
        "description": "Search posts by creator, audience and engagement. By default returns post summaries; full=true returns the complete post record. Cursor pagination.",
        "parameters": [
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Subalytics ID of one creator",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "audience",
            "in": "query",
            "required": false,
            "description": "Audience, e.g. only_paid or everyone",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wordcount",
            "in": "query",
            "required": false,
            "description": "Minimum word count",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "comment_count",
            "in": "query",
            "required": false,
            "description": "Minimum number of comments",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "reaction_count",
            "in": "query",
            "required": false,
            "description": "Minimum number of reactions",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "full",
            "in": "query",
            "required": false,
            "description": "true = return the complete post record",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/SubstackPost"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/podcasts/": {
      "get": {
        "operationId": "listPodcasts",
        "tags": [
          "Podcasts"
        ],
        "summary": "Podcasts",
        "description": "The podcasts your key includes, newest-added first. Cursor pagination.",
        "parameters": [
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "One podcast",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "description": "Exact match, e.g. en",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Podcasts whose categories include this value, e.g. Business",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latest_episode_from",
            "in": "query",
            "required": false,
            "description": "Newest episode published on or after (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "latest_episode_to",
            "in": "query",
            "required": false,
            "description": "Newest episode published on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Podcast"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/podcast-episodes/": {
      "get": {
        "operationId": "listPodcastEpisodes",
        "tags": [
          "Podcasts"
        ],
        "summary": "Podcast episodes",
        "description": "Episodes with a transcript, newest-added first. Only episodes published since Subalytics started tracking the podcast. Cursor pagination.",
        "parameters": [
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Episodes of one podcast",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "episode_sub_id",
            "in": "query",
            "required": false,
            "description": "One episode",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "published_from",
            "in": "query",
            "required": false,
            "description": "Published by the podcast on or after (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "published_to",
            "in": "query",
            "required": false,
            "description": "Published by the podcast on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "transcribed_from",
            "in": "query",
            "required": false,
            "description": "Became available in the API on or after (use for sync) (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "transcribed_to",
            "in": "query",
            "required": false,
            "description": "Became available in the API on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PodcastEpisode"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/podcast-transcripts/": {
      "get": {
        "operationId": "listPodcastTranscripts",
        "tags": [
          "Podcasts"
        ],
        "summary": "Podcast transcripts",
        "description": "Transcript summaries by default; full=true adds speakers and segments (then limit defaults to 10, max 10). Newest-added first. Cursor pagination.",
        "parameters": [
          {
            "name": "episode_sub_id",
            "in": "query",
            "required": false,
            "description": "The transcript of one episode",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Transcripts of one podcast",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "full",
            "in": "query",
            "required": false,
            "description": "true = include speakers and segments; anything else or omitted = summary only",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "updated_from",
            "in": "query",
            "required": false,
            "description": "Last changed on or after (use for sync) (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_to",
            "in": "query",
            "required": false,
            "description": "Last changed on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (default 25, max 100). With full=true: default 10, max 10",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PodcastTranscript"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/entity-companies/": {
      "get": {
        "operationId": "listEntityCompanies",
        "tags": [
          "Entity mentions"
        ],
        "summary": "Companies",
        "description": "Every company monitored for mentions; the reference for official company data. Newly monitored companies first. Cursor pagination.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": false,
            "description": "One company, exact match, e.g. META",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cik",
            "in": "query",
            "required": false,
            "description": "One company by SEC CIK",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Case-insensitive search on symbol and company name",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sector",
            "in": "query",
            "required": false,
            "description": "Exact match, e.g. Technology",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "exchange",
            "in": "query",
            "required": false,
            "description": "Exact match, e.g. NASDAQ",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/EntityCompany"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/entity-mentions/": {
      "get": {
        "operationId": "listEntityMentions",
        "tags": [
          "Entity mentions"
        ],
        "summary": "Mentions",
        "description": "One row per company mention in one piece of content, across Substack, Bluesky and podcasts. Newest-added first. Cursor pagination.",
        "parameters": [
          {
            "name": "mention_id",
            "in": "query",
            "required": false,
            "description": "One mention",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "symbol",
            "in": "query",
            "required": false,
            "description": "Mentions of one company",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Omit for all sources",
            "schema": {
              "type": "string",
              "enum": [
                "substack",
                "bluesky",
                "podcast"
              ]
            }
          },
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Mentions by one creator or in one podcast",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "content_id",
            "in": "query",
            "required": false,
            "description": "Mentions in one post or episode (post_id, post_uri or episode_sub_id)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "match_type",
            "in": "query",
            "required": false,
            "description": "What was matched",
            "schema": {
              "type": "string",
              "enum": [
                "cashtag",
                "company_name",
                "alias",
                "product",
                "ticker"
              ]
            }
          },
          {
            "name": "min_confidence",
            "in": "query",
            "required": false,
            "description": "Minimum match confidence, 0.5–1.0 (default 0.7)",
            "schema": {
              "type": "number",
              "minimum": 0.5,
              "maximum": 1.0,
              "default": 0.7
            }
          },
          {
            "name": "published_from",
            "in": "query",
            "required": false,
            "description": "Content published on or after (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "published_to",
            "in": "query",
            "required": false,
            "description": "Content published on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_from",
            "in": "query",
            "required": false,
            "description": "Mention last changed on or after (use for sync) (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_to",
            "in": "query",
            "required": false,
            "description": "Mention last changed on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/EntityMention"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/entity-mention-stats/": {
      "get": {
        "operationId": "listEntityMentionStats",
        "tags": [
          "Entity mentions"
        ],
        "summary": "Mention stats",
        "description": "Mention counts for one company over time, one row per day or week, oldest first; periods with no mentions are returned with zero counts. Counts include only mentions with confidence 0.7 or above. No cursor: limit caps the number of periods and next_cursor is always null.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "description": "The company",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Omit for all sources combined",
            "schema": {
              "type": "string",
              "enum": [
                "substack",
                "bluesky",
                "podcast"
              ]
            }
          },
          {
            "name": "interval",
            "in": "query",
            "required": false,
            "description": "day (default) or week (ISO weeks, starting Monday)",
            "schema": {
              "type": "string",
              "enum": [
                "day",
                "week"
              ],
              "default": "day"
            }
          },
          {
            "name": "period_from",
            "in": "query",
            "required": false,
            "description": "First period returned. Default: 30 days before today (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "period_to",
            "in": "query",
            "required": false,
            "description": "Last period returned. Default: yesterday (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Periods returned (default 100, max 100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/EntityMentionStat"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/entity-trending/": {
      "get": {
        "operationId": "listEntityTrending",
        "tags": [
          "Entity mentions"
        ],
        "summary": "Trending companies",
        "description": "Companies ranked by mention volume, or by change vs. the equal-length window before. Counts include only mentions with confidence 0.7 or above. No cursor: limit caps the number of companies and next_cursor is always null.",
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Omit for all sources combined",
            "schema": {
              "type": "string",
              "enum": [
                "substack",
                "bluesky",
                "podcast"
              ]
            }
          },
          {
            "name": "period_from",
            "in": "query",
            "required": false,
            "description": "Start of the window to rank (whole days). Default: 7 days before today (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "period_to",
            "in": "query",
            "required": false,
            "description": "End of the window to rank. Default: yesterday (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "volume (default) or change (largest change_pct)",
            "schema": {
              "type": "string",
              "enum": [
                "volume",
                "change"
              ],
              "default": "volume"
            }
          },
          {
            "name": "min_mentions",
            "in": "query",
            "required": false,
            "description": "Only rank companies with at least this many mentions in the window (default 10)",
            "schema": {
              "type": "integer",
              "default": 10
            }
          },
          {
            "name": "sector",
            "in": "query",
            "required": false,
            "description": "Rank only companies in one sector (the sector value from entity-companies)",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/EntityTrendingCompany"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/entity-substack-posts/": {
      "get": {
        "operationId": "listEntitySubstackPosts",
        "tags": [
          "Entity mentions"
        ],
        "summary": "Substack posts with mentions",
        "description": "Substack posts that mention at least one monitored company, each with its entities[]. Post bodies are not returned. Newest-added first. Cursor pagination.",
        "parameters": [
          {
            "name": "post_id",
            "in": "query",
            "required": false,
            "description": "One post",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Posts by one creator",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "symbol",
            "in": "query",
            "required": false,
            "description": "Posts mentioning one company",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_confidence",
            "in": "query",
            "required": false,
            "description": "Minimum match confidence, 0.5–1.0 (default 0.7)",
            "schema": {
              "type": "number",
              "minimum": 0.5,
              "maximum": 1.0,
              "default": 0.7
            }
          },
          {
            "name": "published_from",
            "in": "query",
            "required": false,
            "description": "Published on or after (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "published_to",
            "in": "query",
            "required": false,
            "description": "Published on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_from",
            "in": "query",
            "required": false,
            "description": "Mentions last changed on or after (use for sync) (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_to",
            "in": "query",
            "required": false,
            "description": "Mentions last changed on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/EntitySubstackPost"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/entity-bluesky-posts/": {
      "get": {
        "operationId": "listEntityBlueskyPosts",
        "tags": [
          "Entity mentions"
        ],
        "summary": "Bluesky posts with mentions",
        "description": "Top-level Bluesky posts from tracked accounts that mention at least one monitored company, each with its entities[] and full text. Newest-added first. Cursor pagination.",
        "parameters": [
          {
            "name": "post_uri",
            "in": "query",
            "required": false,
            "description": "One post",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Posts by one creator",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "did",
            "in": "query",
            "required": false,
            "description": "Posts by one Bluesky account (DID)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "symbol",
            "in": "query",
            "required": false,
            "description": "Posts mentioning one company",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_confidence",
            "in": "query",
            "required": false,
            "description": "Minimum match confidence, 0.5–1.0 (default 0.7)",
            "schema": {
              "type": "number",
              "minimum": 0.5,
              "maximum": 1.0,
              "default": 0.7
            }
          },
          {
            "name": "published_from",
            "in": "query",
            "required": false,
            "description": "Published on or after (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "published_to",
            "in": "query",
            "required": false,
            "description": "Published on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_from",
            "in": "query",
            "required": false,
            "description": "Mentions last changed on or after (use for sync) (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_to",
            "in": "query",
            "required": false,
            "description": "Mentions last changed on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/EntityBlueskyPost"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    },
    "/api/v1/entity-podcast-episodes/": {
      "get": {
        "operationId": "listEntityPodcastEpisodes",
        "tags": [
          "Entity mentions"
        ],
        "summary": "Podcast episodes with mentions",
        "description": "Podcast episodes that mention at least one monitored company, each with its entities[] (transcript passage, timestamps and speaker). The full transcript is not part of this product. Newest-added first. Cursor pagination.",
        "parameters": [
          {
            "name": "episode_sub_id",
            "in": "query",
            "required": false,
            "description": "One episode",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sub_id",
            "in": "query",
            "required": false,
            "description": "Episodes of one podcast",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "symbol",
            "in": "query",
            "required": false,
            "description": "Episodes mentioning one company",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_confidence",
            "in": "query",
            "required": false,
            "description": "Minimum match confidence, 0.5–1.0 (default 0.7)",
            "schema": {
              "type": "number",
              "minimum": 0.5,
              "maximum": 1.0,
              "default": 0.7
            }
          },
          {
            "name": "published_from",
            "in": "query",
            "required": false,
            "description": "Published on or after (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "published_to",
            "in": "query",
            "required": false,
            "description": "Published on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_from",
            "in": "query",
            "required": false,
            "description": "Mentions last changed on or after (use for sync) (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "name": "updated_to",
            "in": "query",
            "required": false,
            "description": "Mentions last changed on or before (UTC; a date-only *_to covers the whole day; both bounds inclusive)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2})?$",
              "description": "UTC, YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS"
            }
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of results (an empty results list is a success)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CursorPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/EntityPodcastEpisode"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-key",
        "description": "Each key is enabled for specific endpoints; get one at https://subalytics.com/request-access/"
      }
    },
    "parameters": {
      "limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Results per page (default 25, max 100)",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 25
        }
      },
      "cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "next_cursor from the previous page. Opaque: don't parse or build it.",
        "schema": {
          "type": "string"
        }
      },
      "offset": {
        "name": "offset",
        "in": "query",
        "required": false,
        "description": "Records to skip (default 0)",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        }
      }
    },
    "responses": {
      "400": {
        "description": "Unknown query parameter, invalid date or date range, invalid limit, invalid min_confidence, or invalid cursor. msg says which.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "401": {
        "description": "Missing API key, or the key is not enabled for this endpoint.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "403": {
        "description": "The request names a podcast (or one of its episodes) that your key does not include.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "500": {
        "description": "Something went wrong on our side. Retry later.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "success": {
            "const": false
          },
          "error_code": {
            "type": "integer"
          },
          "msg": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "error_code",
          "msg"
        ],
        "additionalProperties": false
      },
      "CursorPage": {
        "type": "object",
        "properties": {
          "success": {
            "const": true
          },
          "results": {
            "type": "array"
          },
          "returned_results": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass back as cursor for the next page; null on the last page"
          }
        },
        "required": [
          "success",
          "results",
          "returned_results",
          "limit",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "OffsetPage": {
        "type": "object",
        "properties": {
          "success": {
            "const": true
          },
          "results": {
            "type": "array"
          },
          "returned_results": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        },
        "required": [
          "success",
          "results",
          "returned_results",
          "limit",
          "offset"
        ],
        "additionalProperties": false
      },
      "CreatorRecord": {
        "type": "object",
        "additionalProperties": true,
        "description": "Creator record. Fields are not individually documented yet."
      },
      "SubstackPost": {
        "type": "object",
        "additionalProperties": true,
        "description": "Post summary (title, URL, date, description, truncated body, engagement counts), or the complete post record with full=true."
      },
      "Podcast": {
        "type": "object",
        "properties": {
          "sub_id": {
            "type": "string",
            "description": "Public podcast ID (10 hex characters)"
          },
          "podcast_name": {
            "type": "string",
            "description": "Podcast name"
          },
          "feed_title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Title as published in the podcast feed"
          },
          "author": {
            "type": [
              "string",
              "null"
            ],
            "description": "Author as published in the feed"
          },
          "owner_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Owner as published in the feed"
          },
          "owner_email": {
            "type": [
              "string",
              "null"
            ],
            "description": "Owner email as published in the feed"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Podcast description"
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Categories"
          },
          "language": {
            "type": [
              "string",
              "null"
            ],
            "description": "Language declared by the feed, e.g. en"
          },
          "explicit": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Explicit flag as declared in the feed; null when the feed doesn't say"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Podcast artwork"
          },
          "website_link": {
            "type": "string",
            "description": "Podcast website; only present when the feed has one"
          },
          "latest_published_episode_utc": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "Publish date of the newest episode"
          }
        },
        "required": [
          "sub_id",
          "podcast_name",
          "feed_title",
          "author",
          "owner_name",
          "owner_email",
          "description",
          "categories",
          "language",
          "explicit",
          "image_url",
          "latest_published_episode_utc"
        ],
        "additionalProperties": false
      },
      "PodcastEpisode": {
        "type": "object",
        "properties": {
          "episode_sub_id": {
            "type": "string",
            "description": "Public episode ID (16 hex characters)"
          },
          "sub_id": {
            "type": "string",
            "description": "The podcast it belongs to"
          },
          "podcast_name": {
            "type": "string",
            "description": "Podcast name"
          },
          "guid": {
            "type": "string",
            "description": "The episode's ID in its podcast feed (unique within that feed only)"
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Episode title"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "As published in the feed, often HTML"
          },
          "link": {
            "type": [
              "string",
              "null"
            ],
            "description": "Episode web page"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Episode artwork, if the feed has one"
          },
          "audio_url": {
            "type": "string",
            "description": "Original audio file, hosted by the podcast"
          },
          "duration_seconds": {
            "type": [
              "integer",
              "null"
            ],
            "description": "From the feed; null when the feed doesn't state it"
          },
          "explicit": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Explicit flag as declared in the feed; null when the feed doesn't say"
          },
          "published_utc": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When the podcast published the episode"
          },
          "transcribed_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When the transcript became available"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When Subalytics first found the episode"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When the episode details were last refreshed"
          }
        },
        "required": [
          "episode_sub_id",
          "sub_id",
          "podcast_name",
          "guid",
          "title",
          "description",
          "link",
          "image_url",
          "audio_url",
          "duration_seconds",
          "explicit",
          "published_utc",
          "transcribed_at",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "Speaker": {
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "description": "host, co-host, guest, …"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "company": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "role",
          "title",
          "company"
        ],
        "additionalProperties": false
      },
      "Segment": {
        "type": "object",
        "properties": {
          "start": {
            "type": "number",
            "description": "Seconds from the start of the audio"
          },
          "end": {
            "type": "number"
          },
          "text": {
            "type": "string"
          },
          "speaker": {
            "type": "string",
            "description": "Key into speakers; may be missing where speakers couldn't be separated"
          }
        },
        "required": [
          "start",
          "end",
          "text"
        ],
        "additionalProperties": false
      },
      "PodcastTranscript": {
        "type": "object",
        "properties": {
          "episode_sub_id": {
            "type": "string",
            "description": "The episode this transcript belongs to"
          },
          "podcast": {
            "type": "object",
            "properties": {
              "sub_id": {
                "type": "string"
              },
              "podcast_name": {
                "type": "string"
              }
            },
            "required": [
              "sub_id",
              "podcast_name"
            ],
            "additionalProperties": false
          },
          "episode": {
            "type": "object",
            "properties": {
              "episode_sub_id": {
                "type": "string"
              },
              "episode_title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "published_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
                "description": "ISO 8601 UTC, e.g. 2026-09-25T05:00:00Z"
              },
              "audio_url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "link": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "image_url": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "episode_sub_id",
              "episode_title",
              "published_at",
              "audio_url",
              "link",
              "image_url"
            ],
            "additionalProperties": false,
            "description": "For convenience; the episodes endpoint is the source of truth"
          },
          "language": {
            "type": [
              "string",
              "null"
            ],
            "description": "Language detected from the audio, e.g. en"
          },
          "duration_seconds": {
            "type": [
              "number",
              "null"
            ],
            "description": "Measured audio length"
          },
          "speakers_identified": {
            "type": "boolean",
            "description": "false = speaker names haven't been identified (yet)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When the transcript was first produced"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "Last change (re-transcription or speakers identified)"
          },
          "speakers": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/Speaker"
            },
            "description": "full=true only. Speaker label → speaker"
          },
          "segments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Segment"
            },
            "description": "full=true only. In order"
          }
        },
        "required": [
          "episode_sub_id",
          "podcast",
          "episode",
          "language",
          "duration_seconds",
          "speakers_identified",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "EntityCompany": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string",
            "description": "Ticker"
          },
          "company_name": {
            "type": "string",
            "description": "Official company name"
          },
          "cik": {
            "type": [
              "string",
              "null"
            ],
            "description": "SEC CIK"
          },
          "exchange": {
            "type": [
              "string",
              "null"
            ],
            "description": "Listing exchange"
          },
          "sector": {
            "type": [
              "string",
              "null"
            ]
          },
          "industry": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "symbol",
          "company_name",
          "cik",
          "exchange",
          "sector",
          "industry"
        ],
        "additionalProperties": false
      },
      "EntityMention": {
        "type": "object",
        "properties": {
          "mention_id": {
            "type": "string",
            "description": "Public mention ID"
          },
          "symbol": {
            "type": "string"
          },
          "company_name": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "substack",
              "bluesky",
              "podcast"
            ]
          },
          "content_id": {
            "type": "string",
            "description": "ID of the post or episode on its content endpoint (post_id, post_uri or episode_sub_id)"
          },
          "sub_id": {
            "type": "string",
            "description": "The creator or podcast"
          },
          "content_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Link to the original post or episode page"
          },
          "published_utc": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When the content was published"
          },
          "match_type": {
            "type": "string",
            "enum": [
              "cashtag",
              "company_name",
              "alias",
              "product",
              "ticker"
            ]
          },
          "matched_text": {
            "type": "string",
            "description": "The text as it appeared in the content"
          },
          "confidence": {
            "type": "number",
            "description": "0–1"
          },
          "snippet": {
            "type": "string",
            "description": "The sentence or passage around the mention"
          },
          "field": {
            "type": [
              "string",
              "null"
            ],
            "description": "Posts only: where the match was found"
          },
          "start": {
            "type": [
              "number",
              "null"
            ],
            "description": "Podcasts only: seconds from the start of the audio"
          },
          "end": {
            "type": [
              "number",
              "null"
            ],
            "description": "Podcasts only"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When the mention was first found"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When the mention last changed"
          }
        },
        "required": [
          "mention_id",
          "symbol",
          "company_name",
          "source",
          "content_id",
          "sub_id",
          "content_url",
          "published_utc",
          "match_type",
          "matched_text",
          "confidence",
          "snippet",
          "field",
          "start",
          "end",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "EntityMentionStat": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string"
          },
          "company_name": {
            "type": "string"
          },
          "period_start": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "Start of the day or week"
          },
          "interval": {
            "type": "string",
            "enum": [
              "day",
              "week"
            ]
          },
          "mention_count": {
            "type": "integer"
          },
          "content_count": {
            "type": "integer",
            "description": "Distinct posts or episodes with at least one mention"
          },
          "creator_count": {
            "type": "integer",
            "description": "Distinct creators and podcasts (sub_id)"
          },
          "by_source": {
            "type": "object",
            "properties": {
              "substack": {
                "type": "integer"
              },
              "bluesky": {
                "type": "integer"
              },
              "podcast": {
                "type": "integer"
              }
            },
            "required": [
              "substack",
              "bluesky",
              "podcast"
            ],
            "additionalProperties": false,
            "description": "Mention counts per source; only when source is omitted"
          }
        },
        "required": [
          "symbol",
          "company_name",
          "period_start",
          "interval",
          "mention_count",
          "content_count",
          "creator_count"
        ],
        "additionalProperties": false
      },
      "EntityTrendingCompany": {
        "type": "object",
        "properties": {
          "rank": {
            "type": "integer",
            "description": "1 = top"
          },
          "symbol": {
            "type": "string"
          },
          "company_name": {
            "type": "string"
          },
          "mention_count": {
            "type": "integer",
            "description": "Mentions in the window"
          },
          "previous_mention_count": {
            "type": "integer",
            "description": "Mentions in the equal-length window before"
          },
          "change_pct": {
            "type": [
              "number",
              "null"
            ],
            "description": "Percentage change vs. the previous window; null when previous_mention_count is 0"
          },
          "creator_count": {
            "type": "integer"
          }
        },
        "required": [
          "rank",
          "symbol",
          "company_name",
          "mention_count",
          "previous_mention_count",
          "change_pct",
          "creator_count"
        ],
        "additionalProperties": false
      },
      "EntityPostMention": {
        "type": "object",
        "properties": {
          "mention_id": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "company_name": {
            "type": "string"
          },
          "match_type": {
            "type": "string",
            "enum": [
              "cashtag",
              "company_name",
              "alias",
              "product",
              "ticker"
            ]
          },
          "matched_text": {
            "type": "string"
          },
          "confidence": {
            "type": "number"
          },
          "snippet": {
            "type": "string"
          },
          "field": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "mention_id",
          "symbol",
          "company_name",
          "match_type",
          "matched_text",
          "confidence",
          "snippet",
          "field"
        ],
        "additionalProperties": false
      },
      "EntityEpisodeMention": {
        "type": "object",
        "properties": {
          "mention_id": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "company_name": {
            "type": "string"
          },
          "match_type": {
            "type": "string",
            "enum": [
              "cashtag",
              "company_name",
              "alias",
              "product",
              "ticker"
            ]
          },
          "matched_text": {
            "type": "string"
          },
          "confidence": {
            "type": "number"
          },
          "snippet": {
            "type": "string"
          },
          "start": {
            "type": "number"
          },
          "end": {
            "type": "number"
          },
          "speaker": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "role": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "label",
              "name",
              "role"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "mention_id",
          "symbol",
          "company_name",
          "match_type",
          "matched_text",
          "confidence",
          "snippet",
          "start",
          "end",
          "speaker"
        ],
        "additionalProperties": false
      },
      "EntitySubstackPost": {
        "type": "object",
        "properties": {
          "post_id": {
            "type": "string",
            "description": "Public post ID; content_id in entity-mentions"
          },
          "sub_id": {
            "type": "string"
          },
          "author_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "subtitle": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "canonical_url": {
            "type": "string",
            "description": "Link to the post"
          },
          "published_utc": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "ISO 8601 UTC, e.g. 2026-09-25T05:00:00Z"
          },
          "entities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EntityPostMention"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When the post first appeared in this product"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "When its mentions last changed"
          }
        },
        "required": [
          "post_id",
          "sub_id",
          "author_name",
          "title",
          "subtitle",
          "description",
          "canonical_url",
          "published_utc",
          "entities",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "EntityBlueskyPost": {
        "type": "object",
        "properties": {
          "post_uri": {
            "type": "string",
            "description": "Public post ID (AT Protocol URI); content_id in entity-mentions"
          },
          "sub_id": {
            "type": "string"
          },
          "did": {
            "type": "string",
            "description": "The Bluesky account"
          },
          "url": {
            "type": "string",
            "description": "Link to the post on bsky.app"
          },
          "text": {
            "type": "string",
            "description": "Full post text"
          },
          "published_utc": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "ISO 8601 UTC, e.g. 2026-09-25T05:00:00Z"
          },
          "entities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EntityPostMention"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "ISO 8601 UTC, e.g. 2026-09-25T05:00:00Z"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "ISO 8601 UTC, e.g. 2026-09-25T05:00:00Z"
          }
        },
        "required": [
          "post_uri",
          "sub_id",
          "did",
          "url",
          "text",
          "published_utc",
          "entities",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "EntityPodcastEpisode": {
        "type": "object",
        "properties": {
          "episode_sub_id": {
            "type": "string",
            "description": "Public episode ID, same as on podcast-episodes"
          },
          "sub_id": {
            "type": "string"
          },
          "podcast_name": {
            "type": "string"
          },
          "episode_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "link": {
            "type": [
              "string",
              "null"
            ]
          },
          "published_utc": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "ISO 8601 UTC, e.g. 2026-09-25T05:00:00Z"
          },
          "entities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EntityEpisodeMention"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "ISO 8601 UTC, e.g. 2026-09-25T05:00:00Z"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
            "description": "ISO 8601 UTC, e.g. 2026-09-25T05:00:00Z"
          }
        },
        "required": [
          "episode_sub_id",
          "sub_id",
          "podcast_name",
          "episode_title",
          "link",
          "published_utc",
          "entities",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      }
    }
  }
}
