# pssst.fyi > AI agent that watches topics you describe in plain text. Sends a 2–4 > sentence brief — synthesised from 3 fresh credible sources — when > something actually changes. Two surfaces: email watchletters for > humans, REST API for your agents. Operated by Aurolabs AB (Stockholm, > Sweden, org. nr 559523-4989). ## Two surfaces, same engine - **Human-facing:** sign up at https://pssst.fyi/, set per-topic cadence (daily / weekly / monthly), get briefs by email. Free tier covers 5 monthly topics; pssst tier is per-cadence-per-topic (€1 monthly / €3 weekly / €9 daily / topic), 30-day Stripe-managed trial. - **Agent-facing:** REST API at `https://pssst.fyi/v1`. Bearer-auth, JSON, idempotency-key support, prepaid credits with auto-refill. 5 free scans per account, then €0.50 per `POST /v1/topics/:id/scan`. Reads + topic CRUD are free. ## Quick start for agents ```bash KEY="sk_live_…" # issued from /dash → API tab curl -H "Authorization: Bearer $KEY" https://pssst.fyi/v1/account curl -H "Authorization: Bearer $KEY" https://pssst.fyi/v1/topics curl -X POST -H "Authorization: Bearer $KEY" \ -H "Idempotency-Key: $(uuidgen)" \ https://pssst.fyi/v1/topics//scan ``` Full machine-readable contract: https://pssst.fyi/v1/openapi.json ## /v1 endpoints | Method | Path | Cost | |--------|-----------------------------------|----------------| | GET | /v1/account | free | | GET | /v1/topics | free | | POST | /v1/topics | free | | GET | /v1/topics/:id | free | | PATCH | /v1/topics/:id | free | | DELETE | /v1/topics/:id | free | | GET | /v1/topics/:id/briefs | free | | GET | /v1/topics/:id/briefs/latest | free | | POST | /v1/topics/:id/scan | **€0.50/call** | | POST | /v1/credits/topup | free (Checkout URL) | | GET | /v1/credits | free | ## What an API key CAN do - Read account state, credit balance, free-call usage - List, read, create, edit, delete the account's topics (web + API) - Run on-demand scans (debits credits) - Read past briefs + cited source URLs - Generate Stripe top-up Checkout URL (user pays at checkout) ## What an API key CANNOT do - Sign in as the user / change email / verify magic-links — human-only - Manage subscription tier / billing portal / invoices — human-only - Toggle auto-refill / save card — human-only via /dash - Access another user's account — auth boundary blocks it structurally - Send watchletters / change recipient — cron-only ## Auth + headers - `Authorization: Bearer sk_live_<48-hex>` on every request - `Idempotency-Key: ` recommended on POSTs (24h replay window) - Rate limit: 60 req/min/key — response carries `X-RateLimit-Remaining` ## Errors - `401` — missing/invalid/revoked key - `402` — insufficient credits → `topup_url` in body - `404` — topic not found / not owned by this key - `409` — conflicting state (e.g. scan on paused topic) - `429` — rate-limited → `retry_after_s` in body - `502` — upstream LLM/Stripe failed; debit refunded automatically ## Pricing (API) - 5 free scans on first key creation per account - €0.50 per `POST /v1/topics/:id/scan` after that - Top-up packs: €5 / €10 / €25 / €50 via Stripe Checkout - Auto-refill: when balance < threshold (default €10), charge saved card amount (default €5) ## Pricing (dashboard / email) - Free: €0/mo, up to 5 topics on monthly cadence - pssst: per-cadence per topic — €1 monthly / €3 weekly / €9 daily - 30-day Stripe-managed free trial on first paid signup - 5 free monthly topics included even on paid tier ## How a scan works 1. The agent receives `POST /v1/topics/:id/scan`. 2. Server debits 1 free call OR €0.50 atomically (insufficient → 402). 3. `runTopicScan` does pass 1: agentic web-search via OpenAI Responses API + `web_search_preview` tool. 4. If pass 1 returns 0 fresh sources, pass 2 escalates: an LLM generates 4 language-aware varied queries (Italian topic → Italian queries; Swedish → Swedish), runs them as distinct web_search calls, dedupes URLs, synthesises a brief from the union. 5. Brief, sit_with question, 3 cited sources (title/outlet/url/published_at) returned in one JSON response. 6. Hard scan failure refunds the debit. ## Topic shape ```json { "id": "12", "title": "OPEC+ output decisions", "summary": "Tracks production quota changes…", "status": "active" | "paused", "cadence": "daily" | "weekly" | "monthly", "scan_mode": "api" | "cron", "last_scan_at": "2026-05-05T11:42:00Z", "scan_count": 3, "created_at": "2026-05-04T13:45:10Z" } ``` API-created topics are `scan_mode: "api"` — agent owns the schedule, no cron auto-scan. Dashboard topics are `scan_mode: "cron"` and run automatically on cadence. ## Brief shape (returned by /scan + /briefs/latest) ```json { "brief": "2-4 sentence synthesis in the topic's language.", "sit_with": "Optional follow-up question.", "sources": [ { "title": "Headline", "outlet": "Reuters", "url": "https://…", "published_at": "2026-05-04" } ], "fresh": true, "scan_at": "2026-05-05T11:42:00Z", "billing": { "paid": true, "cost_cents": 50, "balance_cents": 950, "free_calls_remaining": 0 } } ``` ## Honest limits (today) - No webhooks on new brief — poll `/v1/topics/:id/briefs/latest` - No streaming — scan returns the brief in one JSON response - No cadence-based auto-scan for API topics — agent owns the schedule - One key = one account; no public read-only keys yet - 60 req/min/key; raise via PSSST_API_RATE_LIMIT_PER_MIN env (operator-side) ## Security model - Keys stored as SHA-256 hashes — even with full DB access, raw key is unrecoverable - Revoke is instant (rejected at auth boundary on next request) - One key = one account; cross-account access is structurally impossible - Rate-limits + idempotency caps protect against runaway agents - Credit debits are atomic + refunded on hard scan failures ## AI transparency (EU AI Act Art. 50) Briefs are AI-generated, synthesised from publicly available sources via OpenAI's Responses API + web_search_preview tool. Each watchletter is labelled "AI-generated". Sources are linked. The system makes no consequential decisions about users. ## Data we hold Email address, topic descriptions, sign-in tokens (hashed), session IDs, IP at sign-in, and Stripe billing references. No tracking cookies, no analytics scripts, no ad networks. Account deletion wipes everything within 30 days (Stripe billing records retained 7 years per Swedish accounting law). ## Contact - Contact form (general / privacy / security / billing / bug): https://pssst.fyi/contact - Terms: https://pssst.fyi/terms - Privacy: https://pssst.fyi/privacy