API reference

Read your mentions, manage what is watched, and check usage from your own code. Base URL https://socialear.app/v1.

Kept in this browser only, so the Test buttons work as you read. It is never sent anywhere except to https://socialear.app/v1 — the same API you would call yourself. Clear it when you are done on a shared machine.

Authentication

Every request carries an API key as a bearer token. Create one on the API page; the secret is shown once at creation and stored only as a hash, so it cannot be recovered afterwards — if it is lost, revoke the key and make another.

A key carries the whole workspace’s access. Keep it on a server. Anything shipped to a browser or a mobile app is public no matter how it is obfuscated.

A request with no key, an unknown key, or a revoked key answers 401. The three are deliberately indistinguishable from outside.

Credits

Calls are metered in credits, granted monthly by your plan. A read costs 1, a write costs 2, and the balance is returned on every metered response in X-Credits-Remaining — so a client can watch its own budget without spending a call to check it.

Two balances, one number. The plan’s grant resets at the period boundary and is spent first; credits bought as a pack on the billing page never expire and are spent once the grant is gone. /v1/usage reports both — grant_remaining and topup_remaining — beside the total.

Credits are charged before the handler runs. That means a request that fails inside the handler has still been charged; it also means a caller with no balance is refused rather than served.

Running out answers 402, which is a distinct status from 401 and 429 on purpose: 402 means top up and retry, 401 means never retry, 429 means retry later.

Send an Idempotency-Key header to make a retry free. The key is remembered for a short window — long enough to absorb a client resending a request whose response it never saw, which is the reason a charge would otherwise be duplicated.

Errors

Every error has the same shape: a type to branch on, a stable code, a human message, and the offending field when there is one. The message is written for a person and may change; the code will not.

invalid_request_error (400) — something about the call is wrong. Fix it; never retry unchanged.

authentication_error (401) — the key is missing, wrong, or revoked.

insufficient_credits (402) — top up or wait for the period to reset, then retry.

rate_limit_error (429) — slow down. Retry-After says how long.

api_error (500) — our fault. Retry with backoff, and quote the X-Request-Id on every response if it persists.

Pagination

List endpoints return { object: "list", data, has_more, next_cursor }. Pass next_cursor back as starting_after to get the following page, and stop when has_more is false.

Do not build a cursor yourself. It encodes a timestamp and a row id together, because Reddit produces many items per second and a timestamp alone either skips rows at a page boundary or repeats them forever.

limit defaults to 25 and is capped at 100. A larger value is clamped rather than rejected.

Mentions

List mentions

GET/v1/mentions1 credit

Your matched posts, comments, and transcript windows, newest first, from every platform. Transcript mentions include a transcript object with is_asr, language, start_ms and end_ms. Every mention carries metrics — the platform’s own counts for the item, current as of the last poll that saw it: upvotes on Reddit, points on Hacker News and Lobsters, likes and comments on Instagram, views on YouTube, views, likes, comments and shares on TikTok, likes, reposts, replies, quotes, bookmarks and views on X — and score, the primary one of those under a generic name, for integrations written before metrics existed. Archived mentions are excluded unless you ask for them, and deleted ones are never returned.

Query parameters

limitinteger
Between 1 and 100. Defaults to 25.
starting_afterstring
A next_cursor from a previous page.
sourcestring
Restrict to one source, by its key: a subreddit name without the r/ prefix, or ~hn, ~lobsters, ~lobsters:rust, ~yt:<channelId>, ~ig:<username>, ~tt:<username>. The values come from /v1/sources.
platformstring
Restrict to one platform: reddit, hackernews, lobsters, youtube, instagram, tiktok, or x.
subredditstring
Deprecated alias for source. Identical behaviour; use source in new code.
kindstring
post, comment, or transcript. Omit for all kinds.
sentimentstring
positive, neutral, or negative.
intentstring
question, complaint, praise, buying, comparison, or mention.
unreadboolean
Pass true for unread only.
archivedboolean
Pass true to read the archive instead of the inbox.
sinceinteger
Unix seconds. Only mentions Reddit published at or after this. Use it to sync incrementally.
curl "https://socialear.app/v1/mentions?limit=25" \
  -H "Authorization: Bearer se_live_…"
Response
{
  "object": "list",
  "data": [
    {
      "object": "mention",
      "id": "mn_7f3a21c9",
      "source": "ClaudeAI",
      "platform": "reddit",
      "label": "r/ClaudeAI",
      "subreddit": "ClaudeAI",
      "kind": "post",
      "author": "example_user",
      "title": "Is Claude Pro (~$24/mo) genuinely worth it over Gemini / ChatGPT",
      "body": "Hey everyone, I’m starting university soon (Cybernetics and Robotics) and trying to decide whether Claude Pro is truly worth the ~$24/month (with VAT) for my use case, or if it’s an inefficient expense. A bit about me:…",
      "locked": false,
      "url": "https://reddit.com/r/ClaudeAI/comments/1wdkhkd/is_claude_pro_24mo_genuinely_worth_it_over_gemini/",
      "permalink": "/r/ClaudeAI/comments/1wdkhkd/is_claude_pro_24mo_genuinely_worth_it_over_gemini/",
      "score": null,
      "metrics": {},
      "created_utc": 1789142755,
      "sentiment": "neutral",
      "intent": "comparison",
      "relevance": 1,
      "is_read": false,
      "is_archived": false
    },
    {
      "object": "mention",
      "id": "mn_9b2e40d1",
      "source": "~ig:selfhostweekly",
      "platform": "instagram",
      "label": "@selfhostweekly",
      "subreddit": "~ig:selfhostweekly",
      "kind": "comment",
      "author": "example_user",
      "title": "My homelab, one year in — what stayed and what got ripped out",
      "body": "which one is the cron monitor in the second slide? been burned twice by silent backups, looking at acme and Healthchecks",
      "locked": false,
      "url": "https://www.instagram.com/p/DdDE8ZHOfeH/c/18115734686065312/",
      "permalink": "https://www.instagram.com/p/DdDE8ZHOfeH/c/18115734686065312/",
      "score": 3,
      "metrics": {
        "likes": 3
      },
      "created_utc": 1789536168,
      "sentiment": "neutral",
      "intent": "buying",
      "relevance": 0.92,
      "is_read": false,
      "is_archived": false
    },
    {
      "object": "mention",
      "id": "mn_c41d7e02",
      "source": "~tt:selfhostweekly",
      "platform": "tiktok",
      "label": "@selfhostweekly",
      "subreddit": "~tt:selfhostweekly",
      "kind": "comment",
      "author": "example_user",
      "title": "I tried 7 uptime monitors so you don’t have to",
      "body": "the acme one at 0:41 — does it do cron jobs too or just http? mine keep dying silently",
      "locked": false,
      "url": "https://www.tiktok.com/@selfhostweekly/video/7683649763480309022?share_comment_id=7685008080057058081",
      "permalink": "https://www.tiktok.com/@selfhostweekly/video/7683649763480309022?share_comment_id=7685008080057058081",
      "score": 12,
      "metrics": {
        "likes": 12
      },
      "created_utc": 1789571002,
      "sentiment": "neutral",
      "intent": "question",
      "relevance": 0.9,
      "is_read": false,
      "is_archived": false
    },
    {
      "object": "mention",
      "id": "mn_e8a17b3c",
      "source": "~x:selfhostweekly",
      "platform": "x",
      "label": "@selfhostweekly",
      "subreddit": "~x:selfhostweekly",
      "kind": "comment",
      "author": "example_user",
      "title": "I tried 7 uptime monitors so you don’t have to — the thread",
      "body": "the acme one — does it do cron jobs too or just http? mine keep dying silently and I only find out when a customer does",
      "locked": false,
      "url": "https://x.com/example_user/status/2100013412855820001",
      "permalink": "https://x.com/example_user/status/2100013412855820001",
      "score": 41,
      "metrics": {
        "likes": 41
      },
      "created_utc": 1789582310,
      "sentiment": "negative",
      "intent": "question",
      "relevance": 0.88,
      "is_read": false,
      "is_archived": false
    }
  ],
  "has_more": true,
  "next_cursor": "1789142755.mn_7f3a21c9"
}

Retrieve a mention

GET/v1/mentions/:id1 credit

One mention by id. body is null when the mention is locked — that is, when it arrived after the plan’s monthly allowance ran out. The row still exists and still counts, so the list and your usage figures agree.

Path parameters

idstringrequired
The mention id.
curl "https://socialear.app/v1/mentions/{id}" \
  -H "Authorization: Bearer se_live_…"
Response
{
  "object": "mention",
  "id": "mn_7f3a21c9",
  "source": "ClaudeAI",
  "platform": "reddit",
  "label": "r/ClaudeAI",
  "subreddit": "ClaudeAI",
  "kind": "post",
  "author": "example_user",
  "title": "Is Claude Pro (~$24/mo) genuinely worth it over Gemini / ChatGPT",
  "body": "Hey everyone, I’m starting university soon (Cybernetics and Robotics) and trying to decide whether Claude Pro is truly worth the ~$24/month (with VAT) for my use case, or if it’s an inefficient expense. A bit about me:…",
  "locked": false,
  "url": "https://reddit.com/r/ClaudeAI/comments/1wdkhkd/is_claude_pro_24mo_genuinely_worth_it_over_gemini/",
  "permalink": "/r/ClaudeAI/comments/1wdkhkd/is_claude_pro_24mo_genuinely_worth_it_over_gemini/",
  "score": null,
  "metrics": {},
  "created_utc": 1789142755,
  "sentiment": "neutral",
  "intent": "comparison",
  "relevance": 1,
  "is_read": false,
  "is_archived": false
}

Mark as read

POST/v1/mentions/:id/read2 credits

Marks one mention read. Idempotent: marking a read mention read again succeeds and changes nothing.

Path parameters

idstringrequired
The mention id.
curl -X POST "https://socialear.app/v1/mentions/{id}/read" \
  -H "Authorization: Bearer se_live_…"
Responseexample only
{
  "object": "mention",
  "id": "mn_7f3a21c9",
  "is_read": true
}

Archive

POST/v1/mentions/:id/archive2 credits

Moves a mention out of the inbox. Nothing is deleted — pass archived=true when listing to read it back.

Path parameters

idstringrequired
The mention id.
curl -X POST "https://socialear.app/v1/mentions/{id}/archive" \
  -H "Authorization: Bearer se_live_…"
Responseexample only
{
  "object": "mention",
  "id": "mn_7f3a21c9",
  "is_archived": true
}

Keywords

List keywords

GET/v1/keywords1 credit

Every keyword in the workspace, with how many times each has matched.

curl "https://socialear.app/v1/keywords" \
  -H "Authorization: Bearer se_live_…"
Response
{
  "object": "list",
  "data": [
    {
      "object": "keyword",
      "id": "kw_2c81f0",
      "term": "claude",
      "match_mode": "word",
      "negatives": [
        "monet"
      ],
      "enabled": true,
      "hits": 412,
      "created_at": 1754931200
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Create a keyword

POST/v1/keywords2 credits

Adds a term to watch. The same rules the dashboard enforces apply here: word and prefix modes match a single token, so a term containing a space must use phrase mode.

Body

termstringrequired
What to watch for. 2 to 40 characters.
match_modestring
word matches the whole token and is the default — "notion" hits "Notion is great" but not "notional". phrase matches an exact string including spaces. prefix matches tokens starting with the term, for product families.
negativesstring[]
Any of these appearing anywhere in the text discards the match. This is where precision comes from for a brand name that is also an ordinary word.
curl -X POST "https://socialear.app/v1/keywords" \
  -H "Authorization: Bearer se_live_…" \
  -H "Content-Type: application/json" \
  -d '{"term":"claude","match_mode":"word"}'
Responseexample only
{
  "object": "keyword",
  "id": "kw_2c81f0",
  "term": "claude",
  "match_mode": "word",
  "negatives": [],
  "enabled": true,
  "hits": 0
}

Delete a keyword

DELETE/v1/keywords/:id2 credits

Stops matching on a term. Mentions it already produced are kept.

Path parameters

idstringrequired
The keyword id.
curl -X DELETE "https://socialear.app/v1/keywords/{id}" \
  -H "Authorization: Bearer se_live_…"
Responseexample only
{
  "object": "keyword",
  "id": "kw_2c81f0",
  "deleted": true
}

Sources

A source is one place being watched: a subreddit, all of Hacker News, all of Lobsters, a single Lobsters tag, one YouTube channel, one public Instagram account, one public TikTok account, or one public X account. Each takes one slot from the plan, whichever platform it is on. Sources can be listed, read, created, paused, resumed and deleted here — the same operations as the dashboard, through the same rules.

Every source carries metrics: what its platform counts about the place, refreshed on every poll. A subreddit or feed reports posts_per_minute and comments_per_minute as measured; an Instagram account reports followers, following and posts_tracked; a TikTok account reports followers, following, likes, videos and videos_tracked, exact as the profile page publishes them; an X account reports followers, following, posts, media and posts_tracked, exact; a YouTube channel reports subscribers, views and videos. A key the platform does not publish — a channel that hides its subscriber count — is absent rather than zero, and as_of says when the numbers were read.

Every source has a key — SaaS, ~hn, ~lobsters, ~lobsters:rust, ~yt:<channelId>, ~ig:<username>, ~tt:<username>, ~x:<username> — and that key is what a mention carries as source and what you pass back to filter by it. The ~ prefix is safe to rely on: Reddit forbids ~ and : in a community name, so a prefixed key is never a subreddit.

Mentions also carry platform (reddit, hackernews, lobsters, youtube, instagram, tiktok, x) for grouping, and label for printing — so a client never has to reimplement those rules to show "lobsters/rust" instead of a key.

List watched sources

GET/v1/sources1 credit

Everything the workspace watches, on every platform, with the health of each and what its platform counts about it. next_poll_at is when the scheduler looks at it next, null for a YouTube channel, which is polled by its own consumer every six hours and pushed to on upload.

curl "https://socialear.app/v1/sources" \
  -H "Authorization: Bearer se_live_…"
Response
{
  "object": "list",
  "data": [
    {
      "object": "source",
      "id": "SaaS",
      "platform": "reddit",
      "label": "r/SaaS",
      "name": "r/SaaS",
      "avatar_url": null,
      "enabled": true,
      "watch_comments": true,
      "status": "ok",
      "last_error": null,
      "last_polled_at": 1757600180,
      "next_poll_at": 1757600452,
      "poll_interval_seconds": 272,
      "posts_per_minute": 0.41,
      "comments_per_minute": 18.7,
      "metrics": {
        "posts_per_minute": 0.41,
        "comments_per_minute": 18.7,
        "as_of": 1757600180
      },
      "created_at": 1754931200
    },
    {
      "object": "source",
      "id": "~hn",
      "platform": "hackernews",
      "label": "Hacker News",
      "name": "Hacker News",
      "avatar_url": null,
      "enabled": true,
      "watch_comments": true,
      "status": "ok",
      "last_error": null,
      "last_polled_at": 1757600160,
      "next_poll_at": 1757600280,
      "poll_interval_seconds": 120,
      "posts_per_minute": 0.66,
      "comments_per_minute": 6.2,
      "metrics": {
        "posts_per_minute": 0.66,
        "comments_per_minute": 6.2,
        "as_of": 1757600160
      },
      "created_at": 1757001200
    },
    {
      "object": "source",
      "id": "~yt:UCX6OQ3DkcsbYNE6H8uQQuVA",
      "platform": "youtube",
      "label": "YouTube/UCX6OQ3DkcsbYNE6H8uQQuVA",
      "name": "MrBeast",
      "avatar_url": "https://yt3.ggpht.com/…=s88",
      "enabled": true,
      "watch_comments": null,
      "status": "ok",
      "last_error": null,
      "last_polled_at": 1789549800,
      "next_poll_at": null,
      "poll_interval_seconds": 21600,
      "posts_per_minute": 0,
      "comments_per_minute": 0,
      "metrics": {
        "subscribers": 456000000,
        "views": 98765432100,
        "videos": 903,
        "as_of": 1789549800
      },
      "created_at": 1789200000
    },
    {
      "object": "source",
      "id": "~ig:mrbeast",
      "platform": "instagram",
      "label": "@mrbeast",
      "name": "@mrbeast",
      "avatar_url": "https://scontent-zrh1-1.cdninstagram.com/v/…",
      "enabled": true,
      "watch_comments": true,
      "status": "ok",
      "last_error": null,
      "last_polled_at": 1789570658,
      "next_poll_at": 1789572458,
      "poll_interval_seconds": 1800,
      "posts_per_minute": 0,
      "comments_per_minute": 0,
      "metrics": {
        "followers": 89364569,
        "following": 1003,
        "posts_tracked": 12,
        "as_of": 1789570658
      },
      "created_at": 1789560000
    },
    {
      "object": "source",
      "id": "~tt:mrbeast",
      "platform": "tiktok",
      "label": "@mrbeast",
      "name": "@mrbeast",
      "avatar_url": "https://p16-common-sign.tiktokcdn-eu.com/tos-maliva-avt-0068/…",
      "enabled": true,
      "status": "ok",
      "last_error": null,
      "last_polled_at": 1789571400,
      "next_poll_at": 1789573200,
      "poll_interval_seconds": 1800,
      "posts_per_minute": 0,
      "comments_per_minute": 0,
      "metrics": {
        "followers": 140855715,
        "following": 355,
        "likes": 1464579515,
        "videos": 473,
        "videos_tracked": 28,
        "as_of": 1789571400
      },
      "created_at": 1789560000
    },
    {
      "object": "source",
      "id": "~x:mrbeast",
      "platform": "x",
      "label": "@mrbeast",
      "name": "@mrbeast",
      "avatar_url": "https://pbs.twimg.com/profile_images/…_normal.jpg",
      "enabled": true,
      "status": "ok",
      "last_error": null,
      "last_polled_at": 1789571520,
      "next_poll_at": 1789573320,
      "poll_interval_seconds": 1800,
      "posts_per_minute": 0,
      "comments_per_minute": 0,
      "metrics": {
        "followers": 39150233,
        "following": 1201,
        "posts": 35812,
        "media": 9340,
        "posts_tracked": 40,
        "as_of": 1789571520
      },
      "created_at": 1789560000
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Retrieve a source

GET/v1/sources/:key1 credit

One watched source by its key, with its metrics. A key the workspace does not watch is a 400 with code not_found.

Path parameters

keystringrequired
The source key: SaaS, ~hn, ~lobsters:rust, ~yt:<channelId>, ~ig:<username>, ~tt:<username>.
curl "https://socialear.app/v1/sources/{key}" \
  -H "Authorization: Bearer se_live_…"
Response
{
  "object": "source",
  "id": "~ig:mrbeast",
  "platform": "instagram",
  "label": "@mrbeast",
  "name": "@mrbeast",
  "avatar_url": "https://scontent-zrh1-1.cdninstagram.com/v/…",
  "enabled": true,
  "watch_comments": true,
  "status": "ok",
  "last_error": null,
  "last_polled_at": 1789570658,
  "next_poll_at": 1789572458,
  "poll_interval_seconds": 1800,
  "posts_per_minute": 0,
  "comments_per_minute": 0,
  "metrics": {
    "followers": 89364569,
    "following": 1003,
    "posts_tracked": 12,
    "as_of": 1789570658
  },
  "created_at": 1789560000
}

Watch a source

POST/v1/sources2 credits

Adds a place to watch on any platform, through the same rules as the dashboard: the plan’s slot limit, the platform’s own check that the place exists and can be read, and the first poll within seconds. A subreddit, a Lobsters tag, an Instagram account, a TikTok account or an X account is confirmed in the request and answers 201 with the source. A YouTube channel is resolved by the consumer and answers 202 with status resolving; it appears in the list, with its key, once resolved, and its latest 50 uploads are checked against the keywords.

Body

platformstringrequired
reddit, hackernews, lobsters, youtube, instagram, tiktok, or x.
handlestring
Which part of the platform: a subreddit name (with or without r/); a Lobsters tag, or empty for all of Lobsters; empty for Hacker News, which is watched whole; a YouTube channel ID, @handle or channel URL; an Instagram, TikTok or X @username or profile URL (a twitter.com URL is accepted too).
watch_commentsboolean
Whether to take the comments (on X, the replies) under what the source watches, as well as the posts. Defaults to true. False watches the posts alone: a subreddit’s threads without the replies, an account’s own posts without what people say under them. Ignored for YouTube, All of Reddit and a Lobsters tag, which have no comments to take.
exclude_shortsboolean
YouTube only. Skip videos that are Shorts.
exclude_made_for_kidsboolean
YouTube only. Skip videos marked made for kids.
curl -X POST "https://socialear.app/v1/sources" \
  -H "Authorization: Bearer se_live_…" \
  -H "Content-Type: application/json" \
  -d '{"platform":"instagram","handle":"@mrbeast"}'
Responseexample only
{
  "object": "source",
  "id": "~ig:mrbeast",
  "platform": "instagram",
  "label": "@mrbeast",
  "name": "@mrbeast",
  "avatar_url": "https://scontent-zrh1-1.cdninstagram.com/v/…",
  "enabled": true,
  "watch_comments": true,
  "status": "ok",
  "last_error": null,
  "last_polled_at": 1789570658,
  "next_poll_at": 1789572458,
  "poll_interval_seconds": 1800,
  "posts_per_minute": 0,
  "comments_per_minute": 0,
  "metrics": {
    "followers": 89364569,
    "following": 1003,
    "posts_tracked": 12,
    "as_of": 1789570658
  },
  "created_at": 1789560000
}

Resume a source

POST/v1/sources/:key/enable2 credits

Turns a paused source back on, re-checking the plan’s slot limit, and publishes its first poll immediately. Answers with the source.

Path parameters

keystringrequired
The source key.
curl -X POST "https://socialear.app/v1/sources/{key}/enable" \
  -H "Authorization: Bearer se_live_…"
Responseexample only
{
  "object": "source",
  "id": "SaaS",
  "platform": "reddit",
  "label": "r/SaaS",
  "name": "r/SaaS",
  "avatar_url": null,
  "enabled": true,
  "watch_comments": true,
  "status": "ok",
  "last_error": null,
  "last_polled_at": 1757600180,
  "next_poll_at": 1757600452,
  "poll_interval_seconds": 272,
  "posts_per_minute": 0.41,
  "comments_per_minute": 18.7,
  "metrics": {
    "posts_per_minute": 0.41,
    "comments_per_minute": 18.7,
    "as_of": 1757600180
  },
  "created_at": 1754931200
}

Comments on or off

POST/v1/sources/:key/comments2 credits

Turns the comments (on X, the replies) under a source on or off for this workspace, without touching what was already collected. Off, the source is polled for posts alone from its next check. A source with no comments to take — a YouTube channel, All of Reddit, a Lobsters tag — is a 400 with code no_comments. Answers with the source.

Path parameters

keystringrequired
The source key.

Body

enabledbooleanrequired
true to take the comments, false for posts only.
curl -X POST "https://socialear.app/v1/sources/{key}/comments" \
  -H "Authorization: Bearer se_live_…"
Responseexample only
{
  "object": "source",
  "id": "SaaS",
  "platform": "reddit",
  "label": "r/SaaS",
  "name": "r/SaaS",
  "avatar_url": null,
  "enabled": true,
  "watch_comments": false,
  "status": "ok",
  "last_error": null,
  "last_polled_at": 1757600180,
  "next_poll_at": 1757600452,
  "poll_interval_seconds": 272,
  "posts_per_minute": 0.41,
  "comments_per_minute": 18.7,
  "metrics": {
    "posts_per_minute": 0.41,
    "comments_per_minute": 18.7,
    "as_of": 1757600180
  },
  "created_at": 1754931200
}

Pause a source

POST/v1/sources/:key/disable2 credits

Stops polling a source for this workspace without deleting what it collected. It keeps its slot until it is deleted.

Path parameters

keystringrequired
The source key.
curl -X POST "https://socialear.app/v1/sources/{key}/disable" \
  -H "Authorization: Bearer se_live_…"
Responseexample only
{
  "object": "source",
  "id": "SaaS",
  "platform": "reddit",
  "label": "r/SaaS",
  "name": "r/SaaS",
  "avatar_url": null,
  "enabled": false,
  "watch_comments": true,
  "status": "ok",
  "last_error": null,
  "last_polled_at": 1757600180,
  "next_poll_at": 1757600452,
  "poll_interval_seconds": 272,
  "posts_per_minute": 0.41,
  "comments_per_minute": 18.7,
  "metrics": {
    "posts_per_minute": 0.41,
    "comments_per_minute": 18.7,
    "as_of": 1757600180
  },
  "created_at": 1754931200
}

Delete a source

DELETE/v1/sources/:key2 credits

Stops watching a place and deletes every mention this workspace collected from it. Other workspaces watching the same place are unaffected.

Path parameters

keystringrequired
The source key.
curl -X DELETE "https://socialear.app/v1/sources/{key}" \
  -H "Authorization: Bearer se_live_…"
Responseexample only
{
  "object": "source",
  "id": "SaaS",
  "deleted": true
}

Subreddits (deprecated)

This endpoint predates the product watching anything but Reddit. It still works and still returns every source, but it describes each one as a subreddit — so a Hacker News watch arrives with object "subreddit" and the name ~hn, which is true of the key and misleading about everything else.

Use /v1/sources instead. This will not be removed without a new API version.

List watched subreddits

GET/v1/subreddits1 credit

Deprecated: use /v1/sources, which names the platform of each place instead of calling all of them subreddits. Kept working so that integrations written before there were three platforms do not break.

curl "https://socialear.app/v1/subreddits" \
  -H "Authorization: Bearer se_live_…"
Response
{
  "object": "list",
  "data": [
    {
      "object": "subreddit",
      "name": "SaaS",
      "platform": "reddit",
      "enabled": true,
      "status": "ok",
      "last_polled_at": 1757600180,
      "posts_per_minute": 0.41,
      "comments_per_minute": 18.7,
      "created_at": 1754931200
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Transcripts

Every YouTube video the consumer reads is kept whole, once per video, as JSON segments in the shape YouTube gives them: text, start and duration in milliseconds. There is no end field, because YouTube does not send one — it is start + duration.

A transcript mention tells you which window matched; this is the rest of what was said. A workspace can read the transcript of any video on a channel it watches, or of any video it holds a mention from.

Retrieve a transcript

GET/v1/videos/:id/transcript1 credit

The whole transcript of one video. language is the caption track’s language code and is_asr says whether YouTube generated it by speech recognition rather than the channel uploading it. Large: an hour of captions is several hundred kilobytes.

Path parameters

idstringrequired
The 11-character YouTube video id — the part after yt_ in a transcript mention’s permalink v= parameter.
curl "https://socialear.app/v1/videos/{id}/transcript" \
  -H "Authorization: Bearer se_live_…"
Responseexample only
{
  "platform": "youtube",
  "videoId": "dQw4w9WgXcQ",
  "channelId": "UCX6OQ3DkcsbYNE6H8uQQuVA",
  "language": "en",
  "isAsr": true,
  "fetchedAt": 1789570000,
  "segments": [
    {
      "text": "the one that actually surprised me was acme",
      "start": 761000,
      "duration": 3200
    },
    {
      "text": "the status page took two minutes",
      "start": 764200,
      "duration": 2100
    }
  ]
}

Usage

Retrieve usage

GET/v1/usageFree

Mentions and credits for the current period, and the plan’s limits. This endpoint is free — checking whether you can afford a call must not cost one.

curl "https://socialear.app/v1/usage" \
  -H "Authorization: Bearer se_live_…"
Response
{
  "object": "usage",
  "plan": "pro",
  "period_start": 1757030400,
  "period_end": 1759622400,
  "mentions": {
    "used": 418,
    "included": 2000,
    "withheld": 0
  },
  "credits": {
    "remaining": 19217,
    "included": 20000,
    "grant_remaining": 19217,
    "topup_remaining": 0,
    "spent": 783
  },
  "limits": {
    "sources": 10,
    "subreddits": 10,
    "keywords": 30,
    "poll_seconds": 300,
    "retention_days": 365
  },
  "platforms": [
    "reddit",
    "hackernews",
    "lobsters",
    "youtube",
    "instagram",
    "tiktok",
    "x"
  ]
}