Pressfront API
Paste one link and every alert lands there too. Need more? A key lets your bot read your alerts and traces, add names, and start a trace.
Set it up in SettingsComes with Trace, $149 a month.In Settings, paste a Slack or Discord webhook link (or any https address of yours) and press Send a test. From then on every alert we email you lands there too.
Slack: Incoming Webhooks, pick a channel, copy the link. Discord: channel settings, Integrations, Webhooks, Copy Webhook URL.
Same page, Make a key. It starts with pf_live_ and we show it once, so copy it then. Keep it secret like a password. Delete it any time and anything using it stops.
Tick Read only for a key that can look but never change anything (good for a dashboard). It gets a 403 read_only on anything but GET.
Send the key as a header. This one lists the alerts we sent you:
curl https://pressfront.co/api/v1/alerts \
-H "Authorization: Bearer pf_live_YOUR_KEY"Start a trace of a name, then check on it:
curl -X POST https://pressfront.co/api/v1/traces \ -H "Authorization: Bearer pf_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"@yourname"}' # {"id":"01J...","status":"queued","link":"https://pressfront.co/trace.html?id=01J..."} curl https://pressfront.co/api/v1/traces/01J... \n -H "Authorization: Bearer pf_live_YOUR_KEY"
How often we check a name on X once it starts picking up (every 30 minutes when it is quiet). Bluesky is counted as posts land. We watch 10 names per plan.
Base: https://pressfront.co/api/v1. Every call needs Authorization: Bearer pf_live_.... Answers are JSON.
| Path | What it does | |
|---|---|---|
| GET | /me | Your plan, names watched of how many, calls today. |
| GET | /alerts?since=&limit= | Alerts we sent you, newest first. since is a date (ISO 8601), limit up to 100. |
| GET | /names | The names we watch for you. |
| POST | /names | Watch one more. Body {"name":"@handle"}: an X @handle, an x.com link, or a Bluesky handle like name.bsky.social. |
| DELETE | /names/:id | Stop watching it. |
| GET | /traces?limit= | Your traces, newest first (up to 50). |
| POST | /traces | Start a full trace of a name. Body {"name":"@handle"}. The same name within the hour gives back the trace you already have ("reused": true). 20 a day per account through the API. Topics and phrases run on the website. |
| GET | /traces/:id | Where it is (queued, running, done, thin, failed). When done: summary with posts, relevant posts, sources reached, confidence, the earliest post and the biggest account that spread 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"
}
}| type | When | |
|---|---|---|
alert.spike | Posts 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.sweep | The 6 hour check of a name or phrase found it moving. | |
alert.watch | A trace you Watch pinged: a big account replied, quoted or mentioned you, or the pace jumped. data.reason says which. | |
trace.done | One 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. | |
test | You 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.
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 || "")); }
60 calls a minute and 5,000 a day per key, 5 keys per account. Every answer carries X-RateLimit-Remaining. Over the limit you get a 429 with Retry-After in seconds.
| Status | error | Means |
|---|---|---|
| 401 | missing_key, bad_key | No key sent, or it was deleted. |
| 402 | no_plan, names_full | The account is not on Trace any more, or all 10 names are in use. |
| 403 | read_only | A read-only key tried to change something. |
| 404 | not_found | No such endpoint, name or trace on your account. |
| 429 | rate_limited, traces_today | Slow down. Wait Retry-After seconds. |
| 500 | server | Our side. Try again; if it keeps happening, email support@pressfront.co. |
Every error is {"error": "code", "message": "plain words"}.
The full wording is in our Terms (section 7) and Privacy Policy (what we log and for how long).
More names, more calls, or something your team needs wired in: support@pressfront.co. Tell us what you are building.