STEALCONTENT

Reference

API reference

Every documented endpoint, its parameters and what comes back. Pick a language once at the top and every example on the page follows you.

Getting started

There is nothing to install and nothing to sign up for. Every endpoint below is a GET you can paste into a browser, except the MCP server, which is a POST because it speaks JSON-RPC. Responses are JSON with no envelope: the fields named under Returns are the top-level keys.

Authentication

Reading is open. A key is for volume and for one gated field: without one, a post's mirrored video, carousel or PDF comes back as a null url with locked set to true, while the kinds and dimensions ship either way so a client can still lay out the right shape of panel. Keys go on the Authorization header as a Bearer token, and the samples read one from an environment variable rather than putting it in a file.

GET/api/posts

Page the library

The whole corpus, filtered and paged, exactly as the library page reads it. Every post carries its engagement AND its outlier multiple, which is how far it beat that author's own median. Rank on the multiple: raw reactions only find accounts with big followings, and a 200-reaction post from somebody who averages 30 is the one worth stealing from.

dataset
The vertical corpus slug. Every list endpoint takes this and means it.
q
Words that must appear in the post text.
author
One account's handle, matched case-insensitively.
platform
linkedin | x | youtube | tiktok | instagram | threads | substack
format
text | image | carousel | video | poll | document | repost
hook
The named opening move: contrarian, story, number, question, listicle, confession, announcement, how-to, callout. Lowercase-hyphenated, permanently.
topic
One topic tag from the describe pass, lowercase-hyphenated.
lang
Two-letter language of the post itself.
year
Four digits. Matched on the year of posted_at in UTC.
min
Outlier floor. 2 is the threshold for 'it beat its own author's median'.
media
any | none | image | video | document
reposts
hide | only | all. Hidden by default: a repost is not a post by the account that reshared it.
since
ISO 8601. Posts on or after this instant.
until
ISO 8601. Posts strictly before it.
sort
recent | engagement | outlier. Default recent.
page
1-based. 60 posts a page.
group
none | week | year | author | hook. How the same rows are arranged.
facets
Set to 1 to add the counts behind the filter bar, computed over the same WHERE clause as the rows.
shelf
Set to 1 to add what broke out in the last seven days, under the same filters.
keys
Set to 1 for the skinny ordering rows (id, handle, date, engagement, outlier) instead of full posts. Up to 600, for arrow-key navigation.
curl -s "https://stealcontent.com/api/posts?dataset=cold-email&min=2&sort=outlier&page=1"

Returns { posts, total, page, pageSize, pages, sort, groupBy, capped } plus `facets` and `shelf` when asked for. `capped: true` with an empty list means a signed-out caller went past page 5, which is the depth ceiling.

Run it
GET/api/posts/{id}

One post and its neighbours

The full post, its assets, more from the same author and the posts nearest it in meaning, in one request rather than four. The text, the metrics, the multiple and the teardown are public. The mirrored artefact is not: `media[].url` is null and `locked` is true for a caller without an account, while the kinds and dimensions ship either way so a client can lay out the right shape of panel.

dataset
Restrict the neighbours and the author's best to one corpus.
curl -s "https://stealcontent.com/api/posts/po_1?dataset=seo"

Returns { post, media, similar, byAuthor }. 404 for a post that was never indexed or has been de-listed.

Run it
GET/api/hooks

The hook vocabulary

The named opening moves the describe pass tags posts with: how often each appears, how far a typical post using it beat its own author's median, and the best examples of each. The multiple is the MEDIAN and never the mean, because one 40x post in a bucket of thirty would make its pattern look like the best hook on the internet and somebody would copy it on that basis. This is also the shared vocabulary the whole library filters on, so read it before inventing your own word for an opener.

dataset
Count inside one vertical only. A hook that works in cold email is not a hook that works in SEO.
min
Outlier floor, and every other filter /api/posts takes. The counts are computed over exactly the rows those filters describe.
curl -s "https://stealcontent.com/api/hooks?dataset=cold-email"

Returns { hooks } - each with the pattern slug, `n`, `medianOutlier` (null when nothing in the bucket is scored) and a few `examples`.

Run it
GET/api/datasets

List the verticals

Every corpus this caller may see: slug, name, one line of what it is for, and how many posts and accounts are in it. A dataset is the dimension the whole library turns on, so start here when you do not know which corpus a question belongs to. The ones still being built are not listed; that is deliberate, because a half-indexed corpus in a stranger's list teaches them the library is thin.

curl -s "https://stealcontent.com/api/datasets"

Returns { datasets } - each with slug, name, blurb, postCount, profileCount and live.

Run it
GET/api/datasets/{slug}

One vertical, in full

The row plus its BRIEF, which is what an agent is told the corpus is FOR and the single most useful field on it. That field is the reason this is a separate call from the list: the switcher does not read it and should not pay to fetch it nine times. Comes with the twelve highest-multiple posts and the accounts watched for the vertical.

curl -s "https://stealcontent.com/api/datasets/cold-email"

Returns { dataset, topPosts, profiles }. 404 for a corpus that is not live yet, unless it has been granted to your account.

Run it
GET/api/profiles/{handle}

One account and its posts

Who they are, their follower count, their BASELINE (the median every one of their multiples is measured against), and their posts under any of the library's filters. Read the baseline before advising anybody to write like somebody: what lands for an account with a baseline of 40 is not what lands for one with a baseline of 4,000. Handles are unique per platform rather than globally, so pass `platform` when one is held on two networks; without it the larger following wins, which is at least a stable answer.

platform
Disambiguate a handle held on two networks.
dataset
Scope the STATS as well as the posts. How they do at cold email is a different question from how they do overall.
insights
Set to 1 for the when-to-post panel, computed over exactly the rows returned. Off by default because it is four extra queries.
tz
IANA zone the insights are bucketed in. Default UTC.
sort
recent | engagement | outlier.
page
1-based. 60 posts a page.
curl -s "https://stealcontent.com/api/profiles/timsoulo?platform=linkedin"

Returns { profile, stats, posts, total, page, pageSize, pages, sort } plus `insights` when asked for.

Run it
POST/api/mcp

The MCP server

JSON-RPC over Streamable HTTP. The corpus tools are open and need no key at all; presenting one ADDS tools rather than unlocking these, and `export_dataset` and `get_post_media` are listed for everybody and state their price in their own description. Most people should install this rather than call it by hand: see /mcp for the command their client takes.

curl -s "https://stealcontent.com/api/mcp" \
  -X POST \
  -H "content-type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"find_hooks","arguments":{"topic":"pricing for solo founders","dataset":"go-to-market"}}}'

Returns A JSON-RPC result whose `content` is one text block of JSON. `isError: true` on a refusal, which is a sentence to relay rather than a failure to retry.

STEALCONTENT agent
this chat $0