◆ v1.10.1 · 2026-04-18
Webhook replay protection · SSRF redirect hardening · audit fixes
SECURITY- ▸**Webhook signatures now cover `timestamp.body`** (not just `body`). Receivers can trust `X-FundedAPI-Timestamp` and reject replays outside a 5-minute tolerance window. Without this, an intercepted webhook could be replayed indefinitely. Updated verifier snippet is in `/docs`. Small pre-1.0 breaking change — documented.
- ▸**SSRF hardening on every outbound fetch to user-supplied URLs** — webhook dispatcher, webhook test, saved-search dispatcher, Slack delivery, and scraped-URL validator all now set `redirect: "manual"`. Previously a 302 to `127.0.0.1` after the `resolveSafeHost()` check could bypass the guard.
- ▸**Scraped-URL liveness check runs through `resolveSafeHost()`** — defense in depth against a polluted scrape source pointing at `169.254.169.254` (cloud metadata) or RFC1918 ranges.
- ▸**Narrowed Prisma `select` on the auth path** — `apiKeyHash` and Stripe fields never leave the DB on the API-key lookup. Defense in depth against accidental serialization.
- ▸**Webhook dispatcher audit**: only reset `dailyCallsUsed` on genuine plan upgrades (not every `subscription.updated` event) — caught pre-release. Bug would have let paid users farm extra quota by waiting for Stripe to fire any update event.
- ▸**Checkout audit**: already-subscribed users now get bounced to the Stripe Billing Portal instead of spawning a second subscription — Stripe handles plan changes with prorations natively.
- ▸**JSON-LD XSS fix**: switched every `<script type="application/ld+json">` block from plain `JSON.stringify` to `safeJsonLd()` — the default serializer leaves `<` unescaped, so a scraped startup named `NovaAI</script><script>alert(1)</script>` would break out of the inline script tag. 12 page templates hardened. Full regression suite pinned.
- ▸**Stripe cancel on account deletion**: a paid user who hit DELETE ACCOUNT would stay billed indefinitely — we wiped the User row so the `customer.subscription.deleted` webhook had nothing to match. Now we `stripe.subscriptions.cancel()` first, log to audit if Stripe is unreachable, and still honor the GDPR deletion.
- ▸**Body-size DoS closed**: `safeJsonBody()` previously only checked `Content-Length`. A chunked / Transfer-Encoding request bypassed the 32KB cap entirely. Now post-read length is also enforced. Same guard added to the Stripe webhook raw-body reader (256KB cap).
- ▸**CRON_SECRET timing-safe compare** on the digest cron (scrape cron already had it). New shared `safeCompareStrings()` helper in `lib/crypto.ts`.
- ▸**Defense-in-depth pagination caps** on `/v1/saved-searches` and `/v1/webhooks` list endpoints — 100 row hard cap even though plan limits are already enforced at create time.
- ▸**a11y**: `aria-busy` on Stripe upgrade/portal buttons, `role="alert"` on error regions.
- ▸33 new tests covering the new signing scheme (8), replay/freshness checks (2), webhook plan-change logic (9), checkout portal-bounce (6), JSON-LD XSS (5), chunked body (5), account deletion + Stripe cancel (5). 148 tests total.
- ▸**Docs** updated to reflect all the above — `docs/ai_rules.md` has five new non-negotiables that would have caught these before ship.
◆ v1.10.0 · 2026-04-18
Self-serve Stripe billing + planning docs
FEAT- ▸**Stripe Checkout** at `POST /api/stripe/checkout` — signed-in users can upgrade to Pro or Scale in one click. Creates a hosted Checkout session with `client_reference_id` + metadata for traceability, reuses the customer if we already have one.
- ▸**Stripe webhook handler** at `POST /api/stripe/webhook` — verifies signatures, handles `checkout.session.completed`, `customer.subscription.{created,updated,deleted}`, and `invoice.payment_failed`. Flips `User.plan`, resets daily quota on upgrade, records `currentPeriodEnd` + `subscriptionStatus`.
- ▸**Billing portal** at `POST /api/stripe/portal` — short-lived hosted Stripe portal for self-serve cancel, card update, invoice download. No UI reimplementation.
- ▸**BillingCard** in dashboard — shows current plan, status, next renewal, and a Manage Subscription button for paid users. Free users see an upgrade nudge.
- ▸**UpgradeButton** component — pricing page CTAs now start real Checkout sessions. Graceful fallback to `mailto:` when Stripe isn't configured on the instance (keeps local dev painless).
- ▸**Schema**: four new nullable fields on `User` — `stripeCustomerId` (unique), `stripeSubscriptionId` (unique), `stripePriceId`, `subscriptionStatus`, `currentPeriodEnd`. Additive migration, no backfill required.
- ▸**Planning docs** — new `docs/architecture.md`, `docs/prd.md`, `docs/ai_rules.md`, `docs/plan.md`. Ground truth for contributors and AI assistants. Referenced at the start of every new feature.
- ▸9 new tests (Stripe plan↔price mapping, `isStripeConfigured`, quota lookup, error path when client isn't configured). 115 tests total.
◆ v1.9.0 · 2026-04-17
Per-niche RSS, AI ICP scorer, public trends page
FEAT- ▸Per-niche RSS feeds at `/feed/{niche}.xml` — drop just-the-AI feed into Feedly, just-the-fintech feed into Inoreader, just-the-devtools feed into Slack /feed. Pre-rendered for all 10 whitelisted niches. Advertised via `<link rel="alternate">` for auto-discovery.
- ▸Shared RSS renderer (`lib/rss.ts`) — single source of truth for feed XML. Global + per-niche feeds use the same escaped, CDATA-safe pipeline.
- ▸**AI ICP scorer** (Pro-gated) — `POST /v1/icp-score` with a plain-English ICP description + optional startup IDs. Returns 0-100 match score + reason for every startup, sorted descending. Temperature-0 Perplexity call, cached per (ICP+startup) pair for 6h, bounded concurrency (4 parallel), graceful heuristic fallback if Perplexity is down or key is missing.
- ▸Public `/trends` page — 30-day rolling deal report: top niches with total-raised bars, round distribution, country heatmap. All computed from live aggregates with ISR. Huge SEO moat.
- ▸Sitemap expanded — /trends + all 10 per-niche RSS URLs. Robots + Feedly can crawl the new surface immediately.
- ▸7 new tests for the ICP scorer (empty-input guards, heuristic ranking, Perplexity happy path with cache verification, 500-fallback). 99 tests total.
◆ v1.8.0 · 2026-04-17
Saved-search dispatcher, dashboard UI, watchlist, upgrade nudges
FEAT- ▸Saved-search dispatcher — on every successful scrape we fan out new startups to all active saved searches. Instant-cadence subscribers get emails / Slack blocks / HMAC-signed webhook POSTs within minutes of the row landing.
- ▸Dashboard card for saved searches — create, pause/resume, delete, see match counts. Free-tier users get plan-limit hints inline; Pro perks are called out on the disabled options.
- ▸Watchlist (free-tier feature) — `/v1/watchlist` CRUD. Users bookmark any startup with an optional personal note. No cap. Drives repeat dashboard visits.
- ▸Upgrade-nudge component + QuotaNudge helper. Dashboard shows a contextual banner at 80% / 100% quota for free users, with a tuned CTA to /pricing.
- ▸`authenticateRequest` now accepts session cookies as a fallback for Bearer-less same-origin requests — keeps the raw API key out of client JS and fixed a latent issue with the existing webhooks card.
- ▸429 responses on free-tier quota exhaustion now include the upgrade URL directly in the error message. Visible in API client logs, CLI output, and the Scalar docs playground.
- ▸8 new dispatcher tests (instant delivery, deferred counting, channel routing, HMAC signature presence, inactive-search skipping, zero-match skipping). 92 tests total.
◆ v1.7.0 · 2026-04-17
Saved searches with email/Slack/webhook alerts
FEAT- ▸New `/v1/saved-searches` CRUD API — name a filter preset, pick a delivery channel (email/webhook/slack/none) and cadence (instant/daily/weekly), get pushed when matches appear.
- ▸Free tier: 3 saved searches, weekly email delivery (rides the existing digest infra).
- ▸Pro tier: 20 searches, instant delivery, Slack + webhook channels. Scale: 50 searches.
- ▸Plan limits enforced server-side — if a free user POSTs `cadence: instant`, we quietly downgrade to weekly and return a `warnings` array so the UI can upsell.
- ▸Filter shape matches the main /v1/startups query surface + `keywords[]` for free-text match against name/website. All sanitized — unknown keys dropped, bounds enforced.
- ▸Destination URLs SSRF-guarded (same guard as webhooks). Slack URLs must be on `hooks.slack.com`.
- ▸18 new tests covering filter sanitization, match logic (niche/round/hiring/amount/country/keywords all tested individually + ANDed), plan enforcement, and tier limits. 84 tests total.
- ▸Added Saved Searches tag to OpenAPI so `/docs/api` surfaces the feature category.
◆ v1.6.0 · 2026-04-17
Zero-auth public API, RSS feed, landing live-demo
FEAT- ▸New `/api/public/latest` — no-auth JSON endpoint with top 10 fresh rows. Rate-limited 60/hr per IP, edge-cached 5 min, CORS `*`. Strips contact/priority/confidence fields (those stay behind auth).
- ▸New `/feed.xml` — RSS 2.0 feed with 30 most recent funded startups. Drop into Feedly, Slack `/feed`, IFTTT, Zapier RSS trigger. Auto-discovered via `<link rel="alternate">` in `<head>`.
- ▸Landing page 'Live' widget above the fold — renders 3 real startups fetched from the public endpoint. Proves the API is alive before asking for a signup.
- ▸7 new tests covering the public endpoint (no-auth, rate limiting, field-leakage defense) and RSS (XML escape, categories, canonical links). 66 tests total.
- ▸CSP + compression audit — already in place (middleware.ts + Next.js defaults). Marking those items done.
◆ v1.5.0 · 2026-04-17
Weekly digest, /subscribe preferences, /pricing page
FEAT- ▸Weekly digest email — top 20 newly-funded startups every Monday, filterable by niche. Free forever, double opt-in, one-click unsubscribe, CAN-SPAM + GDPR compliant.
- ▸Public /subscribe page with niche + frequency preferences. Honeypot anti-bot, disposable-email blocking (already in place).
- ▸Public /digest preview page — same data as the email, SEO-indexed, regenerates every 30 min. Great SERP target for 'funded startups this week'.
- ▸New /pricing page with clear Free/Pro/Scale tiers, 9 FAQs, Product+Offer schema.org markup. Pro highlighted as 'most popular'.
- ▸Landing page pricing grid expanded with feature parity across tiers (weekly digest, MCP, npm CLI, webhook batching all called out).
- ▸/api/cron/weekly-digest route — scheduled via Railway cron at `0 14 * * MON` (Mondays 14:00 UTC). Pre-fetches 200-row candidate pool once, filters per-subscriber in-process.
- ▸Subscriber model: digestNiches, digestFrequency, lastDigestAt. Indexed for cron-friendly lookups.
- ▸8 new tests covering digest builder (XSS escape, amount formatting, unsubscribe link, empty-state, plain-text deliverability). 59 tests total.
◆ v1.4.0 · 2026-04-17
Webhook batching, npm client typed events, /for-customer-io
FEAT- ▸Webhook batching (opt-in): set `filters.batch = true` on webhook creation. When a scrape surfaces >1 matching startup, subscribers get ONE POST with `event: "startup.batch"` and `data: [array]` instead of N per-row POSTs. Cuts outbound HTTP and receiver-side DB writes dramatically. Default behavior unchanged — full backward compat.
- ▸@getfundedapi/client v0.3.0: new `WebhookEvent` discriminated union (`StartupCreatedEvent` | `StartupBatchEvent`), `StartupSummary` type, `WebhookFilters.batch` field. Webhook handlers now get exhaustive autocomplete + narrowing.
- ▸/for-customer-io landing — lifecycle campaigns triggered by fresh funding events.
- ▸4 new tests covering batching (default per-row, opted-in folding, single-match fallback, filter-respect). 51 tests total.
◆ v1.3.0 · 2026-04-17
AI search cache, streaming CSV, +2 landings
PERF- ▸AI search: in-memory LRU cache keyed on normalized query, 10-min TTL, cap 500 entries. Identical queries hit Perplexity once, not per-request — cuts Perplexity spend significantly on hot natural-language searches.
- ▸/v1/startups/export now streams CSV through a ReadableStream with cursor-paginated 500-row batches. Memory ceiling for any export size drops from ~5-10 MB to ~1 MB. Downloads start within ~200 ms instead of waiting for the full set.
- ▸2 new landings: /for-zapier (no-code automation), /for-retool (internal-tool dashboards).
- ▸2 new tests covering AI search cache hits + normalization (47 tests total).
◆ v1.2.0 · 2026-04-17
GIN indexes, cached investor aggregator, website filter
PERF- ▸Postgres GIN indexes on `niches` + `investors` arrays — `?niche=AI` and `?investor=Sequoia` queries now hit indexes instead of sequential scans.
- ▸New `?website=acme.io` filter on /v1/startups + /v1/startups/export — exact-match domain lookup for Clay / HubSpot / Salesforce enrichment patterns.
- ▸TTL-cached investor aggregator: one DB scan per 30 min regardless of traffic. `/investors`, `/v1/investors`, and MCP `list_investors` all share the same hot snapshot.
- ▸2 new conversion landings: /for-outreach-com, /for-smartlead.
- ▸Homepage hero redesigned with 3 equivalent quick-starts (curl / npm+CLI / Claude Desktop MCP config).
- ▸OpenAPI spec now documents /mcp JSON-RPC endpoint and the website filter.
- ▸PostHog tracking on feed CTAs (website / LinkedIn / careers clicks), row expansions, load-more, and AI search submissions.
- ▸2 new validation tests covering website filter edge cases (45 tests total).
◆ v1.1.0 · 2026-04-17
npm CLI, feed pagination, dashboard polish
FEAT- ▸@getfundedapi/client@0.2.1 published with a `fundedapi` CLI binary — `npx @getfundedapi/client stats`, `...ai "query"`, `...startups --niche=AI --hiring`, pipes to jq.
- ▸Dashboard: live reset countdown on daily usage, 3-tab Try It Now (curl / Node / Python) with copy-to-clipboard per language.
- ▸Feed: cursor-style Load More pagination with 500-row pages and exhausted-state footer.
- ▸Docs page: new /docs#sdk and /docs#mcp sections with full install + config.
- ▸/llms-full.txt now surfaces the npm client + hosted MCP server for AI agent citations.
- ▸3 new landings: /for-make, /for-heyreach, /for-clearbit.
◆ v1.0.0 · 2026-04-17
npm client, MCP server, admin panel, 4 new landings
FEAT- ▸@getfundedapi/client@0.1.0 published to npm — zero-dependency TypeScript SDK with typed endpoints, auto-retry on 429, HMAC webhook verification.
- ▸First-party MCP server at /mcp — Claude Desktop, Cursor, and any MCP client can call our tools directly over JSON-RPC 2.0. Setup doc at /mcp/claude.
- ▸Admin control panel at /admin (gated by ADMIN_GITHUB_IDS) — scrape runs, abuse feed, webhook health, user signups.
- ▸Four new conversion landings: /for-clay, /for-apollo, /for-instantly, /for-crm-enrichment.
- ▸GitHub CI (lint + tsc + test + build + package build), Dependabot, PR template, issue templates.
◆ v0.9.0 · 2026-04-17
Recipes, status page, dynamic OG
FEAT- ▸New /recipes page with Langchain, MCP, CrewAI, Slack, HubSpot, Python, Node.js snippets.
- ▸Public /status page — live scrape freshness, DB health, data-quality probe.
- ▸Dynamic Open Graph images per startup and per niche — better social + LLM previews.
- ▸Niches index page /niches with activity-sorted grid.
◆ v0.8.0 · 2026-04-17
Long-tail SEO layer
FEAT- ▸Public /startups/[slug] detail pages with Organization + BreadcrumbList JSON-LD.
- ▸Niche hub pages /niches/[niche] with CollectionPage + ItemList schema.
- ▸RSS feed /rss.xml with last 100 rounds, 10-minute cache.
- ▸Dynamic sitemap: top 500 startups + every niche + static pages.
◆ v0.7.1 · 2026-04-17
GDPR + security hardening
SECURITY- ▸Account deletion endpoint + dashboard DangerZone (GDPR Art. 17).
- ▸/.well-known/security.txt with RFC 9116 disclosure policy.
- ▸Audit log entries anonymized on account wipe; retained 90d for abuse detection.
◆ v0.7.0 · 2026-04-17
AI natural-language search
FEAT- ▸POST /v1/search/ai — Perplexity-powered query → structured filter → results in one call.
- ▸AISearchBar UI with suggestion chips mounted on /feed.
- ▸Plan quotas on top of base rate limit: free 10/day · pro 200/day · scale unlimited.
- ▸Circuit breaker around Perplexity; heuristic fallback keeps search live on failure.
◆ v0.6.0 · 2026-04-17
Conversion landing pages
FEAT- ▸/for-sales-teams, /for-recruiters, /for-founders, /for-ai-agents with FAQ JSON-LD.
- ▸/vs/crunchbase honest comparison page for high-intent searches.
- ▸llms.txt at emerging spec for richer LLM citation context.
- ▸robots.txt: explicit Allow for GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot.
◆ v0.5.0 · 2026-04-17
Newsletter + email capture
FEAT- ▸Double-opt-in subscribe flow (/api/subscribe → /confirm → Brevo sync).
- ▸Honeypot field + disposable email blocklist + per-IP rate limit.
- ▸Landing newsletter section with live counter + success animation.
◆ v0.4.1 · 2026-04-17
Scalar interactive API reference
DOCS- ▸/docs/api now ships a try-it-in-browser Scalar reference from our OpenAPI 3.1 spec.
- ▸CSP tightened to allow only Scalar CDN scripts + fonts.
◆ v0.4.0 · 2026-04-17
Webhooks with SSRF-safe delivery
FEAT- ▸POST /v1/webhooks — subscribe with filters, HMAC-signed deliveries.
- ▸Runtime DNS resolution + private-IP block prevents DNS-rebinding SSRF.
- ▸Per-hostname circuit breaker isolates flaky customer endpoints.
◆ v0.3.0 · 2026-04-17
Auth + rate-limit hardening
SECURITY- ▸API key shape-check before DB lookup (anti-enumeration).
- ▸Brute-force lockout after 10 bad attempts/IP.
- ▸__Host- session cookie prefix in production.
- ▸GitHub OAuth: state cookie hardened, account-age fraud check on signup.
◆ v0.2.0 · 2026-04-17
Public API launch
FEAT- ▸GET /v1/startups, GET /v1/startups/[id], GET /v1/stats, GET /v1/startups/export.
- ▸Strict input validation, CORS, X-RateLimit-* response headers.
- ▸Free tier: 100 calls/day. Pro and Scale tiers ready (Stripe pending).
◆ v0.1.0 · 2026-04-17
Initial release
FEAT- ▸Daily Apify scrape pipeline with priority + confidence scoring.
- ▸Retro synthwave landing, feed, docs, dashboard.
- ▸GitHub OAuth, hashed API keys, per-user daily quotas.
More coming.
Stripe checkout, PostHog dashboards, first-party MCP server, npm client.