---
title: "Read cohort query results"
method: GET
path: "/cohort-queries/{queryId}/results"
tags: ["cohorts"]
---

# Read cohort query results

`GET /cohort-queries/{queryId}/results`

## Request

- Base URL: `https://www.socialcrawl.dev/v1`
- URL: `https://www.socialcrawl.dev/v1/cohort-queries/{queryId}/results`
- Auth: API key in header `x-api-key`

Returns cursor-paginated keyword matches plus per-member coverage. Matching is deterministic: Unicode NFKC normalization, locale-independent case folding, whitespace collapse, then whole-word matching at Unicode word boundaries (`acme` matches `#acme` but not `acmecorp`; scripts without word delimiters, such as CJK, effectively require exact token matches). Matched keywords are echoed in their normalized form. On YouTube and Twitch the matched text covers the title and the description. A keyword query does no stemming, fuzzy matching, or semantic expansion. A query submitted with `topics` and `match` of `topics` or `both` also checks items against your topic descriptions and adds `matched_topics` and `mention_type` to each item. The response carries the standard `pagination` block (send `pagination.next_cursor` back as `cursor`) and a `dropped` counter, and the raw `data.next_cursor` is accepted as well.

## Path parameters

- `queryId` string, required

## Query parameters

- `cursor` string
- `limit` integer

## Response `200`

Cohort query results page

- object
  - `cached` boolean
  - `credits_remaining` integer, nullable
  - `credits_used` integer
  - `data` object
    - `coverage` object[]: One record per cohort member, whether or not it matched. `window_complete` is true only when the route reached the requested time boundary or an end-of-feed marker; a page budget, timeout, or error leaves it false.
      - `external_id` string, nullable
      - `member_id` string
      - `oldest_seen` string, date-time, nullable
      - `pages` integer
      - `platform` string
      - `query_id` string
      - `route_errors` object[]
        - `code` string
        - `route` string
      - `status` 'complete' | 'partial' | 'not_found' | 'unsupported' | 'failed'
      - `window_complete` boolean
    - `items` object[]
      - `canonical_url` string, nullable
      - `content_id` string
      - `external_id` string, nullable: Your own opaque identifier for this panel member.
      - `matched_keywords` string[]: The normalized keywords found in the item. Empty only on a `match: "both"` query, for an item that a topic matched and no keyword did.
      - `matched_topics` object[], nullable: Topic queries only (absent on a keyword query). The topics this item is about, strongest first: your topic `id` and `p`, the probability from 0 to 1 that the item is about that topic (only topics at 0.7 or above are listed). An empty array means the item was checked and is about none of your topics. `null` means the item could not be checked and stands on its keyword match alone.
        - `id` string, required
        - `p` number, required
      - `member_id` string
      - `mention_type` 'first_hand_use_or_purchase' | 'opinion_or_review' | 'sponsored_or_promotional' | 'news_or_share' | 'incidental' | 'other' | 'uncertain' | 'null', nullable: Topic queries only (absent on a keyword query). How the author relates to the matched topic. `uncertain` means no option was a clear winner. `null` means the item was not checked, or matched no topic.
      - `platform` string
      - `published_at` string, date-time
      - `query_id` string
      - `retrieved_at` string, date-time
      - `route` string
      - `text_excerpt` string
    - `next_cursor` string, nullable: Opaque signed cursor for the next page, or null on the last page. Pages are additionally bounded so the serialized body never exceeds 1 MB.
  - `endpoint` string
  - `platform` string
  - `request_id` string
  - `success` boolean

## Other responses

- `400`: Invalid request - missing or malformed parameters
- `401`: Unauthorized - missing or invalid API key
- `404`: Not found - the endpoint does not exist, or the requested resource was not found upstream
- `405`: Method not allowed - wrong HTTP verb for this endpoint
- `409`: Conflict - an idempotent request is still in flight, its completed body exceeded the replay limit, or the cohort resource is not in a state that allows this operation
- `413`: Payload too large: the JSON request body exceeds the 1 MB size limit and is rejected before parsing, or a single cohort result cannot fit beneath the 1 MB response-page ceiling
- `429`: Rate or concurrency limit exceeded. `RATE_LIMITED`: more than 600 requests in a 1-minute sliding window on this API key (headers `X-RateLimit-Limit`/`Remaining`/`Reset`; `Retry-After` is seconds until the window resets). `CONCURRENCY_LIMIT`: more than 50 simultaneous in-flight requests (headers `X-Concurrency-Limit`/`Remaining`; short static `Retry-After`). Both are unbilled. Honor `Retry-After`, then back off with jitter. See /docs/rate-limits.
- `500`: Internal server error - an immediate refund is attempted; credits_used reports the committed net charge and exact compensation is queued if that refund cannot commit

---

[API](https://skmtc.dev/socialcrawl/apis/socialcrawl-api.md) · [All operations](https://skmtc.dev/socialcrawl/apis/socialcrawl-api/llms.txt) · [OpenAPI document](https://skmtc.dev/socialcrawl/apis/socialcrawl-api/revisions/a0ad2511004a?raw)
