API Documentation

A public, read-only REST API providing access to curated recommendations across 8,337 items in 15 collections.

Quick Links

Collections

CollectionEndpointCountFilters
Activities/api/activities.json326year sportType q
Movies/api/movies.json324year genre director actor q
Places/api/places.json187city country category neighborhood q
Events/api/events.json0type city year q
Sporting Events/api/sporting-events.json109team sport league year city venue experience experienceStatus q
Music/api/music.json481genre type q
Concerts/api/concerts.json43year artist venue city q
Videos/api/videos.json354category q
Podcasts/api/podcasts.json27show q
Tweets/api/tweets.json5,260author q
Code/api/code.json803kind repo year q
Photos/api/photos.json62year month
Books/api/books.json163author q
Work/api/work.json168year kind company
Reading/api/reading.json30q domain

Standards Compliance

This API implements the following standards:

StandardPurpose
RFC 7946GeoJSON place collection exchange
RFC 5870Provider-neutral geographic location URIs
OGC KML 2.3Map annotation and place interchange
GPX 1.1Waypoint interchange with navigation applications
RFC 5545iCalendar event subscriptions
RFC 7986iCalendar calendar metadata and refresh hints
RFC 9073Structured event venue metadata
RFC 8288Web Linking (Link headers, pagination)
RFC 9652Link-Template Header Field
RFC 8631Service Discovery
RFC 9727API Catalog
ARD 0.9Agentic Resource Discovery
RFC 9457Problem Details (errors)
RFC 9309robots.txt policy publication
RFC 9116security.txt vulnerability disclosure policy
RFC 9745Deprecation Header Field
RFC 8594Sunset Header Field
RFC 9110Conditional Requests (ETag)
RFC 9111HTTP Caching
RFC 3339Date/Time Format
RFC 7231Content 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.

curl -fsS https://irvinebroque.com/calendar.ics -o brendan-events.ics

Content Negotiation

All collection endpoints support multiple response formats via the Accept header:

  • application/json — JSON (default)
  • text/csv — CSV export
  • application/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.geojson
curl https://irvinebroque.com/places.kml -o irvinebroque-places.kml
curl -H "Accept: text/csv" https://irvinebroque.com/api/movies.json
curl -H "Accept: application/geo+json" https://irvinebroque.com/api/places.json
curl -H "Accept: text/markdown" https://irvinebroque.com/movies

Cap’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 REST
  • getMeta() — Return service metadata, interface discovery, and collection counts
  • getStatus() — 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 citations
  • taste.find — Known-item lookup across titles, names, URLs, and collection fields
  • taste.get — Canonical detail rehydration for bounded item IDs
  • places.plan — Approximate place planning without device-location or live-routing access
  • sports.list — Filter sporting events Brendan attended in person or watched, plus planned experiences, by experience, status, team, sport, league, year, city, or venue
  • taste.render_recommendations — Taste Explorer list for model-selected canonical IDs
  • places.render_map — Taste Explorer real map for model-selected canonical place IDs
  • sports.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/mcp

In 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.next
  • sort — 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.json

Deprecation 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 links
  • Link-Template — RFC 9652 parameterized collection query template
  • ETag — Entity tag for conditional requests
  • Last-Modified — Last modification timestamp
  • X-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.