Social Listening API: 4 Calls, Once Each
25.92 GBP is the 3-page upper figure for Reddit and YouTube every 1h. On 8 Nov 2026 the check spent 6 credits and stored a baseline, not a later mention.
Social listening is a listener you create once for a keyword or boolean topic, priced first with ?dry_run=1. Once each is the rule for a mention after that baseline. For a tools list, read best social listening tools. You can stop writing the loop that polls the same keyword search and then drops, by hand, the posts you already stored.
On 8 Nov 2026 the four calls below priced a listener, created it, read its mentions, and registered a webhook. The topic was the coffee method pour over, not a brand. The blocks below are shortened fields from the capture. That run stored a baseline and did not show a later mention. The listener was deleted before the next fire. The dry run cost 0 credits. The quote for Reddit and YouTube was 25.92 GBP as the 3-page upper figure.
What does a social listening API quote before you create it?
On 8 Nov 2026 a social listening API dry run quoted 1,440 credits a month for Reddit and YouTube, 25.92 GBP as the 3-page upper figure, and 0 credits to ask. The call was POST /v1/listening/streams?dry_run=1 at 02:08:07Z. It returned HTTP 200 and credits_used 0. The body was the one you would create: keywords ["pour over"], platforms Reddit and YouTube, schedule.every 1h, and schedule.name pour over chatter.
curl -X POST "https://www.socialcrawl.dev/v1/listening/streams?dry_run=1" \
-H "x-api-key: $SOCIALCRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"keywords":["pour over"],"platforms":["reddit","youtube"],"schedule":{"every":"1h","name":"pour over chatter"}}'The read-back was Posts mentioning “pour over”. The lanes on that quote were reddit/search and youtube/search/advanced. Both were newest_first, max_pages 3, and empty_pages_refunded true. That refund flag is the lane's rule, and this listener did not receive that refund.
The quote returned credits_per_hour 2, credits_per_month 1,440, depth_range_credits_per_month 1,440 to 4,320, recommended_max_credits_per_month 4,911, and money_per_credit 0.006 GBP on basis starter_list. Each platform was 720 credits a month. money_per_month was 25.92 GBP. That 25.92 GBP is the 3-page upper figure on the response, not a promise of a typical month. screen.result was allowed. See priced before you create it for how that price is calculated.
{
"credits_used": 0,
"data": {
"read_back": "Posts mentioning “pour over”",
"lanes": [
{
"lane": "reddit/search",
"ordering": "newest_first",
"max_pages": 3,
"empty_pages_refunded": true
},
{
"lane": "youtube/search/advanced",
"ordering": "newest_first",
"max_pages": 3,
"empty_pages_refunded": true
}
],
"estimate": {
"credits_per_hour": 2,
"credits_per_month": 1440,
"depth_range_credits_per_month": [1440, 4320],
"recommended_max_credits_per_month": 4911,
"money_per_credit": { "amount": 0.006, "currency": "GBP", "basis": "starter_list" },
"money_per_month": { "amount": 25.92, "currency": "GBP" }
},
"screen": { "result": "allowed" }
}
}The block is shortened fields from the capture. The create, at 02:09:12Z, was the same body plus schedule.max_credits_per_month 4911, the recommended cap on this response. A different body can return a different cap.
curl -X POST "https://www.socialcrawl.dev/v1/listening/streams" \
-H "x-api-key: $SOCIALCRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"keywords":["pour over"],"platforms":["reddit","youtube"],"schedule":{"every":"1h","name":"pour over chatter","max_credits_per_month":4911}}'The response was HTTP 201, credits_used 0, id lst_m5DZU2OVQsBzbhd9p1C2U. Baseline was establishing. Spend was gross 0, refunded 0, net 0. Lane last_check_at was null. Caps were 4,911 for the month and 6 for a run. last_fire_at was 2026-11-08T02:09:11.761Z. next_fire_at was 2026-11-08T03:09:11.713Z, the next hour on 8 Nov 2026.
The check finished before the mentions read. After that check, both the delete and the confirm GET showed month 2026-11 spend gross 6, refunded 0, net 6, baseline established, and last_check_at 2026-11-08T02:09:18.551Z. That 6 is one slot at the run cap of 6. The runs route was not called, so there is no per-page line. credits_refunded stayed 0. There is no no_new_items line, and there was no second check.
How do you run keyword monitoring on social media?
You read the mentions the listener kept. On 8 Nov 2026 that was GET /v1/listening/streams/lst_m5DZU2OVQsBzbhd9p1C2U/mentions?limit=5 at 02:09:45Z, HTTP 200, credits_used 0.
curl "https://www.socialcrawl.dev/v1/listening/streams/lst_m5DZU2OVQsBzbhd9p1C2U/mentions?limit=5" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"The page had five rows, has_more true, and dropped 0, so this page is not the whole set. All five had baseline true and platform youtube. Reddit was not on this page and was not counted. Only one row's text is quoted below.
The row is mention id men_00816399bfd354856ea6b14c, platform youtube, baseline true, record_type video, matched_keywords ["pour over"], literal_match true, relevance p 0.85, and first_seen_at 2026-11-08T02:09:17.458Z. The text field was 233 characters. The JSON below keeps the first 80: Downtown Seattle's new pour-over spot? Narrative Coffee #coffee #pourover #seat. Those scores are returned fields, and this run has no accuracy rate. The JSON uses shortened field names from the capture.
{
"mention_id": "men_00816399bfd354856ea6b14c",
"first_seen_at": "2026-11-08T02:09:17.458Z",
"platform": "youtube",
"baseline": true,
"record_type": "video",
"literal_match": true,
"text": "Downtown Seattle's new pour-over spot? Narrative Coffee #coffee #pourover #seat",
"matched_keywords": ["pour over"],
"relevance": "p 0.85"
}This page is the baseline. The rows are readable, and this run did not show a later mention.
How is a social media listening API different from polling?
After the mentions read above, this run also used a social media listening API for a named events consumer and a webhook registration. Standing polls against a monitoring route are a different post, social media monitoring.
The events call was GET /v1/events?consumer=blog-listening-demo&types=mention.created&start=now&limit=5 at 02:10:58Z. HTTP 200, credits_used 0. It was not acknowledged.
curl "https://www.socialcrawl.dev/v1/events?consumer=blog-listening-demo&types=mention.created&start=now&limit=5" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"The call returned 0 items, unread 0, has_more false, dropped 0, and empty_reason no_matches. The response note was: "The source answered and has no rows for this request. The same call returns the same answer, so change the query or the filters to get rows."
{
"credits_used": 0,
"unread": 0,
"has_more": false,
"dropped": 0,
"empty_reason": "no_matches"
}start=now ran at 02:10:58Z, about 100 seconds after the check (last_check_at 2026-11-08T02:09:18.551Z). This empty page does not prove the check wrote no mention.created events. There was no second events read. Consumer blog-listening-demo is bound to mention.created with subject_ids null. It listed 5 listeners on this key, including this one, with both lanes health ok and checks_since_last_read 0. The feed is the events feed.
POST /v1/webhook-endpoints targeted https://example.com/hooks/socialcrawl-listening-demo, type mention.created, subject_ids this listener. HTTP 201, credits_used 0, status enabled, id we_kThLyRoMOlhGqIDS36a7c, created_at 2026-11-08T02:12:36.771Z. data.secret was returned and was not stored. The webhook docs, read on this run, require HTTPS on port 443 and a public host. This URL was accepted. The URL was the example.com hook, the test send was not called, and attempts were not read.
curl -X POST "https://www.socialcrawl.dev/v1/webhook-endpoints" \
-H "x-api-key: $SOCIALCRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/hooks/socialcrawl-listening-demo","types":["mention.created"],"subject_ids":["lst_m5DZU2OVQsBzbhd9p1C2U"]}'{
"credits_used": 0,
"data": {
"endpoint": {
"id": "we_kThLyRoMOlhGqIDS36a7c",
"status": "enabled",
"created_at": "2026-11-08T02:12:36.771Z"
}
}
}DELETE on that endpoint returned HTTP 200, deleted true, credits_used 0, in the same minute (02:12:36Z). No payload arrived. The listener was deleted before the next fire, so the 201 is the registration. The register steps are in register the webhook.
What did the boolean dry run read back?
The boolean call was a dry run at 02:08:08Z, HTTP 200, credits_used 0, and the listener was not created. The rule was "pour over" AND (dripper OR kettle) NOT fruit. The context was pour-over coffee equipment, not fruit. The name was pour over gear. The platform was Reddit. The schedule was every 1h.
curl -X POST "https://www.socialcrawl.dev/v1/listening/streams?dry_run=1" \
-H "x-api-key: $SOCIALCRAWL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"rule":"\"pour over\" AND (dripper OR kettle) NOT fruit","context":"pour-over coffee equipment, not fruit","platforms":["reddit"],"schedule":{"every":"1h","name":"pour over gear"}}'The read-back was Posts mentioning “pour over”, together with “dripper” or “kettle”, but not “fruit”. fetch_terms was "pour over". local was (dripper OR kettle) AND NOT fruit. The operators in this rule were AND, OR, NOT, double quotes, and brackets. The full grammar is the listening reference.
The estimate, still a dry run, was 720 credits a month, depth 720 to 2,160, slot max 3, recommended cap 2,456, and 12.96 GBP. The credit price was the same 0.006 GBP on starter_list. credits_used was 0. The screen was allowed. The lane was reddit/search, newest first, 3 pages, empty pages refunded. That flag is the lane's rule on a listener that was never created, so nothing was refunded. The response also had expected net 719. The listener that ran was the keyword body above, not this rule, and the 25.92 GBP 3-page upper figure stays on that keyword quote.
{
"credits_used": 0,
"read_back": "Posts mentioning “pour over”, together with “dripper” or “kettle”, but not “fruit”",
"fetch_terms": "\"pour over\"",
"local": "(dripper OR kettle) AND NOT fruit",
"screen": { "result": "allowed" },
"estimate": {
"credits_per_month": 720,
"depth_range_credits_per_month": [720, 2160],
"max_credits_per_slot": 3,
"recommended_max_credits_per_month": 2456,
"money_per_credit": { "amount": 0.006, "currency": "GBP", "basis": "starter_list" },
"money_per_month": { "amount": 12.96, "currency": "GBP" }
},
"lane": {
"lane": "reddit/search",
"ordering": "newest_first",
"max_pages": 3,
"empty_pages_refunded": true
}
}Which lanes refund an empty page, and which do not?
This table is the lanes page as read on 8 Nov 2026, file modified 2 Nov 2026, and it is not the pour-over listener's spend. The dry run matched the docs on the two priced lanes only, reddit/search and youtube/search/advanced. The other rows were not called. The page is which lanes refund an empty page.
| Lane | Order | Shortest every | Empty page refunded | Pages |
|---|---|---|---|---|
reddit/search | Newest first | 30m | Yes | 3 |
youtube/search/advanced | Newest first | 30m | Yes | 3 |
reddit/search/comments | Newest first | 30m | Yes | 3 |
twitter/search/tweets | Newest first | 30m | Yes | 3 |
naver/news/search | Newest first | 30m | Yes | 3 |
naver/blog/search | Top results | 1h | No | 3 |
tiktok/search | Top results | 1h | No | 1 |
facebook/search/posts | Top results | 1h | No | 2 |
threads/search | Top results | 1h | No | 1 |
linkedin/search/posts | Top results | 6h | No | 3 |
google_news/search | Time window | 1h | No | 1 |
Newest first, shortest 30m, empty page refunded, 3 pages: reddit/search, youtube/search/advanced, reddit/search/comments, twitter/search/tweets, and naver/news/search. Naver news at 30 minutes is a docs row, not this listener. This listener was Reddit and YouTube every 1h. Top results, shortest 1h, not refunded: naver/blog/search at 3 pages, tiktok/search at 1, facebook/search/posts at 2, and threads/search at 1. linkedin/search/posts is top results, 6h, not refunded, 3 pages. google_news/search is a time window, 1h, not refunded, 1 page. The lanes page says that time window is not a media-monitoring feed. Google News was not called on this run. reddit/search/comments is a row in the table. This run did not call it.
Empty-page refunded is the lanes-file mark on those newest-first rows. This run has no no_new_items line. credits_refunded was 0, and there was no second check. This listener did not receive that refund.
Account panels were not called. The reference, read on 8 Nov 2026, documents up to 300 accounts and schedule.purpose. The account-lane rows in the lanes file were also not called: newest first, 30m, empty page refunded, 2 pages, and 1 page on Threads. The lanes file has no Instagram lane.
What does this listener not do?
This post creates the listener through the API and does not show a screen. The run priced one keyword body, stored a baseline on the first check, and was deleted at 02:12:37Z. The next fire was 03:09:11Z (response field 2026-11-08T03:09:11.713Z). There was no second check. credits_refunded was 0, and there is no no_new_items line.
There is no backfill. History before the listener exists is Discover with since. The path is posts from before the listener exists. This run did not call Discover.
The mentions payload has no sentiment score, no share of voice, and no analytics rollup. The 0.85 on the sample row is a returned field. The lanes file has no Instagram lane. Listening is not real-time. The shortest interval on the docs table is 30 minutes, and this listener was every 1h. The two priced lanes have max_pages 3. The runs route was not called, so there is no per-page line.
reddit/search/comments was not called. Facebook comments and Telegram are not in the rows copied here, and this run did not call Facebook or Telegram. This post is not a guide to government, intelligence, or protest monitoring. It is not a hosted MCP wrapper. The listener was deleted before the next hour, so this one check is not a reliability measurement. People to contact are a different job. See leads from listening.
How do you start a listener and delete it before the next hour?
Price the body you would create with POST /v1/listening/streams?dry_run=1, create it with the recommended_max_credits_per_month that your own dry run returns, read mentions, and delete the listener before the next hour if you do not want the next check.
- Send the dry run with your keyword. This run's body is in the first section.
- Create with the recommended cap from that response. This run sent 4,911 because that was the cap on this quote.
- Read mentions on the id the create returned. This run used
GET /v1/listening/streams/lst_m5DZU2OVQsBzbhd9p1C2U/mentions?limit=5. - Delete before the next hour if you do not want the next check. This run deleted at 02:12:37Z. The response was HTTP 200,
credits_used0,statusdeleted,next_fire_atnull, baselineestablished, spend net 6. The confirm GET was HTTP 200 with that tombstone, not 404.
curl -X DELETE "https://www.socialcrawl.dev/v1/listening/streams/lst_m5DZU2OVQsBzbhd9p1C2U" \
-H "x-api-key: $SOCIALCRAWL_API_KEY"You send one API key in the x-api-key header. The listening overview says what a listener is. The listening quickstart has the same price, create, and read steps.
Frequently asked questions
What is social listening?
Social listening is a listener you create once for a keyword or a boolean topic. You price that body before you create it. Once each is the rule for a mention after that baseline. On 8 Nov 2026 the first check stored a baseline. This run did not show a later delivery.
How much did this listener cost before it was created?
The dry run cost 0 credits to ask. It quoted 2 credits an hour, credits_per_month 1,440, a depth range of 1,440 to 4,320, each platform 720 credits a month, a recommended cap of 4,911, and 25.92 GBP as the 3-page upper figure at 0.006 GBP per credit on starter_list, for Reddit and YouTube every 1h. The create response had credits_used 0. The finished first check, month 2026-11, showed spend gross 6, refunded 0, net 6.
Does the first check send old posts?
Create came back with baseline establishing, and after the check the listener was baseline established. All five mentions on the page had baseline true and were readable on the mentions route. This run did not show a later delivery. The events read does not prove the check wrote no mention.created events.
Does a social listening API include sentiment, a dashboard, or real-time results?
The mentions payload has no sentiment score, no share of voice, and no analytics rollup. This post creates the listener through the API and does not show a screen. It is not real-time. The shortest interval on the docs table is 30 minutes, and this listener was every 1h. The lanes file has no Instagram lane. History before the listener exists is Discover with since. The two priced lanes have max_pages 3. This run's credits_refunded was 0. This is not a guide to government, intelligence, or protest monitoring.
Why did the events read return zero rows?
The call used consumer blog-listening-demo, types mention.created, and start=now, at 02:10:58Z, and it returned 0 rows with empty_reason no_matches. That was about 100 seconds after the check, so it does not prove the check wrote no mention.created events. The webhook returned HTTP 201 and was deleted in the same minute. The secret was not stored. The test send was not called. Attempts were not read. No payload arrived.
Related posts
An AI Report From Social Media Data
A PDF, Word file, or Markdown report from fetched social rows starts at 50 credits, plus 50 per image. A PNG is 50 credits. Generate shows the price first.
Analyze Social Media Data With AI
A 1-credit hold comes before a Reddit coffee search runs. Approve the plan, then sort, filter, chart, and export the rows. The dry run used 0 credits.
Twitter Analytics Tools: 0.57% Median ER
0.57% is the median engagement rate on 363 original posts from 20 public X accounts on 6 November 2026. The rate uses likes, comments, and shares over views.
