API Documentation
A public, read-only REST API providing access to curated recommendations across 8,337 items in 15 collections.
Quick Links
- OpenAPI Specification — Machine-readable API description
- Service Metadata — Collection counts and capabilities
- Service Status — Health and status information
- MCP Endpoint — Public read-only MCP Streamable HTTP endpoint
- MCP Server Card — MCP discovery document for clients
- MCP Discovery Alias — Secondary MCP discovery document
- Cap’n Web Endpoint — Stable read-only HTTP batch RPC endpoint
- Places GeoJSON — Complete RFC 7946 place collection
- Places CSV — Complete tabular place collection for import tools
- Places KML — Complete OGC KML place collection
- Places GPX — Complete GPX waypoint collection
- Events Calendar — Subscribable concerts and sporting-events calendar (
text/calendar) - API Catalog — RFC 9727 discovery (
application/linkset+json; profile="https://www.rfc-editor.org/info/rfc9727") - Agentic Resource Catalog — ARD discovery for MCP, OpenAPI, and Agent Skills (
application/ai-catalog+json) - Problem Types — RFC 9457 error type registry
- Agent Skills Index — Public skill discovery endpoint
Collections
| Collection | Endpoint | Count | Filters |
|---|---|---|---|
| Activities | /api/activities.json | 326 | year sportType q |
| Movies | /api/movies.json | 324 | year genre director actor q |
| Places | /api/places.json | 187 | city country category neighborhood q |
| Events | /api/events.json | 0 | type city year q |
| Sporting Events | /api/sporting-events.json | 109 | team sport league year city venue experience experienceStatus q |
| Music | /api/music.json | 481 | genre type q |
| Concerts | /api/concerts.json | 43 | year artist venue city q |
| Videos | /api/videos.json | 354 | category q |
| Podcasts | /api/podcasts.json | 27 | show q |
| Tweets | /api/tweets.json | 5,260 | author q |
| Code | /api/code.json | 803 | kind repo year q |
| Photos | /api/photos.json | 62 | year month |
| Books | /api/books.json | 163 | author q |
| Work | /api/work.json | 168 | year kind company |
| Reading | /api/reading.json | 30 | q domain |
Standards Compliance
This API implements the following standards:
| Standard | Purpose |
|---|---|
| RFC 7946 | GeoJSON place collection exchange |
| RFC 5870 | Provider-neutral geographic location URIs |
| OGC KML 2.3 | Map annotation and place interchange |
| GPX 1.1 | Waypoint interchange with navigation applications |
| RFC 5545 | iCalendar event subscriptions |
| RFC 7986 | iCalendar calendar metadata and refresh hints |
| RFC 9073 | Structured event venue metadata |
| RFC 8288 | Web Linking (Link headers, pagination) |
| RFC 9652 | Link-Template Header Field |
| RFC 8631 | Service Discovery |
| RFC 9727 | API Catalog |
| ARD 0.9 | Agentic Resource Discovery |
| RFC 9457 | Problem Details (errors) |
| RFC 9309 | robots.txt policy publication |
| RFC 9116 | security.txt vulnerability disclosure policy |
| RFC 9745 | Deprecation Header Field |
| RFC 8594 | Sunset Header Field |
| RFC 9110 | Conditional Requests (ETag) |
| RFC 9111 | HTTP Caching |
| RFC 3339 | Date/Time Format |
| RFC 7231 | Content Negotiation |
Calendar subscriptions
The calendar feeds are public, read-only iCalendar subscriptions. Subscribe to the HTTPS URL in a calendar client to receive later updates; downloading the file is a one-time snapshot. Stable domain-qualified event IDs and revision metadata let clients correlate updates and cancellations. Events include canonical detail links, categories, venue text, coordinates and structured locations when available; concert flyers are published as first-party event images. Exact sporting-event end times are included only when the canonical record supplies one.
/calendar.ics— Combined concerts and sporting events/concerts.ics— Concerts only/sports.ics— Sporting events only
curl -fsS https://irvinebroque.com/calendar.ics -o brendan-events.icsContent Negotiation
All collection endpoints support multiple response formats via the Accept header:
application/json— JSON (default)text/csv— CSV exportapplication/geo+json— GeoJSON (/api/places.json and /api/photos.json)application/vnd.google-earth.kml+xml— Complete KML (/places.kml)application/gpx+xml— Complete GPX waypoints (/places.gpx)
curl https://irvinebroque.com/places.geojson -o irvinebroque-places.geojsoncurl https://irvinebroque.com/places.kml -o irvinebroque-places.kmlcurl -H "Accept: text/csv" https://irvinebroque.com/api/movies.jsoncurl -H "Accept: application/geo+json" https://irvinebroque.com/api/places.jsoncurl -H "Accept: text/markdown" https://irvinebroque.com/moviesCap’n Web (Stable Read-Only)
The Cap’n Web endpoint lives at /api/rpc and supports HTTP batch requests only. Version 1.0.0 is a TypeScript-friendly adapter over the same query behavior as REST; REST and OpenAPI remain the canonical, language-neutral public contract.
The endpoint is unauthenticated and read-only. A batch may contain at most20 operations within a65536-byte request. Public clients receive up to 1000 operations per 60 seconds per source and should honor the retryAfter field on stable RATE_LIMITED RPC errors.
Send CapnWeb-Version: 1.0.0to select the current contract explicitly. Additive changes preserve the current major version. Breaking changes require a new major version, and supported behavior receives at least 90 days’ published notice. The endpoint intentionally does not expose WebSocket sessions, callbacks, subscriptions, or generated protocol schemas.
HTTP batch sessions are single-use. Queue calls synchronously, then await them together; start a new session for later work.
Available methods:
query(collection, params)— Query any public list surface with the same filters, sorting, pagination, and response envelope as RESTgetMeta()— Return service metadata, interface discovery, and collection countsgetStatus()— Return the current public service health snapshot
TypeScript HTTP batch example:
import { newHttpBatchRpcSession } from 'capnweb';
type PublicCollection =
| 'activities'
| 'movies'
| 'places'
| 'events'
| 'sports'
| 'music'
| 'concerts'
| 'videos'
| 'podcasts'
| 'tweets'
| 'code'
| 'photos'
| 'books'
| 'work'
| 'reading'
| 'blog'
| 'writing'
| 'search'
| 'feed-items';
type QueryValue = string | number | boolean | null | undefined;
interface ListResponse<TItem = Record<string, unknown>> {
data: TItem[];
meta: {
totalCount: number;
pageSize: number;
timestamp: string;
facets?: Record<string, Record<string, number>>;
};
links: {
self: string;
first: string;
last: string;
next?: string;
prev?: string;
};
}
interface PublicApi {
query(
collection: PublicCollection,
params?: Record<string, QueryValue>
): Promise<ListResponse>;
getMeta(): Promise<Record<string, unknown>>;
getStatus(): Promise<{ status: 'healthy' | 'degraded' }>;
}
const request = new Request('https://irvinebroque.com/api/rpc', {
headers: { 'CapnWeb-Version': '1.0.0' }
});
using api = newHttpBatchRpcSession<PublicApi>(request);
// Queue every call before awaiting so they share one HTTP request.
const moviesPromise = api.query('movies', {
limit: 10,
sort: 'releaseDate:desc'
});
const concertsPromise = api.query('concerts', {
city: 'Oakland',
limit: 20
});
const [movies, concerts] = await Promise.all([
moviesPromise,
concertsPromise
]);MCP (Public Read-Only)
The public MCP endpoint lives at /mcp and uses Model Context Protocol (2025-11-25) over Streamable HTTP. Discovery is available at /.well-known/mcp/server-card.json and/.well-known/mcp.json.
Browser HTML requests to /mcp redirect to the human setup page. Protocol clients continue to send JSON-RPC requests directly to /mcp.
The public MCP lane is unauthenticated and read-only. It complements the REST API rather than replacing it; authenticated owner writes use /owner/mcp on the same Worker.
Available tools:
taste.recommend— Deterministic recommendations from Brendan’s corpus with evidence and canonical citationstaste.find— Known-item lookup across titles, names, URLs, and collection fieldstaste.get— Canonical detail rehydration for bounded item IDsplaces.plan— Approximate place planning without device-location or live-routing accesssports.list— Filter sporting events Brendan attended in person or watched, plus planned experiences, by experience, status, team, sport, league, year, city, or venuetaste.render_recommendations— Taste Explorer list for model-selected canonical IDsplaces.render_map— Taste Explorer real map for model-selected canonical place IDssports.render_events— Scorecard view for model-selected in-person, watched, and planned sporting events
Migration notes:
- Code Mode and its Worker Loader binding are removed; task-shaped read tools are the stable public contract.
- Data tools stand alone in non-App clients. Render tools receive bounded canonical IDs and rehydrate trusted records server-side.
- Five generated Agent Skills are available through the draft Skills over MCP extension for submission-time import; this extension is experimental, not part of the stable MCP contract.
- Owner writes are absent from /mcp and appear only on OAuth-protected /owner/mcp with taste:write.
Initialize request example:
curl -X POST https://irvinebroque.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {
"extensions": {
"io.modelcontextprotocol/ui": {
"mimeTypes": ["text/html;profile=mcp-app"]
}
}
},
"clientInfo": { "name": "curl", "version": "1.0.0" }
}
}'List tools example:
curl -X POST https://irvinebroque.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}'Submission-time Agent Skill import is available through the experimentalio.modelcontextprotocol/skills extension:
curl -X POST https://irvinebroque.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "skills/list",
"params": {}
}'OpenCode remote MCP config example:
{
"mcp": {
"brendan-website": {
"type": "remote",
"url": "https://irvinebroque.com/mcp"
}
}
}Claude Code command:
claude mcp add --transport http brendan-website https://irvinebroque.com/mcpIn ChatGPT developer mode, connect `https://irvinebroque.com/mcp` for anonymous read tools and Taste Explorer, or `https://irvinebroque.com/owner/mcp` for the owner OAuth lane.
Pagination
Collection endpoints support cursor-based pagination:
limit— Items per page (default: 50, max: 100)cursor— Pagination cursor from links.nextsort— Sort field and direction (e.g., year:desc)facets— Optional facet metadata in meta.facets when set to 1
Pagination links are provided in both the response body and Link header (RFC 8288).
Endpoints also publish a Link-Template header (RFC 9652) with query templates for pagination and capability-specific filters.
Versioning, rate limits, and retries
REST responses publish API-Version: 1.0.0. Clients may omit the request header or send that value explicitly; unsupported versions receive RFC 9457 Problem Details.
RateLimit-Policy and RateLimit-Limit describe the public Cloudflare Worker abuse brake. An exhausted policy returns 429 withRateLimit and Retry-After.
The public REST contract is read-only and exposes only safe, intrinsically idempotent methods.Idempotency-Key is accepted for clients that attach it uniformly, but is not required and does not create a replay cache for read responses.
curl -i -H 'API-Version: 1.0.0' -H 'Idempotency-Key: probe-2026-08-16' 'https://irvinebroque.com/api/places.json?limit=1'Conditional Requests
Use If-None-Match or If-Modified-Since headers to receive 304 Not Modified responses:
curl -H "If-None-Match: "abc123"" https://irvinebroque.com/api/movies.jsonDeprecation and Sunset
Endpoints scheduled for lifecycle changes include Deprecation and optional Sunset headers, with a rel="deprecation" link to migration guidance.
No endpoints are currently scheduled for deprecation.
CORS
Cross-origin requests are enabled for all origins. The following headers are exposed:
Link— Pagination and discovery linksLink-Template— RFC 9652 parameterized collection query templateETag— Entity tag for conditional requestsLast-Modified— Last modification timestampX-Total-Count— Total items in collection
Errors
Errors are returned as RFC 9457 Problem Details with stable type URIs:
{
"type": "https://irvinebroque.com/problems/invalid-cursor",
"title": "Bad Request",
"status": 400,
"detail": "The cursor parameter must be a valid opaque cursor value returned by this API."
}See /problems/ for the full registry.