---
name: sippar-social-data
description: Get social media data for an app without signing up for any platform. Use when a developer needs what people are posting on Reddit, YouTube, LinkedIn or X: "what are people saying about my product", "pull Reddit threads about X", "get YouTube comments on this video", "find LinkedIn posts about Y", competitor monitoring, launch reaction, review mining, or any app feature that needs social data. Every platform is paid per call from a wallet, so there is no signup, no API key, no contract and no subscription on any of them. Triggers: social media data, social listening, what are people saying, X, Twitter, Reddit, YouTube comments, LinkedIn posts, competitor monitoring, launch reaction, sentiment, discourse, no API key, pay per call.
version: 0.6.0
author: Sippar
updated: 2026-09-07
---

# sippar-social-data

**The wall this exists for.** A developer building an app needs social data. X caps and meters the
account. Reddit will not sell at any published price, it wants permission and a signed contract.
LinkedIn has no API for this at all. Four platforms, four signup walls, and every one of them
demands a human with a card. Their AI assistant cannot sign up for any of it.

This skill buys the same data per call. No account on any platform, no key in your environment,
no contract, no subscription. You pay for the calls you make.

> **Companion skills.** `sippar-enrich` is the same shape for company, property, web, market and
> grounded-search data. `sippar-x402` is the payment rail itself: read it if you need the wallet,
> the sessions, or to pay something that is not on this shelf.

## What you buy

One product, `social-search`. One question in, one cited answer out, in a single call. It covers
Reddit, YouTube and LinkedIn, and it returns Sippar's own cited answer plus links to the posts
rather than the posts themselves. Follow the citations to read them at the source.

Coverage is best-effort and point-in-time. A platform with nothing to say is reported as such
rather than dropped.

You also get per-platform counts and a `relevance` block that says whether the rows are actually
about the thing you named. If no written answer clears Sippar's citation and faithfulness checks,
the call still returns 200 with `answer: null` and the real citations, rather than charging you for
a paragraph that did not earn its claims.

**Never hardcode a price.** The price and the input shape live in the catalog, and this file does
not carry them:

```bash
curl https://sippar.network/mcp/tools/pay/products/social-search
```

**Discord cannot be bought.** It is not sold by any x402 service, and saying so is more useful than
substituting something else. If the user needs Discord, tell them it is not purchasable here.

### There is a web page, and it is not this. Do not drive it.

`https://sippar.network/social/` runs the same idea as a human interface. **It is not the machine
path and an agent should never operate it.** It is a browser app with a wallet-connect flow and a
prepaid pack door, so scripting it means driving a UI to reach something sold as one HTTP call.
The page's own `<head>` now says this, and `https://sippar.network/social/social-capabilities.json`
carries a `machinePath` block pointing back here.

**The page offers more than the product does, and that gap is real rather than a documentation
lag.** Anyone who has watched the page and then read this file will notice it, so it is written
down instead of left to be rediscovered:

| The page | `social-search` |
|---|---|
| Several platform families (phrase, account, post, trending, ads, brand watch) across ten or more platforms | Reddit, YouTube and LinkedIn, phrase search only |
| A time window and sort options per platform, and platform selection | A time window and platform selection, both optional. No sort parameter |
| A "where to reply" worklist ranked out of the same run | Not exposed |
| An audio brief and a deeper report, bought out of page credit | Not purchasable per call |
| Relevance reporting on the rows | Same, in the `relevance` block |

**Deliberate**: the platform families and the report add-ons. The wide capability map is what the
page pays for on a human's behalf out of its own credit, and the add-ons are priced against that
credit rather than against a wallet, so neither has a per-call product behind it today. Selling
them per call is a pricing and packaging decision, not a plumbing one.

**Closed on 2026-09-07**: the time window and platform selection. Both are now optional inputs on
the product. See "Narrowing the search" below for what they do and what they cost, which is
nothing.

**Still open, and not deliberate**: sort order, and the "where to reply" worklist. Neither is
reachable per call.

**What you can honestly promise from the machine path today**: one question, up to three platforms,
one cited answer plus links, an optional time window that each platform reports back, best effort.
That is the whole of it.

### Narrowing the search

Two optional inputs sit alongside the question. Read their exact names and accepted values from the
catalog with the rest of the input shape, the same way you read the price; this file does not carry
them.

**Which platforms to search.** Omit it and every platform runs, which is the default. Name a subset
and only those are bought.

**The price does not change when you narrow.** One call is one price whether it covers one platform
or all of them, so selecting fewer buys a narrower answer for the same money rather than a cheaper
one. Do not tell a user that picking one platform saves them anything. Narrowing also makes an
empty result more likely, and an empty result is charged like any other.

**How far back to search.** Omit it and each platform keeps the window it has always used. That is
NOT an all-time sweep, and the difference has misled people: the Reddit leg is pinned to the last
month, and the other platforms take whatever their supplier defaults to. A topic that peaked three
months ago can come back thin on Reddit for that reason alone.

**Every platform now reports the window it actually searched**, in a `window` block beside its row
count. Read it rather than assuming: it names the window that was requested, the one that was
applied, the exact parameter sent upstream, and whether the platform could honour the request. Two
of the suppliers publish no all-time option at all, so asking for everything is reported as not
honoured on those platforms instead of being quietly ignored. Carry that into whatever you tell the
user, the same way you carry the row counts.

**Do not fake a window by stuffing "last week" into the query text.** The keyword legs treat those
words as search terms and the match gets worse, not narrower. The parameter exists now; use it.

## Buying: the MCP is the path

Two calls. The first answers with a real **HTTP 402** carrying `payTo`, the exact amount and the
rails. The second replays the same request with the payment credential. **Your wallet pays and
Sippar is the payee.**

An x402 client handles both calls for you, because this is an ordinary 402 resource: the status is
402, and `x402Version` and `accepts[]` are at the top level of the body where a client looks for
them. Nothing Sippar-specific has to be written to pay it.

```bash
# 1. Ask
curl -X POST https://sippar.network/mcp/tools/pay/buy \
  -H 'Content-Type: application/json' \
  -d '{"productId":"social-search","input":{"query":"what are people saying about Cursor"}}'

# 2. Pay the challenge from your wallet, then repeat with the credential
curl -X POST https://sippar.network/mcp/tools/pay/buy \
  -H 'Content-Type: application/json' \
  -H 'X-PAYMENT: <base tx hash | solana signature | base64 x402 v2 payload>' \
  -d '{"productId":"social-search","input":{"query":"what are people saying about Cursor"}}'
```

Rails: USDC on Base, USDC on Solana, and USDC.e over Tempo MPP. For the MPP rail, send the
credential from the `WWW-Authenticate` challenge as `Authorization: Payment <credential>` instead of
`X-PAYMENT`.

This route needs **no API key**, and since #2353 neither does the JSON-RPC door. An MCP client that
speaks JSON-RPC can call the same thing as the `buy_product` tool on
`https://sippar.network/mcp/protocol/pay`, and `buy_product` is one of the thirteen tools that
`tools/call` now serves without a credential. Five stay keyed (`transfer`, `session_draw`,
`relay_pay`, `batch_pay`, `pay_paysh_service`) on one rule: a tool stays keyed when the caller
names both whose wallet pays and who gets paid. Buying a product names neither. See `sippar-x402`
section 1 and `docs/security/2026-08-28_MCP_PAY_AUTH_GATE_REVIEW.md`.

Prefer the REST route above anyway: it answers a real 402, which is the thing an x402 client
already knows how to pay.

**The JSON-RPC door answers 200, not 402.** JSON-RPC carries its outcome in the body and has no
status code to spend, so an unpaid `buy_product` comes back as a tool result with
`data.paymentRequired: true` and the challenge at `data.challenge`. That is the one place the two
doors differ, and it is why an autonomous x402 client should use the REST route above.

**The query bounds**: at least 3 characters, at most 500. A brand name works best. A broad topic
phrase returns rows that may be about something else, which the `relevance` block reports rather
than hides.

### It is slow on purpose, so set your timeout before you pay

This call fans out across several platforms and then writes an answer over what comes back. It
usually takes over a minute. The 402 publishes the bounds it promises in
`collect.expectedLatencySeconds`, so read them rather than guessing: a 30-second client timeout is
not enough, and a client that gives up early looks exactly like a service that ate the money. That
is not hypothetical. It happened to a real buyer on 2026-08-27, twice in one sitting, for one
question (#2288).

### If it times out, do not pay again

One payment buys one delivery, and that delivery can be collected more than once. Re-send the SAME
payment header, to whichever door you used, and you are served the same result at no further
charge. While the first call is still running you get a 409 telling you to come back; once it
finishes you get the result with `redelivered: true`. Collecting never verifies a payment and never
charges.

A second payment for a question you already bought is refused rather than taken, so that money
stays yours to spend on something else. Send `"allowDuplicate": true` if you genuinely want a fresh
run of the same question.

Everything a program needs is in the `collect` block of the 402, on either door. Read it there;
this file does not carry the field values, the same way it does not carry the price.

**Two escapes exist on the plain HTTP endpoint below, and not yet on the MCP door.** Sending
`Prefer: respond-async` with the payment returns an immediate 202 carrying the settlement key and a
collect URL, and `POST /api/sippar/sell/social-search/collect` fetches a result for free with the
same payment header. Neither is plumbed through `/mcp/tools/pay/buy` yet, and that hop aborts its
own request at 130 seconds, which is below this product's declared maximum. So for a run you expect
to be slow, either use the plain endpoint, or expect to collect through the MCP door by
re-presenting your payment. Tracked as #2311.

**A program does not have to read this file to get that right.** Since 2026-09-07 the same
statement rides the machine-readable surfaces, in fields rather than prose: the 402's `collect`
block carries `preferredEndpoint` (with the MCP doors under `avoid`, each saying what it cannot do
and where it aborts) for any product whose `collect.asyncHandle.recommended` is true,
`/.well-known/x402` qualifies the doors it names under `related.buyEndpointLimits`, and
`https://sippar.network/social/social-capabilities.json` carries `machinePath.doors` with one entry
marked `preferred`. All three are derived from the product's own measured latency, so none of them
is a list anyone has to maintain. The MCP hop's own 402 splats that `collect` block to the top
level, which means a client standing at the wrong door reads the warning before it pays.

### The plain endpoint, which is the right door for THIS product

The product is also its own plain HTTP endpoint. Same payment, same rails, same result.

For most products this is the fallback for a caller with no MCP client. For `social-search` it is
the better door outright, and `listen.sh` uses it deliberately: this is the only place
`Prefer: respond-async` and the free `collect` re-presentation both work, and a product that
routinely runs over a minute against an MCP hop that aborts at 130 seconds needs both.

```bash
curl -s -X POST https://sippar.network/api/sippar/sell/social-search \
  -H 'Content-Type: application/json' \
  -d '{"query":"what are people saying about Cursor"}'
```

That answers 402 with payment instructions on Base, Solana and Tempo. Pay from your own wallet and
retry with the header it names. The endpoint URL comes from the catalog's `url` field, never from
memory.

The same collect contract applies, and this is the door where both escapes work: `Prefer:
respond-async` for a 202 and a settlement key instead of a held-open socket, and
`POST /api/sippar/sell/social-search/collect` with the same payment header to fetch a finished
result for free.

---

## The two scripts, and which side of the payment line each one is on

Two scripts ship with this skill. Since 2026-08-31 they sit on opposite sides of the money, and
that is the first thing to know about them.

| Script | Who pays | Who can run it |
|---|---|---|
| `listen.sh` | the **caller's** wallet, Sippar is the payee | anyone, Sippar included |
| `comments.sh` | Sippar's treasury, credential required | Sippar only |

### `listen.sh`: Sippar's own run and a customer's run are now the same request

`listen.sh` buys the `social-search` product described above. It does not fan out across suppliers
and it does not spend Sippar's money. That makes it the one script here worth handing to a stranger,
and it makes Sippar dogfooding this skill genuinely the same code path a customer uses.

```bash
cd scripts

./listen.sh "what are people saying about Cursor"     # asks, prints the real 402, spends nothing
./listen.sh --payment <base tx hash> "..."            # pays and collects
./listen.sh --mpp <credential> "..."                  # same, on the Tempo MPP rail
./listen.sh --collect <the same key>                  # re-collect something already bought, free
./listen.sh --json ...                                # raw JSON instead of the rendered answer
./listen.sh --allow-duplicate --payment <key> "..."   # deliberately re-run a question already bought
```

**Running it with no `--payment` is the dry run.** It asks the endpoint, prints the live 402 with the
live price and every rail on offer, and stops. There is no separate `--dry-run` flag any more,
because the free ask is more honest than a printed estimate: it is the actual challenge you will pay.

**The script reads the price; it never carries one.** The endpoint URL, the price, the collect URL
and the latency bounds all come from `GET /api/sippar/sell/catalog` at run time, and the 402
confirms the price again before anything is paid.

**Which door it uses, and why that is not the MCP one.** The product is buyable two ways:

```
POST /api/sippar/sell/social-search   <- listen.sh uses this
POST /mcp/tools/pay/buy               with {"productId":"social-search","input":{...}}
```

Same product, same price. The MCP hop aborts its own request at 130 seconds (#2311) while this
product's declared maximum is 300, so a slow run there is charged and then answered 502 with nothing
to collect against. That hop also has no collect verb, so neither escape from a slow run is reachable
through it. The plain endpoint is where `Prefer: respond-async` and the free `collect`
re-presentation both work, and a call that typically takes over a minute needs both. `listen.sh`
therefore pays with `Prefer: respond-async`, holds the settlement key, and collects. Use the MCP door
from an MCP client for a product that answers fast; use this one for this product.

**A refused duplicate is not an error.** Pay twice for the same question inside the duplicate window
and the second payment is **refused, not taken**: the money is still yours to present for something
else. The script says exactly that and offers the two real moves, which are collecting what you
already bought or passing `--allow-duplicate` for a genuine re-run. Do not paper over it as a
failure and do not retry around it.

**If your client gives up, do not pay again.** One payment buys one delivery and that delivery is
held for a week. `./listen.sh --collect <the same key>` fetches it for free. A client that times out
looks exactly like a service that ate the money, and that has happened to a real buyer, twice in one
sitting, for one question (#2288).

### `comments.sh` is internal, and there is no caller-pays version of it yet

`comments.sh` reads the comments on one YouTube video. Sippar does not sell that as a product, so
there is nothing here a caller's own wallet can buy, and the only route left is Sippar's treasury
paying a supplier on someone's behalf through the **authenticated** endpoint:

```bash
SIPPAR_ACCESS=<token> ./comments.sh "https://www.youtube.com/watch?v=..."
./comments.sh --dry-run "https://..."
```

Without a credential it refuses immediately and explains why, rather than spending a round trip to
discover it cannot work. It prints a **ceiling**, not a price: the supplier's own 402 sets the cost
and the receipt reports what was actually paid.

If you need this capability for someone outside Sippar, the answer is to make it a product, not to
find another way to spend the treasury on their behalf.

### Which endpoint, and who pays on each one

Read this before choosing a path. The difference between the rows is not convenience, it is whose
money moves.

| Endpoint | Credential | Who pays | State |
|---|---|---|---|
| `POST /mcp/tools/pay/buy` | none | **the caller** | live. A real 402, so an x402 client pays it unaided |
| `POST /api/sippar/sell/social-search` | none | **the caller** | live. The door where async and collect both work |
| `POST /mcp/tools/pay/pay` | none | Sippar's treasury | **SHUT since 2026-08-31** for treasury-funded calls |
| `POST /api/sippar/agent/pay` | `X-Sippar-Access` | Sippar's treasury | live, internal only |

**The public treasury hop is closed, not merely discouraged.** `AGENT_PAY_PUBLIC_DAILY_USD=0` on
production, and a treasury-funded call answers 402: *"Sippar no longer funds calls on this public
endpoint from its own treasury."* Verified live 2026-09-01. It is also visible from the outside on
`GET /api/sippar/social-beta/packs`, which reports `freeLane: {"enabled": false}`. If you find a
Sippar surface still pointing at it, that surface is broken and the fix is to move it to one of the
two caller-pays rows, not to reopen the lane.

**One thing still passes that hop, and it is not a way back in.** A call covered by an ENERGY hold
goes through, because energy is usage a sponsor or a human already paid for and refusing it would
mean keeping money Sippar took. Nothing in this skill has an energy hold, so for everything here the
hop refuses.

**The two treasury rows were never a cheaper version of the first two.** They are Sippar paying
suppliers on someone else's behalf: every such call spent Sippar's own money and collected nothing.
That is why the public one is gone, and why the remaining one is credential-gated.

### What these scripts used to do, and why it went

Until 2026-08-31, `listen.sh` bought four supplier legs directly (an X/grok leg via Locus, Reddit
from glim.sh, YouTube and LinkedIn from stablesocial.dev) and paid every one of them through the
public treasury hop. Two things ended that at once.

**The lane shut.** With the hop closed, every leg 402s. The script was broken outright, not degraded.

**The duplication was already costing money.** That leg table was a copy of `LEGS` in
`src/backend/src/services/socialStorefrontService.ts`, and it drifted: the script bought Reddit at
6x the engine's price with no fallback for twelve days, and because this skill is published verbatim
at `https://sippar.network/skills/sippar-social-data/`, a customer's agent read the dearer table too
(#2332). A test held the two tables together after that. Buying the product instead removes the
second table entirely, which is the better fix: there is now one supplier table in the repo and the
engine owns it.

**What was lost, said plainly.** The X leg and the `--only <platform>` selector are gone, because
neither exists on the caller-pays side. `social-search` is one call over Reddit, YouTube and
LinkedIn. If X matters, it has to become a leg of the product first, in `LEGS`, where the engine can
price and attest it. Adding it back to a shell script would rebuild exactly the duplication that
just cost a customer money.

### Adding a platform or an endpoint: docs first, always

A platform is added to the **product**, not to a script. `LEGS` in
`src/backend/src/services/socialStorefrontService.ts` is the one supplier table in this repo, and it
is deliberately the only one: the last time a shell script carried a second copy, it drifted and a
customer's agent overpaid on every Reddit call for twelve days (#2332). If you find yourself writing
a supplier URL into a `.sh` file, that is the mistake, not the shortcut.

To find what a supplier sells:

```bash
npx agentcash@latest discover https://stablesocial.dev     # what exists, with prices, free
npx agentcash@latest check <endpoint-url>                  # the exact request schema, free
```

Both are free reads. `agentcash fetch` is a different matter: it pays the supplier directly and puts
Sippar outside its own payment, so it is not how a leg gets bought.

**Run `check` before you add a leg, every time.** It returns the required fields and it is free. A
guessed field name costs a real payment for a 400 that tells you nothing. This is not a style
preference, it is the rule, and skipping it has cost real money more than once.

Two traps worth knowing before you go looking:

- **Some routes are asynchronous.** The non-`sc/` Data365 routes (`/api/reddit/search`,
  `/api/tiktok/*`, `/api/instagram/*`) return a `jobId` and a `pollUrl`, and polling needs a signed
  request from the wallet that paid. The `sc/*` routes return data directly, which is why the routes
  in use are `sc/` ones. Prefer them.
- **A published example value is not a guaranteed-valid value.** Suppliers sometimes advertise a
  parameter their own API rejects. Send the required fields and leave optional ones out unless the
  user asked for them.

**A new upstream is a redistribution question before it is a code question.** Before any supplier is
wired into a paid Sippar surface, its terms get checked and the verdict recorded. That rule has
already refused suppliers. Do not skip it because a leg looks like a drop-in.

---

## Reading the result honestly

The value here is that it sees real posts. The failure mode is treating a thin result as a trend:
the output reads equally confident whether it found forty posts or four.

- **Say how much evidence there was.** "Three posts, all in one thread" is a different claim from
  "sixty posts across twenty subreddits". Carry the count into whatever you tell the user.
- **Say which platforms actually returned something.** The `platforms` block reports a platform that
  came back empty rather than dropping it, so a sweep that covered one platform can be described as
  one platform. If LinkedIn returned nothing, do not let the Reddit rows speak for it.
- **`answer: null` with real citations is a pass, not a failure.** The product returns nothing
  rather than charging for a paragraph that failed its own faithfulness check. Report the citations.
- **Platforms are biased differently, and that is useful.** Reddit is structured and blunt. LinkedIn
  is chronological and professional. YouTube comments are the least filtered. Disagreement between
  them is a finding, not noise to average away.
- **X is not covered.** The product spans Reddit, YouTube and LinkedIn. If someone needs X, say it
  is not in this product rather than letting three platforms stand for four.
- **Provenance, if asked.** The LinkedIn leg uses a scraping-based supplier. Disclose that when it
  comes up rather than letting the whole result read as licensed.

## Cost discipline

Every paid call spends real money, and on `listen.sh` it is the caller's money.

1. **Ask first.** `./listen.sh "<question>"` with no `--payment` returns the live 402 with the live
   price and spends nothing. Do that before agreeing to a run.
2. **Never loop, and never re-pay.** One payment buys one delivery, held for a week. If a call
   appears to fail after payment, collect it with the same key. Paying again for the same question
   is refused rather than taken, which is a safety net and not a workflow.
3. **Ask before a sweep.** Several questions is several times the price. Read the ask output before
   agreeing to a batch.