# Subalytics API documentation (full text) > Every page of https://subalytics.com/docs/ as Markdown. Machine-readable spec: https://subalytics.com/openapi.json --- # Subalytics API Documentation Source: https://subalytics.com/docs/ > Creator, podcast transcript and company mention data through one read-only JSON API ## Overview The Subalytics API is a read-only JSON API over HTTPS. It covers creators and publications across Substack, Medium and Bluesky, their subscriber history and posts, podcasts with their episodes and full transcripts, and [company mentions](https://subalytics.com/docs/entity-overview/) found in Substack posts, Bluesky posts and podcasts. | Endpoint | Returns | |---|---| | `/api/v1/influencers/` | [Influencers](https://subalytics.com/docs/influencers/) | | `/api/v1/creators-historical/` | [Creators (historical)](https://subalytics.com/docs/creators-historical/) | | `/api/v1/subscribers-historical/` | [Subscribers (historical)](https://subalytics.com/docs/subscribers-historical/) | | `/api/v1/substack-posts/` | [Substack posts](https://subalytics.com/docs/substack-posts/) | | `/api/v1/podcasts/` | [Podcasts](https://subalytics.com/docs/podcasts/) | | `/api/v1/podcast-episodes/` | [Podcast episodes](https://subalytics.com/docs/podcast-episodes/) | | `/api/v1/podcast-transcripts/` | [Podcast transcripts](https://subalytics.com/docs/podcast-transcripts/) | | `/api/v1/entity-companies/` | [Companies](https://subalytics.com/docs/entity-companies/) | | `/api/v1/entity-mentions/` | [Mentions](https://subalytics.com/docs/entity-mentions/) | | `/api/v1/entity-mention-stats/` | [Mention stats](https://subalytics.com/docs/entity-mention-stats/) | | `/api/v1/entity-trending/` | [Trending companies](https://subalytics.com/docs/entity-trending/) | | `/api/v1/entity-substack-posts/` | [Substack posts with mentions](https://subalytics.com/docs/entity-substack-posts/) | | `/api/v1/entity-bluesky-posts/` | [Bluesky posts with mentions](https://subalytics.com/docs/entity-bluesky-posts/) | | `/api/v1/entity-podcast-episodes/` | [Podcast episodes with mentions](https://subalytics.com/docs/entity-podcast-episodes/) | All endpoints use `GET`, filter with query parameters, and return the same response envelope. Endpoint paths end with a trailing `/`. A machine-readable OpenAPI 3.1 description of these endpoints is at [`/openapi.json`](https://subalytics.com/openapi.json), for API clients, code generators and AI tools. ## Base URL & authentication ### Base URL ``` https://subalytics.com/api/v1/ ``` ### Authentication Send your API key in the `X-API-key` header with every request: ``` X-API-key: ``` Each API key is enabled for specific endpoints. A request without a valid key, or to an endpoint your key isn't enabled for, returns `401`. [Get access](https://subalytics.com/request-access/) to request a key or add endpoints to an existing one. Podcast endpoints return only the podcasts your key includes, with their episodes and transcripts. Requesting any other podcast by `sub_id`, or one of its episodes by `episode_sub_id`, returns `403`. Entity mentions is a separate product with its own access: keys for other endpoints don't include the `entity-*` endpoints, and the reverse. ### Example request ``` curl -H "X-API-key: " \ "https://subalytics.com/api/v1/podcasts/?limit=5" ``` ## Pagination Every endpoint accepts `limit`: default 25, maximum 100. Endpoints page in one of two ways, shown next to each endpoint. ### Cursor Responses include `next_cursor`. Pass it back as `cursor` to get the next page, and stop when `next_cursor` is `null`. Cursors are opaque strings: don't parse or build them. If the total is an exact multiple of `limit`, the last page comes back empty with `next_cursor: null`. Podcast and entity mentions endpoints return the **newest-added records first**. Records added while you are paging don't appear in that walk; your next sync picks them up. The exceptions are [mention stats](https://subalytics.com/docs/entity-mention-stats/) and [trending companies](https://subalytics.com/docs/entity-trending/), which have no cursor. ### Offset Pass `offset` (default 0) to skip that many records. Keep increasing it by `limit` until a page returns fewer than `limit` results. ## Date filters Dates are UTC, in the format `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS`. ### Creator endpoints [Creators](https://subalytics.com/docs/creators-historical/) and [subscribers](https://subalytics.com/docs/subscribers-historical/) history accept `from` / `to`, applied to the start date of each weekly record. ### Podcast and entity mentions endpoints These date filters come in `_from` / `_to` pairs, named after the field they filter: | Parameters | Endpoint | Field | |---|---|---| | `latest_episode_from / _to` | podcasts | latest_published_episode_utc | | `published_from / _to` | podcast-episodes | published_utc | | `transcribed_from / _to` | podcast-episodes | transcribed_at | | `updated_from / _to` | podcast-transcripts | updated_at | | `published_from / _to` | entity-mentions, entity-*-posts, entity-podcast-episodes | published_utc (when the content was published) | | `updated_from / _to` | entity-mentions, entity-*-posts, entity-podcast-episodes | updated_at (when the mention record last changed; use for sync) | | `period_from / _to` | entity-mention-stats, entity-trending | period_start | - Both bounds are inclusive. A date-only `*_from` starts at 00:00:00; a date-only `*_to` runs to the **end** of that day, so `published_from=2026-09-25&published_to=2026-09-25` returns everything published on 25 September. A `*_to` with a time includes that whole second, so a timestamp returned by the API can be used as either bound. - `*_to` must not be earlier than `*_from`. - These endpoints don't accept the plain `from` / `to` parameters. - Their responses return dates as ISO 8601 UTC with a `Z` suffix, e.g. `2026-09-25T05:00:00Z`, the same format the filters accept. ## Responses & errors ### Success Cursor-paginated endpoints: ``` { "success": true, "results": [ ... ], "returned_results": 25, "limit": 25, "next_cursor": "6a7d976dc8173839e225382f" } ``` Offset-paginated endpoints return `"offset"` in place of `"next_cursor"`. An empty `results` list is a success, not an error. ### Errors ``` { "success": false, "error_code": 400, "msg": "Unknown parameters: bad_param" } ``` | Code | Meaning | When | |---|---|---| | `400` | Bad request | Unknown query parameter, invalid date or date range, invalid limit, invalid min_confidence, or invalid cursor. The message says which. | | `401` | Unauthorized | Missing API key, or the key is not enabled for this endpoint. | | `403` | Forbidden | The request names a podcast (or one of its episodes) that your key does not include. | | `500` | Server error | Something went wrong on our side. Retry later. | Any query parameter not listed for an endpoint is rejected with `400`, so check spelling if you get `Unknown parameters: ...`. --- # Influencers API endpoint: creator snapshots Source: https://subalytics.com/docs/influencers/ > GET /api/v1/influencers/: the latest weekly snapshot of each Substack, Medium and Bluesky creator, with parameters, pagination and an example. `GET /api/v1/influencers/` (Cursor pagination). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ The latest weekly snapshot of each creator: platform, subscriber counts, publication details and more. | Parameter | Type | Description | |---|---|---| | `sub_id` | string | Subalytics ID of one creator | | `social` | string | Platform: substack, medium or bluesky | | `year` | int | Year of the snapshot | | `free_subscribers` | int | Minimum number of free subscribers | | `paid_subscribers` | int | Minimum number of paid subscribers | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Example ``` GET /api/v1/influencers/?social=bluesky&free_subscribers=5000 ``` --- # Creators historical API endpoint Source: https://subalytics.com/docs/creators-historical/ > GET /api/v1/creators-historical/: weekly creator records by Subalytics ID, platform, week, year or date range. Parameters and example. `GET /api/v1/creators-historical/` (Offset pagination). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Weekly creator records by Subalytics ID, platform, week/year or date range. | Parameter | Type | Description | |---|---|---| | `sub_id` | string | Subalytics ID of one creator | | `social` | string | Platform: substack, medium or bluesky | | `week_number` | int | ISO week number (1–53) | | `year` | int | Year, e.g. 2025 | | `from` | string | Start date of the week, from (YYYY-MM-DD) | | `to` | string | Start date of the week, to (YYYY-MM-DD) | | `limit` | int | Results per page (default 25, max 100) | | `offset` | int | Records to skip (default 0) | ## Example ``` GET /api/v1/creators-historical/?sub_id=714165582b&year=2025&limit=20 ``` --- # Subscribers historical API endpoint Source: https://subalytics.com/docs/subscribers-historical/ > GET /api/v1/subscribers-historical/: weekly subscriber statistics by Subalytics ID, platform and date. Parameters and example. `GET /api/v1/subscribers-historical/` (Offset pagination). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Weekly subscriber statistics by Subalytics ID, platform and date. | Parameter | Type | Description | |---|---|---| | `sub_id` | string | Subalytics ID of one creator | | `social` | string | Platform: substack, medium or bluesky | | `week_number` | int | ISO week number (1–53) | | `year` | int | Year, e.g. 2025 | | `free_subscribers` | int | Minimum number of free subscribers | | `paid_subscribers` | int | Minimum number of paid subscribers | | `from` | string | Start date of the week, from (YYYY-MM-DD) | | `to` | string | Start date of the week, to (YYYY-MM-DD) | | `limit` | int | Results per page (default 25, max 100) | | `offset` | int | Records to skip (default 0) | ## Example ``` GET /api/v1/subscribers-historical/?sub_id=f2ac9f1545&from=2025-03-01&to=2025-05-01&limit=50 ``` --- # Substack posts API endpoint Source: https://subalytics.com/docs/substack-posts/ > GET /api/v1/substack-posts/: search Substack posts by creator, audience and engagement. Parameters, response fields and example. `GET /api/v1/substack-posts/` (Cursor pagination). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Search posts by creator, audience and engagement. By default returns post summaries: title, URL, date, description, a truncated body and engagement counts. | Parameter | Type | Description | |---|---|---| | `sub_id` | string | Subalytics ID of one creator | | `audience` | string | Audience, e.g. only_paid or everyone | | `wordcount` | int | Minimum word count | | `comment_count` | int | Minimum number of comments | | `reaction_count` | int | Minimum number of reactions | | `full` | string | true = return the complete post record | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Example ``` GET /api/v1/substack-posts/?sub_id=803b198749&audience=only_paid ``` --- # Podcasts API endpoint Source: https://subalytics.com/docs/podcasts/ > GET /api/v1/podcasts/: the podcasts tracked by Subalytics, with stable IDs, parameters, response fields and an example. `GET /api/v1/podcasts/` (Cursor pagination · newest first). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ The podcasts tracked by Subalytics. Podcasts, episodes and transcripts are linked by stable public IDs: a podcast's `sub_id` (10 hex characters) and an episode's `episode_sub_id` (16 hex characters). They never change, so they are safe to store as foreign keys. To fetch one item, filter by its ID. ## Query parameters | Parameter | Type | Description | |---|---|---| | `sub_id` | string | One podcast | | `language` | string | Exact match, e.g. en | | `category` | string | Podcasts whose categories include this value, e.g. Business | | `latest_episode_from` | date | Newest episode published on or after (see Date filters) | | `latest_episode_to` | date | Newest episode published on or before | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Response fields | Field | Type | Description | |---|---|---| | `sub_id` | string | Public podcast ID | | `podcast_name` | string | Podcast name | | `feed_title` | string \| null | Title as published in the podcast feed (may differ from podcast_name) | | `author` | string \| null | Author as published in the feed | | `owner_name` | string \| null | Owner as published in the feed | | `owner_email` | string \| null | Owner email as published in the feed | | `description` | string \| null | Podcast description | | `categories` | string[] | Categories | | `language` | string \| null | Language declared by the feed, e.g. en | | `explicit` | boolean \| null | Explicit flag as declared in the feed; null when the feed doesn't say | | `image_url` | string \| null | Podcast artwork | | `website_link` | string | Podcast website; only present when the feed has one | | `latest_published_episode_utc` | date \| null | Publish date of the newest episode | ## Example ``` GET /api/v1/podcasts/?category=Business&limit=1 ``` ``` { "success": true, "results": [ { "sub_id": "a1b2c3d4e5", "podcast_name": "Example Business Show", "feed_title": "Example Business Show", "author": "Example Media", "owner_name": "Example Media", "owner_email": "podcast@example.com", "description": "Weekly conversations about business, markets and culture.", "categories": ["Business", "News"], "language": "en", "explicit": null, "image_url": "https://example.com/artwork.jpg", "website_link": "https://example.com/podcast", "latest_published_episode_utc": "2026-09-24T16:38:09Z" } ], "returned_results": 1, "limit": 1, "next_cursor": "6a7cdd39fdbbf69e21a9ffbe" } ``` --- # Podcast episodes API endpoint Source: https://subalytics.com/docs/podcast-episodes/ > GET /api/v1/podcast-episodes/: transcribed episodes of tracked podcasts, filterable by publish and transcription date. Parameters and example. `GET /api/v1/podcast-episodes/` (Cursor pagination · newest first). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Episodes published since Subalytics started tracking each podcast; this is not the podcast's full back catalogue. **Only episodes with a transcript are returned.** Every episode listed here has a transcript at `/api/v1/podcast-transcripts/?episode_sub_id=`. An episode that hasn't been transcribed yet returns an empty `results` list. New episodes are transcribed daily and usually appear within a few hours of 05:00 UTC. Some take longer, and a few may never appear (for example, if the audio is unavailable). ## Query parameters | Parameter | Type | Description | |---|---|---| | `sub_id` | string | Episodes of one podcast | | `episode_sub_id` | string | One episode | | `published_from` | date | Published by the podcast on or after | | `published_to` | date | Published by the podcast on or before | | `transcribed_from` | date | Became available in the API on or after (use for sync) | | `transcribed_to` | date | Became available in the API on or before | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Response fields | Field | Type | Description | |---|---|---| | `episode_sub_id` | string | Public episode ID | | `sub_id` | string | The podcast it belongs to | | `podcast_name` | string | Podcast name | | `guid` | string | The episode's ID in its podcast feed (unique within that feed only) | | `title` | string \| null | Episode title | | `description` | string \| null | As published in the feed, often HTML | | `link` | string \| null | Episode web page | | `image_url` | string \| null | Episode artwork, if the feed has one | | `audio_url` | string | Original audio file, hosted by the podcast | | `duration_seconds` | int \| null | From the feed; null when the feed doesn't state it | | `explicit` | boolean \| null | Explicit flag as declared in the feed; null when the feed doesn't say | | `published_utc` | date | When the podcast published the episode | | `transcribed_at` | date | When the transcript became available | | `created_at` | date | When Subalytics first found the episode | | `updated_at` | date | When the episode details were last refreshed | ## Example ``` GET /api/v1/podcast-episodes/?sub_id=a1b2c3d4e5&published_from=2026-09-20&limit=1 ``` ``` { "success": true, "results": [ { "episode_sub_id": "c41f7a09e2b85d13", "sub_id": "a1b2c3d4e5", "podcast_name": "Example Business Show", "guid": "088561f8-cd50-429d-963c-8f74c8193baa", "title": "Rate Cuts, Robotaxis and the Week in Markets", "description": "The panel breaks down this week's biggest business stories.", "link": "https://example.com/podcast/episodes/248", "image_url": null, "audio_url": "https://example.com/audio/episode-248.mp3", "duration_seconds": 6875, "explicit": null, "published_utc": "2026-09-24T16:38:09Z", "transcribed_at": "2026-09-25T06:12:47Z", "created_at": "2026-09-25T05:01:12Z", "updated_at": "2026-09-26T05:01:09Z" } ], "returned_results": 1, "limit": 1, "next_cursor": "6a7d976dc8173839e225382f" } ``` --- # Podcast transcripts API endpoint Source: https://subalytics.com/docs/podcast-transcripts/ > GET /api/v1/podcast-transcripts/: timestamped podcast transcripts with identified speakers. Parameters, response fields and a full example. `GET /api/v1/podcast-transcripts/` (Cursor pagination · newest first). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ By default returns transcript **summaries** without speakers or text, which are cheap to page through to find what's new. Add `full=true` to get the complete transcript. ## Query parameters | Parameter | Type | Description | |---|---|---| | `episode_sub_id` | string | The transcript of one episode | | `sub_id` | string | Transcripts of one podcast | | `full` | string | true = include speakers and segments; anything else or omitted = summary only | | `updated_from` | date | Last changed on or after (use for sync) | | `updated_to` | date | Last changed on or before | | `limit` | int | Results per page (default 25, max 100). With full=true: default 10, max 10, since a full transcript can be 1–2 MB | | `cursor` | string | next_cursor from the previous page | ## Response fields | Field | Type | Description | |---|---|---| | `episode_sub_id` | string | The episode this transcript belongs to | | `podcast` | object | {sub_id, podcast_name} | | `episode` | object | {episode_sub_id, episode_title, published_at, audio_url, link, image_url}, for convenience; the episodes endpoint is the source of truth. audio_url, link and image_url are always present, null when the feed has none. image_url is the episode's artwork, else the podcast's. audio_url is passed through from the feed as-is and may be a tracking or redirect URL | | `language` | string \| null | Language detected from the audio, e.g. en (may differ from the podcast's declared language) | | `duration_seconds` | number \| null | Measured audio length | | `speakers_identified` | boolean | false = speaker names haven't been identified (yet); labels still work, names are null | | `created_at` | date | When the transcript was first produced | | `updated_at` | date | Last change (re-transcription or speakers identified) | | `speakers` | object | full=true only. Speaker label → {name, role, title, company} | | `segments` | array | full=true only. {start, end, text, speaker} in order; start/end in seconds from the start of the audio | ## Speakers Each segment's `speaker` (e.g. `SPEAKER_00`) is a key into `speakers`. Labels are per transcript: `SPEAKER_00` in one episode is unrelated to `SPEAKER_00` in another. Identification is automatic and best-effort: any of `name`, `role`, `title` and `company` may be `null`. `role` is the speaker's part in the conversation (`host`, `co-host`, `guest`, …). A segment's `speaker` may be missing where speakers couldn't be separated. A transcript can change after it is first published, for example when speaker names are filled in later. Its `updated_at` changes, so an `updated_from` sync picks it up again. ## Example: one full transcript ``` GET /api/v1/podcast-transcripts/?episode_sub_id=c41f7a09e2b85d13&full=true ``` ``` { "success": true, "results": [ { "episode_sub_id": "c41f7a09e2b85d13", "podcast": { "sub_id": "a1b2c3d4e5", "podcast_name": "Example Business Show" }, "episode": { "episode_sub_id": "c41f7a09e2b85d13", "episode_title": "Rate Cuts, Robotaxis and the Week in Markets", "published_at": "2026-09-24T16:38:09Z", "audio_url": "https://media.example.com/c41f7a09e2b85d13.mp3", "link": "https://podcasts.example.com/episodes/c41f7a09e2b85d13", "image_url": "https://images.example.com/c41f7a09e2b85d13.jpg" }, "language": "en", "duration_seconds": 6875.2, "speakers_identified": true, "speakers": { "SPEAKER_00": { "name": "Jane Host", "role": "host", "title": "journalist", "company": "Example Media" }, "SPEAKER_01": { "name": "Sam Guest", "role": "guest", "title": "economist", "company": null } }, "segments": [ { "start": 1.0, "end": 9.72, "text": "Welcome back to the show. Big week in markets.", "speaker": "SPEAKER_00" }, { "start": 10.1, "end": 17.4, "text": "It really was. Let's start with the rate decision.", "speaker": "SPEAKER_01" } ], "created_at": "2026-09-25T06:12:47Z", "updated_at": "2026-09-27T05:48:31Z" } ], "returned_results": 1, "limit": 10, "next_cursor": null } ``` Without `full=true`, each result has the same fields except `speakers` and `segments`. --- # Guide: daily podcast data sync via API Source: https://subalytics.com/docs/podcast-sync/ > How to load Subalytics podcast data once, then sync new episodes and changed transcripts each day with updated_from and transcribed_from. For a first load, list podcasts, then each podcast's episodes, then fetch transcripts with `full=true`. After that, ask only for what changed since your last sync: ## 1. New or changed transcripts ``` GET /api/v1/podcast-transcripts/?updated_from=2026-09-26T05:00:00 ``` Returns summaries of transcripts that are new, re-transcribed, or had speaker names filled in. Fetch the ones you need with `?episode_sub_id=&full=true`. ## 2. Newly available episodes ``` GET /api/v1/podcast-episodes/?transcribed_from=2026-09-26T05:00:00 ``` Filters on when an episode became available, not when it was published, so an episode published three days ago but transcribed today is included. ## 3. New podcasts Re-list `/api/v1/podcasts/` occasionally to pick up newly added podcasts. Start each `*_from` a few minutes before your previous sync. Receiving the same record twice is harmless. --- # Company mentions API: overview Source: https://subalytics.com/docs/entity-overview/ > How the Subalytics entity mentions API works: stable IDs, freshness, typical workflow, daily sync and withdrawn mentions. Entity mentions finds references to public companies in Substack posts, Bluesky posts and podcast episodes. It is a separate product from the other endpoints, with its own access, and every endpoint name starts with `entity-`. **Only content that mentions a company is returned.** A post or episode appears only if it has at least one company mention. Podcast endpoints return only the transcript passages that contain a mention, never the full transcript. ## IDs Resources are linked by stable public IDs that never change for the same item, so they are safe to store as foreign keys: | ID | Identifies | Notes | |---|---|---| | `symbol` | Company | Stock ticker, e.g. META | | `mention_id` | Mention | One mention of one company in one piece of content | | `content_id` | Content | The post or episode: post_id (Substack), post_uri (Bluesky) or episode_sub_id (podcasts) | | `sub_id` | Creator / podcast | The same Subalytics ID used by the creator and podcast endpoints, so mentions join to data you already have | To fetch one item, filter by its ID, e.g. `/api/v1/entity-mentions/?mention_id=9f2c41d07ab35e18`. ## Freshness - **Bluesky:** posts usually appear within minutes. - **Substack:** posts appear after each collection run. - **Podcasts:** episodes appear once they have been transcribed and matched, usually within a few hours of the daily 05:00 UTC run. ## Typical workflow - **List monitored companies:** `GET /api/v1/entity-companies/`. This is the only endpoint with CIK, exchange, sector and industry; the others identify a company by `symbol` and `company_name`. - **Get mentions of a company:** `GET /api/v1/entity-mentions/?symbol=META&published_from=2026-09-01`. One row per mention from every source, each with a snippet and a link to the content. - **Get the content:** `GET /api/v1/entity-bluesky-posts/?symbol=META`, or the Substack or podcast equivalent. Each post or episode lists every company it mentions in `entities[]`. - **Track volume:** `GET /api/v1/entity-mention-stats/?symbol=META&interval=day` for a time series, or `GET /api/v1/entity-trending/?sort=change` for the companies whose mention volume moved most. ## Daily sync Ask only for what was added or changed since your last sync: ``` GET /api/v1/entity-mentions/?updated_from=2026-09-28T05:00:00 GET /api/v1/entity-bluesky-posts/?updated_from=2026-09-28T05:00:00 ``` `updated_from` filters on when a record last changed, not when the content was published: a podcast episode published three days ago but matched today is included. Start each `updated_from` a few minutes before your previous sync; receiving the same record twice is harmless. ## Mentions can be withdrawn Matching improves over time and past content is re-checked. That can add mentions, change their confidence, or remove a mention that turned out to be wrong. A post whose last mention is removed disappears from the content endpoints. Removals don't show up in an `updated_from` sync, so re-pull a recent window (e.g. the last 30 days) periodically if you need an exact match with the API. --- # Companies API endpoint (entity mentions) Source: https://subalytics.com/docs/entity-companies/ > GET /api/v1/entity-companies/: every public company monitored for mentions, with ticker, CIK, exchange, sector and industry. `GET /api/v1/entity-companies/` (Cursor pagination · newest first). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Every company monitored for mentions; a company not listed here is never matched. This is the reference for official company data. Other `entity-*` endpoints give only `symbol` and `company_name`, so join on `symbol` to get the rest. Newly monitored companies appear first. ## Query parameters | Parameter | Type | Description | |---|---|---| | `symbol` | string | One company, exact match, e.g. META | | `cik` | string | One company by SEC CIK | | `q` | string | Case-insensitive search on symbol and company name, e.g. q=meta | | `sector` | string | Exact match, e.g. Technology | | `exchange` | string | Exact match, e.g. NASDAQ | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Response fields | Field | Type | Description | |---|---|---| | `symbol` | string | Ticker | | `company_name` | string | Official company name | | `cik` | string \| null | SEC CIK | | `exchange` | string \| null | Listing exchange | | `sector` | string \| null | Sector | | `industry` | string \| null | Industry | ## Example ``` GET /api/v1/entity-companies/?q=meta ``` ``` { "success": true, "results": [ { "symbol": "META", "company_name": "Meta Platforms, Inc.", "cik": "0001326801", "exchange": "NASDAQ", "sector": "Communication Services", "industry": "Internet Content & Information" } ], "returned_results": 1, "limit": 25, "next_cursor": null } ``` --- # Company mentions API endpoint Source: https://subalytics.com/docs/entity-mentions/ > GET /api/v1/entity-mentions/: one row per company mention in podcasts, Substack and Bluesky, with snippet and link. Parameters and example. `GET /api/v1/entity-mentions/` (Cursor pagination · newest first). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ One row per company mention in one piece of content, across all three sources. Filter by `symbol` to see who is talking about a company, or by `sub_id` to see which companies a creator or podcast talks about. ## Query parameters | Parameter | Type | Description | |---|---|---| | `mention_id` | string | One mention | | `symbol` | string | Mentions of one company | | `source` | string | substack, bluesky or podcast; omit for all | | `sub_id` | string | Mentions by one creator or in one podcast | | `content_id` | string | Mentions in one post or episode (post_id, post_uri or episode_sub_id) | | `match_type` | string | cashtag, company_name, alias, product or ticker | | `min_confidence` | number | 0.5–1.0, default 0.7 | | `published_from` | date | Content published on or after | | `published_to` | date | Content published on or before | | `updated_from` | date | Mention last changed on or after (use for sync) | | `updated_to` | date | Mention last changed on or before | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Response fields | Field | Type | Description | |---|---|---| | `mention_id` | string | Public mention ID | | `symbol` | string | Company ticker | | `company_name` | string | Official company name | | `source` | string | substack, bluesky or podcast | | `content_id` | string | ID of the post or episode on its content endpoint | | `sub_id` | string | The creator or podcast | | `content_url` | string \| null | Link to the original post or episode page | | `published_utc` | date | When the content was published | | `match_type` | string | What was matched: cashtag, company_name, alias, product or ticker | | `matched_text` | string | The text as it appeared in the content | | `confidence` | number | 0–1 | | `snippet` | string | The sentence or passage around the mention | | `field` | string \| null | Posts only: where the match was found | | `start, end` | number \| null | Podcasts only: seconds from the start of the audio | | `created_at` | date | When the mention was first found | | `updated_at` | date | When the mention last changed (e.g. re-scored) | ## Example ``` GET /api/v1/entity-mentions/?symbol=META&published_from=2026-09-20&limit=2 ``` ``` { "success": true, "results": [ { "mention_id": "9f2c41d07ab35e18", "symbol": "META", "company_name": "Meta Platforms, Inc.", "source": "bluesky", "content_id": "at://did:plc:exampleaccount000000000/app.bsky.feed.post/3lqz7x2kfbc2s", "sub_id": "e81a3f90c2", "content_url": "https://bsky.app/profile/did:plc:exampleaccount000000000/post/3lqz7x2kfbc2s", "published_utc": "2026-09-27T14:02:11Z", "match_type": "cashtag", "matched_text": "$META", "confidence": 0.95, "snippet": "$META up 4% premarket after ad revenue beat.", "field": "text", "start": null, "end": null, "created_at": "2026-09-27T14:03:40Z", "updated_at": "2026-09-27T14:03:40Z" }, { "mention_id": "c07e5b1a94d2f836", "symbol": "META", "company_name": "Meta Platforms, Inc.", "source": "podcast", "content_id": "c41f7a09e2b85d13", "sub_id": "a1b2c3d4e5", "content_url": "https://example.com/podcast/episodes/248", "published_utc": "2026-09-24T16:38:09Z", "match_type": "product", "matched_text": "instagram", "confidence": 0.78, "snippet": "and instagram is basically where every small brand does its marketing now", "field": null, "start": 1834.2, "end": 1841.9, "created_at": "2026-09-25T07:15:03Z", "updated_at": "2026-09-25T07:15:03Z" } ], "returned_results": 2, "limit": 2, "next_cursor": "6a7d9a11c8173839e2253ae4" } ``` --- # Mention stats API endpoint Source: https://subalytics.com/docs/entity-mention-stats/ > GET /api/v1/entity-mention-stats/: daily or weekly mention counts for one company, with no gaps in the series. Parameters and example. `GET /api/v1/entity-mention-stats/` (No pagination · up to 100 periods). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Mention counts for one company over time: one row per day or week, oldest first. Counts include only mentions with `confidence` of 0.7 or above. Periods with no mentions are returned with zero counts, so a series has no gaps. To rank companies against each other, use [trending companies](https://subalytics.com/docs/entity-trending/). This endpoint doesn't use cursors: `limit` caps the number of periods and `next_cursor` is always `null`. To cover a longer range, use `interval=week` or split the range into several requests. ## Query parameters | Parameter | Type | Description | |---|---|---| | `symbol` | string | Required. The company | | `source` | string | substack, bluesky or podcast; omit for all sources combined | | `interval` | string | day (default) or week (ISO weeks, starting Monday) | | `period_from` | date | First period returned. Default: 30 days before today | | `period_to` | date | Last period returned. Default: yesterday (the last full day) | | `limit` | int | Periods returned (default 100, max 100) | ## Response fields | Field | Type | Description | |---|---|---| | `symbol` | string | Company ticker | | `company_name` | string | Official company name | | `period_start` | date | Start of the day or week | | `interval` | string | day or week | | `mention_count` | integer | Mentions in the period | | `content_count` | integer | Distinct posts or episodes with at least one mention | | `creator_count` | integer | Distinct creators and podcasts (sub_id) | | `by_source` | object | {substack, bluesky, podcast} mention counts; only when source is omitted | ## Example ``` GET /api/v1/entity-mention-stats/?symbol=META&period_from=2026-09-25&period_to=2026-09-27 ``` ``` { "success": true, "results": [ { "symbol": "META", "company_name": "Meta Platforms, Inc.", "period_start": "2026-09-25T00:00:00Z", "interval": "day", "mention_count": 41, "content_count": 37, "creator_count": 33, "by_source": { "substack": 3, "bluesky": 36, "podcast": 2 } }, { "symbol": "META", "company_name": "Meta Platforms, Inc.", "period_start": "2026-09-26T00:00:00Z", "interval": "day", "mention_count": 58, "content_count": 51, "creator_count": 44, "by_source": { "substack": 5, "bluesky": 52, "podcast": 1 } }, { "symbol": "META", "company_name": "Meta Platforms, Inc.", "period_start": "2026-09-27T00:00:00Z", "interval": "day", "mention_count": 132, "content_count": 118, "creator_count": 97, "by_source": { "substack": 4, "bluesky": 125, "podcast": 3 } } ], "returned_results": 3, "limit": 100, "next_cursor": null } ``` --- # Trending companies API endpoint Source: https://subalytics.com/docs/entity-trending/ > GET /api/v1/entity-trending/: companies ranked by mention volume or by change against the previous window. Parameters and example. `GET /api/v1/entity-trending/` (No pagination · up to 100 companies). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Companies ranked by mention volume, or by how much their volume changed, over a time window. Each company is compared with the window of the same length immediately before it: for a 7-day window, the previous 7 days. Counts include only mentions with `confidence` of 0.7 or above. This endpoint doesn't use cursors: `limit` caps the number of companies and `next_cursor` is always `null`. ## Query parameters | Parameter | Type | Description | |---|---|---| | `source` | string | substack, bluesky or podcast; omit for all sources combined | | `period_from` | date | Start of the window to rank (whole days). Default: 7 days before today | | `period_to` | date | End of the window to rank. Default: yesterday (the last full day) | | `sort` | string | volume (default, most mentions in the window) or change (largest change_pct) | | `min_mentions` | int | Only rank companies with at least this many mentions in the window (default 10), so sort=change isn't dominated by moves like 1 → 5 mentions | | `sector` | string | Rank only companies in one sector (the sector value from entity-companies) | | `limit` | int | Companies returned (default 25, max 100) | ## Response fields | Field | Type | Description | |---|---|---| | `rank` | integer | 1 = top | | `symbol` | string | Company ticker | | `company_name` | string | Official company name | | `mention_count` | integer | Mentions in the window | | `previous_mention_count` | integer | Mentions in the equal-length window before | | `change_pct` | number \| null | Percentage change vs. the previous window; null when previous_mention_count is 0 | | `creator_count` | integer | Distinct creators and podcasts in the window | With `sort=change`, companies whose `change_pct` is `null` (no mentions in the previous window) are ranked after every company with a number. ## Example ``` GET /api/v1/entity-trending/?sort=change&period_from=2026-09-21&period_to=2026-09-27&limit=2 ``` ``` { "success": true, "results": [ { "rank": 1, "symbol": "META", "company_name": "Meta Platforms, Inc.", "mention_count": 412, "previous_mention_count": 139, "change_pct": 196.4, "creator_count": 301 }, { "rank": 2, "symbol": "TSLA", "company_name": "Tesla, Inc.", "mention_count": 5210, "previous_mention_count": 2884, "change_pct": 80.7, "creator_count": 3120 } ], "returned_results": 2, "limit": 2, "next_cursor": null } ``` --- # Substack posts with mentions: API endpoint Source: https://subalytics.com/docs/entity-substack-posts/ > GET /api/v1/entity-substack-posts/: Substack posts that mention at least one monitored company, each with its entities. Parameters and example. `GET /api/v1/entity-substack-posts/` (Cursor pagination · newest first). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Substack posts that mention at least one monitored company, each with its `entities[]`. This is separate from [`/api/v1/substack-posts/`](https://subalytics.com/docs/substack-posts/), which returns all posts. Post bodies are not returned: only the title, subtitle, description and the mention snippets. ## Query parameters | Parameter | Type | Description | |---|---|---| | `post_id` | string | One post | | `sub_id` | string | Posts by one creator | | `symbol` | string | Posts mentioning one company | | `min_confidence` | number | 0.5–1.0, default 0.7 | | `published_from` | date | Published on or after | | `published_to` | date | Published on or before | | `updated_from` | date | Mentions last changed on or after (use for sync) | | `updated_to` | date | Mentions last changed on or before | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Response fields | Field | Type | Description | |---|---|---| | `post_id` | string | Public post ID; content_id in entity-mentions | | `sub_id` | string | The creator | | `author_name` | string \| null | Author | | `title` | string \| null | Post title | | `subtitle` | string \| null | Post subtitle | | `description` | string \| null | Post description | | `canonical_url` | string | Link to the post | | `published_utc` | date | When the post was published | | `entities` | array | Company mentions: mention_id, symbol, company_name, match_type, matched_text, confidence, snippet, field | | `created_at` | date | When the post first appeared in this product | | `updated_at` | date | When its mentions last changed | ## Example ``` GET /api/v1/entity-substack-posts/?symbol=META&limit=1 ``` ``` { "success": true, "results": [ { "post_id": "173920451", "sub_id": "803b198749", "author_name": "Jane Writer", "title": "The Ad Market Reset", "subtitle": "Instagram now drives more ad revenue than the core app.", "description": "Why Meta and Google are fighting over the same small advertisers.", "canonical_url": "https://newsletter.example.com/p/the-ad-market-reset", "published_utc": "2026-09-20T11:00:00Z", "entities": [ { "mention_id": "51b8e2d7f03a9c64", "symbol": "META", "company_name": "Meta Platforms, Inc.", "match_type": "product", "matched_text": "Instagram", "confidence": 0.78, "snippet": "Instagram now drives more ad revenue than the core app.", "field": "subtitle" }, { "mention_id": "a3d90c6e18f2b475", "symbol": "GOOGL", "company_name": "Alphabet Inc.", "match_type": "alias", "matched_text": "Google", "confidence": 0.84, "snippet": "Why Meta and Google are fighting over the same small advertisers.", "field": "description" } ], "created_at": "2026-09-20T12:31:17Z", "updated_at": "2026-09-20T12:31:17Z" } ], "returned_results": 1, "limit": 1, "next_cursor": "6a7d9b02c8173839e2253b10" } ``` --- # Bluesky posts with mentions: API endpoint Source: https://subalytics.com/docs/entity-bluesky-posts/ > GET /api/v1/entity-bluesky-posts/: Bluesky posts that mention at least one monitored company, with full text and entities. Parameters and example. `GET /api/v1/entity-bluesky-posts/` (Cursor pagination · newest first). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Bluesky posts that mention at least one monitored company, each with its `entities[]`. Only top-level posts from tracked Bluesky accounts are included, not replies. Bluesky posts are short and public, so the full `text` is returned. ## Query parameters | Parameter | Type | Description | |---|---|---| | `post_uri` | string | One post | | `sub_id` | string | Posts by one creator | | `did` | string | Posts by one Bluesky account (DID) | | `symbol` | string | Posts mentioning one company | | `min_confidence` | number | 0.5–1.0, default 0.7 | | `published_from` | date | Published on or after | | `published_to` | date | Published on or before | | `updated_from` | date | Mentions last changed on or after (use for sync) | | `updated_to` | date | Mentions last changed on or before | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Response fields | Field | Type | Description | |---|---|---| | `post_uri` | string | Public post ID (AT Protocol URI); content_id in entity-mentions | | `sub_id` | string | The creator | | `did` | string | The Bluesky account | | `url` | string | Link to the post on bsky.app | | `text` | string | Full post text | | `published_utc` | date | When the post was created | | `entities` | array | Company mentions: mention_id, symbol, company_name, match_type, matched_text, confidence, snippet, field | | `created_at` | date | When the post first appeared in this product | | `updated_at` | date | When its mentions last changed | ## Example ``` GET /api/v1/entity-bluesky-posts/?symbol=META&min_confidence=0.9&limit=1 ``` ``` { "success": true, "results": [ { "post_uri": "at://did:plc:exampleaccount000000000/app.bsky.feed.post/3lqz7x2kfbc2s", "sub_id": "e81a3f90c2", "did": "did:plc:exampleaccount000000000", "url": "https://bsky.app/profile/did:plc:exampleaccount000000000/post/3lqz7x2kfbc2s", "text": "$META up 4% premarket after ad revenue beat. Instagram Reels doing the heavy lifting again.", "published_utc": "2026-09-27T14:02:11Z", "entities": [ { "mention_id": "9f2c41d07ab35e18", "symbol": "META", "company_name": "Meta Platforms, Inc.", "match_type": "cashtag", "matched_text": "$META", "confidence": 0.95, "snippet": "$META up 4% premarket after ad revenue beat.", "field": "text" } ], "created_at": "2026-09-27T14:03:40Z", "updated_at": "2026-09-27T14:03:40Z" } ], "returned_results": 1, "limit": 1, "next_cursor": "6a7d9c77c8173839e2253c21" } ``` The post also mentions "Instagram" below 0.9, so that entry is left out of `entities[]` because of `min_confidence=0.9`. --- # Podcast episodes with mentions: API Source: https://subalytics.com/docs/entity-podcast-episodes/ > GET /api/v1/entity-podcast-episodes/: podcast episodes that mention a monitored company, with the passage, timestamps and speaker. `GET /api/v1/entity-podcast-episodes/` (Cursor pagination · newest first). Base URL `https://subalytics.com/api/v1/`, API key in the `X-API-key` header; authentication, pagination, dates and errors: https://subalytics.com/docs/ Podcast episodes that mention at least one monitored company, each with its `entities[]`. Each entity includes the transcript passage around the mention (`snippet`), its timestamps (`start` / `end`) and the speaker. The full transcript is not part of this product; with access to the podcast endpoints you can fetch it from [`/api/v1/podcast-transcripts/`](https://subalytics.com/docs/podcast-transcripts/) with `?episode_sub_id=&full=true`. Transcripts are automatic speech recognition output, so snippets are lower-case and loosely punctuated, and company names are occasionally misheard. ## Query parameters | Parameter | Type | Description | |---|---|---| | `episode_sub_id` | string | One episode | | `sub_id` | string | Episodes of one podcast | | `symbol` | string | Episodes mentioning one company | | `min_confidence` | number | 0.5–1.0, default 0.7 | | `published_from` | date | Published on or after | | `published_to` | date | Published on or before | | `updated_from` | date | Mentions last changed on or after (use for sync) | | `updated_to` | date | Mentions last changed on or before | | `limit` | int | Results per page (default 25, max 100) | | `cursor` | string | next_cursor from the previous page | ## Response fields | Field | Type | Description | |---|---|---| | `episode_sub_id` | string | Public episode ID, same as on podcast-episodes; content_id in entity-mentions | | `sub_id` | string | The podcast | | `podcast_name` | string | Podcast name | | `episode_title` | string \| null | Episode title | | `link` | string \| null | Episode web page | | `published_utc` | date | When the episode was published | | `entities` | array | Company mentions: mention_id, symbol, company_name, match_type, matched_text, confidence, snippet, start, end, speaker | | `created_at` | date | When the episode first appeared in this product | | `updated_at` | date | When its mentions last changed | ## Example ``` GET /api/v1/entity-podcast-episodes/?symbol=META&limit=1 ``` ``` { "success": true, "results": [ { "episode_sub_id": "c41f7a09e2b85d13", "sub_id": "a1b2c3d4e5", "podcast_name": "Example Business Show", "episode_title": "Rate Cuts, Robotaxis and the Week in Markets", "link": "https://example.com/podcast/episodes/248", "published_utc": "2026-09-24T16:38:09Z", "entities": [ { "mention_id": "4e71d0b93ca2f58e", "symbol": "TSLA", "company_name": "Tesla, Inc.", "match_type": "alias", "matched_text": "tesla", "confidence": 0.88, "snippet": "and tesla launching the robotaxi this week is a bigger deal than the market is pricing in", "start": 412.6, "end": 419.3, "speaker": { "label": "SPEAKER_01", "name": "Sam Guest", "role": "guest" } }, { "mention_id": "c07e5b1a94d2f836", "symbol": "META", "company_name": "Meta Platforms, Inc.", "match_type": "product", "matched_text": "instagram", "confidence": 0.78, "snippet": "and instagram is basically where every small brand does its marketing now", "start": 1834.2, "end": 1841.9, "speaker": { "label": "SPEAKER_00", "name": "Jane Host", "role": "host" } } ], "created_at": "2026-09-25T07:15:03Z", "updated_at": "2026-09-25T07:15:03Z" } ], "returned_results": 1, "limit": 1, "next_cursor": "6a7d9d4ec8173839e2253d02" } ``` --- # API FAQ: keys, errors, pagination, updates Source: https://subalytics.com/docs/faq/ > Answers to common Subalytics API questions: getting a key, authentication, 401/403/400 errors, pagination, update times and syncing. ## Access and keys ### How do I get an API key? [Request access](https://subalytics.com/request-access/) and tell us which data you need. Each key is enabled for specific endpoints, and you can ask to add endpoints to an existing key. ### How do I authenticate? Send the key in the `X-API-key` header with every request to `https://subalytics.com/api/v1/`. See [authentication](https://subalytics.com/docs/#authentication). ### Does my key include company mentions? Not automatically. Entity mentions is a separate product with its own access: keys for other endpoints don't include the `entity-*` endpoints, and the reverse. See [about entity mentions](https://subalytics.com/docs/entity-overview/). ### Which podcasts can I query? Podcast endpoints return only the podcasts your key includes, with their episodes and transcripts. ## Errors ### Why do I get 401 Unauthorized? The API key is missing, or it isn't enabled for the endpoint you called. ### Why do I get 403 Forbidden? The request names a podcast, by `sub_id`, or one of its episodes, by `episode_sub_id`, that your key doesn't include. ### Why do I get 400 "Unknown parameters"? Any query parameter not listed for an endpoint is rejected with `400`, so check the spelling against the endpoint's page. Invalid dates, date ranges, limits, cursors and `min_confidence` values also return `400`, and the message says which. ### What should I do about a 500 error? Something went wrong on our side. Retry later, and check the [API status](https://subalytics.com/docs/status/) page. ### Is an empty result an error? No. An empty `results` list is a successful response. ## Pagination and dates ### How many results can I get per request? `limit` defaults to 25, with a maximum of 100. Full podcast transcripts (`full=true`) default to 10, with a maximum of 10, because one transcript can be 1–2 MB. ### How do I page through results? Cursor endpoints return `next_cursor`: pass it back as `cursor` until it is `null`. Offset endpoints take `offset`. Each endpoint's page says which it uses. See [pagination](https://subalytics.com/docs/#pagination). ### What time zone and format are dates in? UTC, as `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS`. Podcast and entity mentions responses return ISO 8601 with a `Z` suffix, the same format the filters accept. See [date filters](https://subalytics.com/docs/#date-filters). ### Do paths need a trailing slash? Yes. Every endpoint path ends with `/`, for example `/api/v1/podcasts/`. ## Updates and syncing ### How often is the data updated? - **Creators:** a weekly snapshot of each creator. - **Podcasts:** new episodes are transcribed in a daily run at 05:00 UTC. - **Company mentions:** Bluesky posts usually appear within minutes, Substack posts after each collection run, and podcast episodes within a few hours of the daily run. ### How do I keep my copy in sync? Ask only for what changed since your last sync with `updated_from` (and, for episodes, `transcribed_from`). Start each sync a few minutes before the previous one; receiving the same record twice is harmless. See the [daily podcast sync guide](https://subalytics.com/docs/podcast-sync/). ### Can a transcript change after it is published? Yes, for example when speaker names are filled in later. Its `updated_at` changes, so an `updated_from` sync picks it up again. ### Can a company mention disappear? Yes. Past content is re-checked as matching improves, which can add, change or remove mentions. Removals don't show up in an `updated_from` sync, so re-pull a recent window (e.g. the last 30 days) periodically if you need an exact match. ### Are speaker names always available? No. Speaker identification is automatic and best-effort: any of `name`, `role`, `title` and `company` may be `null`. See [podcast transcripts](https://subalytics.com/docs/podcast-transcripts/). ## Tools ### Is there an OpenAPI spec? Yes, an OpenAPI 3.1 description is at [`/openapi.json`](https://subalytics.com/openapi.json), for API clients, code generators and AI tools. ### Can I read the docs as Markdown? Yes. Add `.md` to any docs page, for example `/docs/podcast-transcripts.md`, or get every page in one file at [`/llms-full.txt`](https://subalytics.com/llms-full.txt). ### Can I check whether the API is up? Yes. See [API status](https://subalytics.com/docs/status/), or call `GET /api/status/`, which returns `{"status": "live"}` and needs no key.