# notacompany.com Public API and MCP Base URL: `https://notacompany.com/api/v1` Remote MCP: `https://www.notacompany.com/mcp` OpenAPI spec: `https://notacompany.com/openapi.yml` This guide (public): `https://notacompany.com/docs/agent-guide` ## Authentication Read endpoints are public — no token required. Optional Bearer token (scope `api:access`, created in Avo at `/avo`) raises rate limits to **600 reads/minute** and unlocks the bookmark write surface — create/update/delete and approve/reject curation: ```bash curl "https://notacompany.com/api/v1/bookmarks?per_page=10" \ -H "Authorization: Bearer YOUR_TOKEN" ``` Cool-companies bookmarks are ingested from Fundz/YC (auto-tagged: investors, "YC", amount buckets in the `fundraising` tag group) and curated in Avo or through the authenticated API/MCP tools. Raindrop bookmarks auto-approve on sync. **Always use `https://www.notacompany.com` for write requests** — the bare domain 301-redirects and drops POST/PATCH/PUT bodies. For Codex remote MCP, install `https://www.notacompany.com/mcp` as a Streamable HTTP server and pass the same token as Bearer auth. ## Rate Limits - 60 requests/minute per IP (unauthenticated) - 600 reads/minute per valid API token (`api:access`) - 100 writes/minute per valid API token (`api:access`) - Exceeding the limit returns 429 with a `Retry-After` header ## Error Responses | Status | Meaning | | ------ | ------------------------------------------------------------- | | 301 | Old slug of a renamed record — follow `Location` (GET only) | | 401 | Missing or invalid token for writes | | 404 | Resource not found | | 422 | Validation failed (details in response body) | | 429 | Rate limited (wait for `Retry-After` seconds) | --- ## Bookmarks (v7.0.0) Everything is a bookmark — one category, grouped tags. Each has a page at `/bookmarks/{slug}` on the site and links out to its source. ### List / get bookmarks ```bash curl "https://notacompany.com/api/v1/bookmarks?source=cool-company-raises&per_page=10" curl "https://notacompany.com/api/v1/bookmarks/acme-raises-4m-seed" curl "https://notacompany.com/api/v1/bookmarks/tags" ``` Parameters: `q`, `tag`, `category` (`cool-company-raises`/`dev-tools`/`finance`/`interesting`), `source` (raw provenance: `raindrop`/`fundz`/`yc`/`speedrun`/`manual`), `date`, `from`, `to`, `page`, `per_page` (max 100). With a token, `status=pending|rejected` lists the curation queue. `GET /bookmarks/{slug}` honours the token the same way the `?status=` listing does: public callers get the **approved feed only**, so a pending or rejected bookmark returns `404`, while a token holder can fetch any bookmark by slug — including one still in the curation queue. `tags` is a derived, lower-cased, alphabetised union of every group — use it for matching. `tag_groups` preserves the original case and order, so render display text (investor names, amount buckets) from there: ```jsonc "tag_groups": { "fundraising": ["Accel", "$10M+"] }, // display "tags": ["$10m+", "accel"] // match ``` `GET /bookmarks/tags` returns each tag as `{ name, slug, count }`, biggest first. `name` is the stored spelling, `slug` is the URL form, and `?tag=` accepts **either** — matching is case-insensitive, and sources spell the same tag differently ("machine-learning" and "machine learning"), so a tag is whatever shares a slug. `count` counts that whole set and `?tag=` returns it, so filtering on a tag gives back exactly the number listed here. Page URLs are `/bookmarks/tag/{slug}` only; every other spelling `301`s onto it. Markdown negotiation: every public page serves `Accept: text/markdown` — `/`, `/principles`, `/people`, `/portfolio` (and `/portfolio/{slug}`), `/bookmarks` (and its category hubs and per-bookmark pages), `/brand`, `/contact`, `/subscribe`, `/subscribe/guide`, `/terms`, `/privacy`. --- ## Bookmark writes and curation All writes require the Bearer token (`api:access`) and the `www.` host. Non-raindrop creates start as `pending` and publish on approval. ```bash # Create (slug derives from the title) curl -X POST "https://www.notacompany.com/api/v1/bookmarks" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"title":"NewCo raises a $5M Seed round","url":"https://newco.dev", "category":"cool_company_raises","stage":"seed","amount":500000000, "published_at":"2026-07-23", "tag_groups":{"topic":["devtools"],"fundraising":["Lead Fund","$1M+"]}}' # List the curation queue curl "https://notacompany.com/api/v1/bookmarks?status=pending" \ -H "Authorization: Bearer YOUR_TOKEN" # Approve / reject curl -X PATCH "https://www.notacompany.com/api/v1/bookmarks/newco-raises-a-5m-seed-round/approve" \ -H "Authorization: Bearer YOUR_TOKEN" curl -X PATCH "https://www.notacompany.com/api/v1/bookmarks/newco-raises-a-5m-seed-round/reject" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"rejection_reason":"Off-scope"}' # Update (slug preserved unless changed — renames 301 via slug aliases) curl -X PATCH "https://www.notacompany.com/api/v1/bookmarks/newco-raises-a-5m-seed-round" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"summary":"Corrected summary"}' # Delete curl -X DELETE "https://www.notacompany.com/api/v1/bookmarks/newco-raises-a-5m-seed-round" \ -H "Authorization: Bearer YOUR_TOKEN" ``` Notes on writes: - `published_at` accepts a date or a datetime and **defaults to now** when omitted on create, so a quick manual add needs only a title. - A supplied `tag_groups` object is written as given — send the full object rather than a single group. - Renaming via `slug` keeps the old slug alive as an alias (`301` on GET, for both the API and the site page). **`DELETE` is a hard delete and removes the aliases with it** — after deleting, a renamed bookmark's old slug returns `404`, not a redirect. Deleting therefore breaks inbound links that a rename alone would have preserved. - Approve works on a `rejected` bookmark, so a mistaken rejection is recoverable with a plain approve call. --- ## Remote MCP Endpoint: `https://www.notacompany.com/mcp` (with the `www`: the bare domain 301s, and a redirect drops the POST body every MCP call carries) Tools mirror the API. Public reads: - `list_bookmarks` - `get_bookmark` - `list_bookmark_tags` (top 50 by default; `limit` up to 200, `query` to search by name or slug) Private tools require the same Bearer token: - `list_pending_bookmarks` - `approve_bookmark` - `reject_bookmark` - `create_bookmark` - `update_bookmark` (merges `tag_groups` by group; `new_slug` renames) - `delete_bookmark` (permanent; takes the slug's aliases with it) With a token, `list_bookmarks` also takes `status: pending|rejected` and `get_bookmark` returns any bookmark. Send URLs bare in write calls: `?ref=notacompany` is added to every URL on the way out and stripped on the way in. --- ## Discovery entry points - Site index for LLMs: `https://notacompany.com/llms.txt` - Sitemap: `https://notacompany.com/sitemap.xml` - OpenAPI spec: `https://notacompany.com/openapi.yml` - API catalog: `https://notacompany.com/.well-known/api-catalog` - Agent skills: `https://notacompany.com/.well-known/agent-skills/index.json` - Issue feed: `https://notacompany.com/archive/rss` (one item per sent newsletter issue, with that issue's links inside it; no filters — use `/api/v1/bookmarks` to filter by source. `/bookmarks/rss` 301s here) - Tiago's Bookmarks (HTML + markdown negotiation): `https://notacompany.com/bookmarks` - Tools, free and ungated (HTML + markdown negotiation): `https://notacompany.com/tools`. Each tool also answers at its URL plus `.md` — `https://notacompany.com/tools/ai-policy-template.md` is a complete, adoptable AI use policy, clause by clause