Pressfront API

Ask Claude, ChatGPT or your own app what happened. It reads your trace.

Every account, every post, who started it and who carried it, as data your AI can explain. Alerts land in Slack or Discord too.

Make a key in SettingsComes with Trace, $149 a month.
What happened with @yourname today?
pressfront · get_trace_brief

Of 99 accounts, 66 were critical and 9 supportive. It started with your 10:53 PM post. The jump came at 2:36 AM, when @quietlantern quoted it: 57 accounts arrived in the next hour, against 3 the hour before.

Three groups of about 10 posted within 5 minutes of each other. That is a timing match, not proof anyone coordinated. A model flagged 2 posts as a possible threat; want me to pull them?

  1. 1

    Make a key (skip this for claude.ai)

    In Settings, press Make a key. It starts with pf_live_ and we show it once, so copy it then. Keep it secret like a password. Tick Read only for a key that can look but never change anything.

  2. 2

    Connect your AI

    Claude (claude.ai or the app): Settings, Connectors, Add custom connector, paste https://pressfront.co/api/mcp, then Connect. Sign in to Pressfront and press Allow. No key needed: it reads only, unless you tick the box to let it start traces too.

    Claude Code, one line:

    claude mcp add --transport http pressfront https://pressfront.co/api/mcp \
      --header "Authorization: Bearer pf_live_YOUR_KEY"

    ChatGPT: make a GPT, open Actions, Import from URL: https://pressfront.co/api/v1/openapi.json. Authentication: API key, Bearer, paste your key.

    Any AI that can make calls (Claude Code, Cursor, agents): make a key in Settings. It shows the one line to paste, with your key already in it.

    Claude Desktop, Cursor and others: the set-ups are under Connect any AI below.

    Then just ask: “what happened with my last trace?”, “who carried it?”, “show me the posts flagged as threats”, “has @someone come at me before?”

  3. 3

    Or call it yourself

    No key yet? Read 3 real traces right now with the demo key. It only reads, never starts anything:

    • A story going around“Lara went partying after concert cancelled”: who said it first, how it spread, whether anyone showed proof.01M6S180Z4AYZ47ACQT09S4WEX
    • A very big name@nytimes: 17,383 accounts, each with its side and its posts.01M6S483JT47MPY51RV3XTQ6BD
    • The instant check@spacex in about a minute. Also GET /instant/spacex.01M6PX06C05X1TV8V1NYZNTKJ3

    Who started the story, in four stops:

    curl https://pressfront.co/api/v1/traces/01M6S180Z4AYZ47ACQT09S4WEX/case \
      -H "Authorization: Bearer pf_live_DemoKeyForPressfrontTraceSample1"

    GET /samples lists all three with their links. The demo key also reads one invented trace, 01JDEM0SAMP1E000000000000T.

    With your own key, the whole situation as plain facts, ready to paste into any AI:

    curl https://pressfront.co/api/v1/traces/TRACE_ID/brief \
      -H "Authorization: Bearer pf_live_YOUR_KEY"

    Every critical post, biggest accounts first:

    curl "https://pressfront.co/api/v1/traces/TRACE_ID/posts?side=critical&sort=followers" \
      -H "Authorization: Bearer pf_live_YOUR_KEY"
  4. 4

    Get alerts where you work

    In Settings, paste a Slack or Discord webhook link (or any https address of yours) and press Send a test. Every alert we email you lands there too: “@yourname: 42 posts in the last 15 min. Usually about 4.”

    Slack: Incoming Webhooks, pick a channel, copy the link. Discord: channel settings, Integrations, Webhooks, Copy Webhook URL.

1 call

gives your AI the whole story: the counts, a quote from each side, how it started, who carried it, who moved together. Our numbers and their words; no AI of ours writes it, so nothing is made up and nobody is labeled.

Every endpoint

Base: https://pressfront.co/api/v1. Every call needs Authorization: Bearer pf_live_.... Answers are JSON (the brief is Markdown). The grey word is the same thing as an AI tool. Machine-readable: openapi.json.

PathWhat it does
Samples
GET/samples3 real finished traces any key reads, the demo key included: a story going around, a very big name, an instant check. Each with links to its /case and /brief. list_samples
Account
GET/meWho this key belongs to. whoami
A situation, in plain words
POST/understand
text, files
Say back what we would look into: the person (an @handle) or the story going around, and 2 or 3 plain lines. Read by a language model. Stores nothing, starts nothing. Up to 5 screenshots or PDFs as files: [{mediaType, data}] (base64, REST only). 300 a day. understand_situation
Traces
GET/traces
limit, status, before
Your traces, newest first. list_traces
POST/tracesStart a trace of a name. start_trace
POST/traces
text, claim, files
Start a trace of a situation or a story going around: {"claim": "Lara went partying after the concert was cancelled"}, or what is going on in plain words as {"text": "..."} (screenshots or PDFs in files, REST only). A story is traced back to who said it first. The answer carries understood. trace_situation
GET/traces/:id
wait
One trace: status and headline numbers. get_trace
Read a trace
GET/traces/:id/brief
format, partial
The whole situation as plain facts, for an AI to explain. Start here. get_trace_brief
GET/traces/:id/caseThe answer on top of the trace page, as data: one headline and four stops, Started, Spread, Who, Before? Who said it first, who spread it, whether they showed a photo or link, whether it happened before. Name and story traces. get_case
GET/traces/:id/story
partial
What happened, as data. The What happened tab: headline, counts by side and tone, the biggest voice on each side, how it started, the jump, who carried it, claims, concentration, pace, and every measured fact. get_trace_story
GET/traces/:id/accounts
side, sort, min_followers, new, q, full, partial, limit, cursor
Every account in the trace. Each account with its side, followers, account age, when it first showed up, how it interacted, who it came through, and its first post. list_trace_accounts
GET/traces/:id/accounts/:handleOne account in full. Everything on one account in this trace: profile, side, every post of theirs we hold with each post's own reading. get_trace_account
GET/traces/:id/posts
side, sort, since, until, q, account, threat, partial, limit, cursor
Every post we hold, in order. Each post with its account, time, link, text, and its own side and tone. list_trace_posts
GET/traces/:id/timelineArrivals over time. Posts (or accounts) per time bin with the critical share, the busiest stretch, stretches we did not read, and activity by hour and weekday. get_trace_timeline
GET/traces/:id/groupsWho moved together. Accounts that posted within minutes of each other, posted the same words, or look alike (created together, same hours), and accounts that posted at the subject before. get_trace_groups
GET/traces/:id/whoWho they are. Where X says the accounts are based, what they call themselves in their bios, renamed accounts, the typical account, big and verified accounts, journalists by their own bio, accounts the subject follows, and what ChatGPT and other AIs answer about the subject. get_trace_who
GET/traces/:id/sitesOther sites. Posts about it on other sites (Reddit, forums, archives and more), each with its link, plus which sites we checked and the domains the posts linked to. get_trace_sites
GET/traces/:id/evidenceSaved posts, threats, personal info. The saved copies of posts (text as it stood when the trace ran), posts a model flagged as a possible threat, posts carrying the subject's personal info, and the block list. get_trace_evidence
GET/traces/:id/evidence/packThe evidence pack. The sealed zip a full name trace builds a few minutes after it finishes: one capture record per post, screenshots, Internet Archive copies, a SHA-256 manifest and an RFC 3161 time-stamp. status none, building, ready or failed; when ready, a one-hour download link. get_evidence_pack
Accounts
GET/accounts/:handle
limit
Has this account shown up in my traces before? lookup_account
Alerts
GET/alerts
since, before, limit
Alerts we sent you, newest first. list_alerts
GET/namesThe names we watch for you. list_watched_names
POST/namesWatch one more name. watch_name
DEL/names/:idStop watching a name. unwatch_name
Reading a trace: sides, filters, pages

A new trace takes a few minutes (POST /traces answers with etaSec). GET /traces/:id?wait=25 holds the answer until it finishes or 25 seconds pass, so repeat it instead of polling; the trace.done webhook works too. While it runs, /traces/:id shows soFar (accounts, critical, stage), and ?partial=true on /brief, /story, /accounts and /posts reads the first results, usually within about two minutes. They are for name traces; a story trace has its answer on /traces/:id/case and its brief on /traces/:id/brief.

side=Means
strongly_criticalCritical, and insulting or hostile.
mockingCritical, by joking or ridicule.
disagreeingCritical, with no insult or joke.
criticalAll three together.
supportive, neutral, not_readThe rest.

Sides are read by a language model from each post's text, and every answer says so. A reading, not a finding: read the posts before acting on one.

Lists come in pages: pass the next value back as cursor (or before on /traces and /alerts) until next is null. Each post carries source: post (read on its own), saved (a saved copy, read with its account; traces from before Oct 24, 2026) or link (only the link was kept).

Connect any AI

The MCP address is https://pressfront.co/api/mcp (streamable HTTP). It offers every endpoint as a tool, and tells the AI to quote posts rather than label people. Two ways in:

  • Sign in with Pressfront (OAuth 2.1 with PKCE, dynamic client registration): claude.ai and any app that supports it. Discovery at /.well-known/oauth-authorization-server. A connected app shows in Settings as a connected app; Disconnect there cuts it off at once. Read only unless you tick the box on the Allow screen.
  • Your key as Authorization: Bearer pf_live_...: everything else, below.

Claude Desktop: Settings, Developer, Edit Config, then add:

{ "mcpServers": { "pressfront": {
  "command": "npx",
  "args": ["-y", "mcp-remote", "https://pressfront.co/api/mcp", "--header", "Authorization:${PF_KEY}"],
  "env": { "PF_KEY": "Bearer pf_live_YOUR_KEY" }
} } }

Cursor: ~/.cursor/mcp.json

{ "mcpServers": { "pressfront": {
  "url": "https://pressfront.co/api/mcp",
  "headers": { "Authorization": "Bearer pf_live_YOUR_KEY" }
} } }

ChatGPT (a custom GPT): Actions, Import from URL, https://pressfront.co/api/v1/openapi.json. Authentication: API key, Auth type Bearer. Privacy policy: https://pressfront.co/privacy.html.

Anything else: generate a client from the OpenAPI file, or call the REST endpoints directly.

An alert, as your server gets it

For your own https link we POST JSON with a Pressfront-Event header and a Pressfront-Signature header. Slack and Discord links get one plain line instead.

{
  "id": "evt_lq3k9x2a7f1c9e",
  "type": "alert.spike",
  "created_at": "2026-11-05T21:14:00.000Z",
  "data": {
    "name": "@yourname", "platform": "x",
    "count": 42, "usual": 4, "window_min": 15,
    "level": 1,
    "link": "https://pressfront.co/account.html?open=01J...#trace"
  }
}
typeWhen
alert.spikePosts at a watched name jump to 3 times its usual 15 minutes (at least 12). level 2, 3... means it doubled again since the last alert.
alert.sweepThe 6 hour check of a name or phrase found it moving.
alert.watchA trace you Watch pinged: a big account replied, quoted or mentioned you, or the pace jumped. data.reason says which.
trace.doneOne of your traces finished (data.status is done, thin or failed; data.started_via is api or site). Sent to your own server only, never to Slack or Discord, so a channel is not filled with every trace you run.
testYou pressed Send a test.

We wait 8 seconds for a 2xx. If it fails we try twice more, after 1 and 5 minutes, with the same id, so you can skip one you already handled. If 3 alerts in a row never land, we pause the link and email you; email alerts keep coming. Fix it and press Send a test in Settings: a test that lands turns it back on.

Check a delivery really came from us

The signature header is t=<unix time>,v1=<hex>, where the hex is HMAC-SHA256 of t + "." + raw body with your signing secret (Settings, under your link). Node:

const crypto = require("crypto");
function fromPressfront(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const want = crypto.createHmac("sha256", secret).update(parts.t + "." + rawBody).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return fresh && crypto.timingSafeEqual(Buffer.from(want), Buffer.from(parts.v1 || ""));
}
Limits and errors

60 calls a minute and 5,000 a day per key, 5 keys per account. An AI's tool call counts as one call; connecting and listing tools is free. Reading traces costs nothing extra. Starting them: 20 a day through the API, and a Trace plan's first 300 traces each month are full; after that they run as lighter traces until the month resets (GET /me shows how many full ones are left). Every answer carries X-RateLimit-Remaining. Over the limit you get a 429 with Retry-After in seconds.

StatuserrorMeans
401missing_key, bad_keyNo key sent, or it was deleted.
402no_plan, names_fullThe account is not on Trace any more, or all 10 names are in use.
403read_onlyA read-only key tried to change something.
400bad_side, bad_cursor, bad_dateA filter or page value we do not take. The message says which.
404not_foundNo such endpoint, name, trace or account on your account.
409not_ready, failedThe trace is still running, or failed. Wait for trace.done.
422not_a_name_traceA topic trace: only its headline numbers are on /traces/:id.
429rate_limited, traces_todaySlow down. Wait Retry-After seconds.
500serverOur side. Try again; if it keeps happening, email support@pressfront.co.

Every error is {"error": "code", "message": "plain words"}.

The rules
  • Keep your key secret. Anything done with it counts as done by you.
  • No harassing, threatening, stalking, doxxing or targeting anyone with alerts, the API, an AI connected to it, or trace results. No building or selling a database of people. No reselling trace results as your own service.
  • Posts in a trace belong to the people who wrote them and the platforms they were posted on. Follow those platforms’ rules for what you do with them.
  • Alerts are an early warning, not a guarantee: we try hard, but we do not promise every alert arrives or every post is counted.
  • We may pause or delete a key or link that breaks these rules. Keys stop working while a plan has ended.
  • v1 stays v1: we give notice here before changing an endpoint in a way that breaks you. New fields can appear at any time; ignore the ones you don't use.

The full wording is in our Terms (section 7) and Privacy Policy (what we log and for how long).

Need more than this?

More names, more calls, or something your team needs wired in: support@pressfront.co. Tell us what you are building.