SocialCrawl
Listening

Reference

Every listener route, body field, mentions filter, refused name and error on one page

This page lists everything a listener takes and returns. To get started, read the overview and run the quickstart first.

cURL
curl "https://www.socialcrawl.dev/v1/listening/streams?status=active" \
  -H "x-api-key: YOUR_API_KEY"

Routes

RouteWhat it does
POST /v1/listening/streams?dry_run=1Prices and checks a listener body. Costs 0 credits and creates nothing
POST /v1/listening/streamsCreates a listener
GET /v1/listening/streamsLists your listeners, filtered by status, name or client
GET /v1/listening/streams/{id}Reads one listener
PATCH /v1/listening/streams/{id}Changes a listener
POST /v1/listening/streams/{id}/pausePauses a listener
POST /v1/listening/streams/{id}/resumeResumes a listener
DELETE /v1/listening/streams/{id}Deletes a listener
GET /v1/listening/streams/{id}/mentionsReads the mentions a listener kept
GET /v1/listening/streams/{id}/runsReads a listener's checks: what each one read, kept, billed and refunded
POST /v1/listening/previewRuns a listener body once and shows what its first check would keep. Billed like the same API calls. A preview of several pages can take 20 seconds or more, so set a client timeout of at least 60 seconds
GET /v1/listening/usageCredits and checks per client, listener, group or platform, as JSON or CSV

New mentions also arrive as mention.created events on the events feed (GET /v1/events) and as signed pushes to your webhook endpoints. Every write (create, change, pause, resume, delete, preview) takes an Idempotency-Key header (idempotency). There is no estimate route: the dry run is the estimate.

Listener body

The create, the dry run, the preview and a change all take this body. Send exactly one of keywords, rule, groups or, for an account panel, accounts.

FieldWhat it doesDefault
keywordsOne group whose keywords are its searches, each matched as written. A keyword of several words is searched as a quoted phrase. At most 100 keywords of 500 characters each
ruleOne group as boolean text: AND, OR, NOT, "quoted phrases" and brackets, up to 2,000 characters
groupsSeveral topics in one listener, at most 500. Each has a unique id and a rule or keywords, and can set its own context, exclude_terms, platforms, languages, country and tags
accountsAn account panel: up to 300 accounts, each platform:handle (reddit:nasa, youtube:@NASA) or a profile URL. Needs a topic and schedule.purpose
author_list_idIn place of accounts: the id of a list stored with POST /v1/prism/discover/inputs, read once when the listener is created
platformsThe platforms to watch. Google News is news, and x is accepted for twitter (lanes)
search_inWhat to search on each platform: posts, comments on Reddit, blog and news on Naverposts
contextWhat kept posts must be about, naming the sense of an ambiguous keyword. 3 to 2,000 characters
scheduleHow often the listener checks, its caps and its name. Required (below)
languagesISO 639-1 codes. A post whose language is unknown is kept
countryISO 3166-1 codes of the posts or authors to keep
exclude_countryISO 3166-1 codes of the posts or authors to drop
unknown_countrykeep or drop a post whose country is unknown when country or exclude_country is setkeep
exclude_termsDrops posts that contain any of these terms
excludeAccount keys (<platform>:<id>) or evidence ids to drop
sponsoredexclude drops posts marked as ads or paid partnerships, only keeps only those, keep turns the filter offexclude
relevancefilter drops posts the relevance check rejects, score keeps every match with its score, off does not check. The check is included in the pricefilter
relevance_definitionmentions keeps posts that name the topic, about keeps posts mainly about itmentions
commentsnew_posts also reads the comments under each post the listener newly keeps, on Reddit (lanes)off
metadataUp to 20 string labels for your own use, returned unchanged. client groups usage
drafttrue saves the listener without running itfalse
new_listenertrue creates a second listener even when an identical one existsfalse

Schedule

FieldWhat it doesDefault
everyHow often the listener checks: 30m, 1h, 3h, 6h, 1d or 7d. 30m works only when every chosen platform is read newest first
max_credits_per_monthThe monthly cap in credits. A check that would pass it does not run, and the listener pauses until the next UTC month or a higher cap. An account panel can pass it by the second pages of one check (pricing). Required on a create made with an API key. A dry run without it still answers and recommends one
max_credits_per_runThe most one check may spenddata.estimate.max_credits_per_slot
nameThe listener's name, up to 120 characters
purposeRequired on an account panel: business, brand, creator or organisation
start_atWhen the first check fires instead of at create, at most 90 days ahead

An account holds up to 50 listeners. Schedules and months are in UTC.

Mentions route

GET /v1/listening/streams/{id}/mentions takes these filters. Pages are read with cursor: send the pagination.next_cursor of the page before until pagination.has_more is false.

FilterWhat it keeps
since, untilPosts published at or after, or before, this time
seen_since, seen_untilPosts the listener first saw at or after, or before, this time
groupMentions of this group id. A group a change removed still reads for the 30-day keep. An id the listener never had answers a free 400 with allowed_values
tag.{key}Mentions of groups with this tag, for example tag.client=client-b
platformMentions from this platform. x works as twitter. A name no listener can watch answers a free 400 with allowed_values
languagePosts in this language code. See the note below the table
record_typepost or comment
parent_idThe comments under the post with this evidence.id
judgment_statusjudged, pending or unjudged
limit1 to 500 per page, 100 by default
formatevidence (every field), compact or text
includeraw adds the platform's original item as evidence.raw

A language filter is checked after each mention is opened, and a request scans at most 2,000 stored mentions. A page can therefore come back short, or empty, with pagination.has_more set to true. Keep paging with pagination.next_cursor while has_more is true, even when a page is short or empty.

Mentions page in the order they were stored: the oldest check first and, inside a check, the order the platform returned its posts. data.dropped counts list items the response check removed because they did not match the documented shape. It is not a count of posts the relevance judge dropped, so it can be 0 when a check's dropped on the runs route is not.

Names a listener does not take

These names answer a 400 not_offered, with docs_url pointing here and, where one exists, did_you_mean. Nothing is charged.

Name sentSend instead
queryrule: a listener's boolean text. Discover's query is one phrase sent as written.
rulesgroups, each with an id and a rule or keywords
refresh_interval_minutesschedule.every
budgetschedule.max_credits_per_month: divide a money budget by money_per_credit (pricing)
match_inNothing: a listener matches a post's title and text together
delivery.endpoint_idssubject_ids on a webhook endpoint
stream_idsubject_id on the events feed and webhook endpoints
stream_idssubject_ids on the events feed and webhook endpoints
threadsNothing: new comments of a known post are a Monitor with webhook_rows: "new"
from: (in a rule)accounts: an account panel of the accounts whose posts you want

label, questions, sentiment and tz are not available yet and answer not_released. A listener's slots and months are UTC.

Errors

Each refusal is free and carries details.reason, details.fields and details.next_step. Change the field it names rather than retrying.

details.reasonStatusWhat to doReference
invalid_param400Send the field or value in did_you_mean, allowed_values or suggested_valueINVALID_REQUEST
conflicting_params400Drop one of the fields in details.fieldsINVALID_REQUEST
not_released400Drop the field, value or routeINVALID_REQUEST
not_offered400Send the name in did_you_mean, or drop it (table above)INVALID_REQUEST
interval_below_lane_minimum400Pick an every from allowed_values, or drop the platform whose lane details.lane namesINVALID_REQUEST
unsupported_operator400Use the rule in nearestINVALID_REQUEST
plan_limit400Send fewer groups, search terms or accounts, within limitINVALID_REQUEST
budget_below_one_check400Ask the user to approve suggested_value, then send it in fieldINVALID_REQUEST
prohibited_use400Do not rephrase to pass. A dry run reports the verdict in data.screen instead; a create or a change refuses itINVALID_REQUEST
unknown_stream404The listener belongs to another key or does not exist. List your key's listenersSTREAM_NOT_FOUND
stream_deleted, resume_from_dashboard409Create a new listener. A listener stopped on a revoked key cannot be resumed with an API key, so create a new one with an active keySTREAM_STATE_CONFLICT
judge_unavailable503Retry after Retry-After. A dry run never answers it: when the use screen cannot run, data.screen.result is unavailableSERVICE_UNAVAILABLE

A few answers are not refusals of the body:

  • 402 INSUFFICIENT_CREDITS or KEY_BUDGET_EXCEEDED on a preview whose first page the balance or the key's credit limit cannot pay. A listener's own checks never answer a 402: a check the balance cannot pay pauses the listener instead.
  • 413 payload_too_large for a body over the size limit. Split the groups across several listeners (PAYLOAD_TOO_LARGE).
  • 503 store_unavailable or store_timeout when the listener store does not answer in time. Nothing is charged; retry the same call after Retry-After (SERVICE_UNAVAILABLE).
  • The Idempotency-Key answers on a write: a reused key with a different body, or a request still in progress (idempotency).

What does the use screen check?

The use screen checks what you declare in each group's rule or keywords and in context against the uses the Terms of Service section 7.2 forbid: monitoring a named private individual, a protest group or its organisers, or government or intelligence monitoring of people. On an account panel its word list also reads each entry, and schedule.purpose records what the panel watches. On a dry run it returns its verdict in data.screen with a warning and creates nothing either way. A create or a change that declares such a use is refused with prohibited_use, and so is a preview. The screen records what you declare and refuses declared uses; it is not a check of what a listener is later used for.

On this page