···2323 },
2424 },
2525 },
2626- "community.lexicon.calendar.rsvp": {},
2727- }
2626+ "community.lexicon.calendar.rsvp": {
2727+ references: {
2828+ event: {
2929+ collection: "community.lexicon.calendar.event",
3030+ field: "subject.uri",
3131+ },
3232+ },
3333+ },
3434+ },
2835};
2936```
3037···7077| `relations.*.field` | `"subject.uri"` | Field in the related record to match against |
7178| `relations.*.match` | `"uri"` | Match against parent's `"uri"` or `"did"` |
7279| `relations.*.groupBy` | — | Split counts by this field's value |
7373-| `queries` | `{}` | Custom query handlers |
7474-| `searchable` | auto-detected | FTS5 search fields. `string[]` = explicit fields, `false` = disabled, omitted = all non-range queryable fields |
8080+| `references` | `{}` | Forward references to other collections for hydration |
8181+| `references.*.collection` | — | Target collection NSID |
8282+| `references.*.field` | — | Field containing the target record's AT URI |
8383+| `queries` | `{}` | Custom query handlers (raw Response) |
8484+| `pipelineQueries` | `{}` | Custom query handlers that go through the standard filter/sort/hydration pipeline |
8585+| `searchable` | disabled | FTS5 search fields. Provide `string[]` to enable, omit to disable |
75867687### Profiles
7788···100111|-------|---------|-------------|
101112| `actor` | `?actor=did:plc:...` or `?actor=alice.bsky.social` | Filter by DID or handle (triggers on-demand backfill) |
102113| `profiles` | `?profiles=true` | Include profile + identity info keyed by DID |
103103-| `search` | `?search=meetup` | Full-text search across searchable fields (FTS5, ranked) |
114114+| `search` | `?search=meetup` | Full-text search across searchable fields (FTS5, ranked). Requires `searchable` to be configured. |
104115| `{field}` | `?status=going` | Equality filter on queryable string field |
105116| `{field}Min` | `?startsAtMin=2026-03-16` | Range minimum (datetime/integer fields) |
106117| `{field}Max` | `?endsAtMax=2026-04-01` | Range maximum (datetime/integer fields) |
···110121| `hydrate{Ref}` | `?hydrateEvent=true` | Embed the referenced record |
111122| `sort` | `?sort=startsAt` | Sort by a queryable field or count (see below) |
112123| `order` | `?order=asc` | Sort direction: `asc` or `desc` (default depends on field type) |
113113-| `limit` | `?limit=25` | Page size (1-100, default 50) |
124124+| `limit` | `?limit=25` | Page size (1-200, default 50) |
114125| `cursor` | `?cursor=...` | Pagination cursor |
115126116127**Sorting** — `sort` accepts any queryable field param name or a count field:
···122133?sort=rsvpsGoingCount&order=asc # by going count ascending
123134```
124135125125-**Search** uses SQLite FTS5 for ranked full-text search. By default, all non-range queryable fields are searchable. Results are ranked by relevance (BM25) with `time_us` as tiebreaker. Supports FTS5 syntax including prefix (`meetup*`), phrases (`"rust meetup"`), and boolean (`rust OR typescript`). Combinable with all other filters.
136136+**Search** uses SQLite FTS5 for ranked full-text search. To enable, set `searchable: ["field1", "field2"]` on a collection. Results are ranked by relevance (BM25) with `time_us` as tiebreaker. Supports FTS5 syntax including prefix (`meetup*`), phrases (`"rust meetup"`), and boolean (`rust OR typescript`). Combinable with all other filters.
126137127138```
128139?search=meetup # basic search
···150161# Single event with counts, RSVPs, and profiles
151162/xrpc/community.lexicon.calendar.event.getRecord?uri=at://did:plc:.../community.lexicon.calendar.event/...&hydrateRsvps=10&profiles=true
152163153153-# Search for events by name/description
164164+# Search for events by name/description (requires searchable config)
154165/xrpc/community.lexicon.calendar.event.listRecords?search=meetup&profiles=true
155166156167# RSVPs for a specific event, with the referenced event embedded