Quick Start

Three examples to get you going — from fully automatic to fully manual.

Minimal — AI handles everything
POST /api/search { "query": "tel aviv this week" }
With timezone + LLM re-ranking
POST /api/search { "query": "paris tonight", "timezone": "America/New_York", "rerank": true }
Fully manual — no AI, fastest
POST /api/search { "query": "earthquake", "expand": false, "extractMeta": false, "strategy": "embed_time", "timePreset": "last_30d", "topK": 50 }
With ATTN filter + cheaper model
POST /api/search { "query": "trending protests", "attnMin": 5000, "claudeModel": "claude-haiku-4-5-20251001" }
User memories — by nickname or userId
GET /api/memories?user=johndoe&page=1&limit=20

Metadata Extraction

POST /api/extract Claude extracts structured metadata
Uses Claude to extract strategy, time preset, location (with timezone), and media type from a natural language query.
Request Body
ParameterTypeDescription
query requiredstringNatural language query
timezonestringIANA timezone for context
claudeModelstringOverride Claude model (e.g. claude-haiku-4-5-20251001)
anthropicKeystringYour own Anthropic API key
Example response
{ "strategy": "embed_time_coord", "timePreset": "yesterday", "type": null, "location": { "country": "Palestine", "city": "Gaza", "lat": 31.5, "lng": 34.47, "radiusKm": 50, "timezone": "Asia/Gaza" } }
200 OK 400 Missing query
POST /api/expand Claude enriches queries with keywords
Adds 5–15 contextually relevant keywords to improve vector search recall. Original words kept at the start.
Request Body
ParameterTypeDescription
query requiredstringQuery to expand
claudeModelstringOverride Claude model (e.g. claude-haiku-4-5-20251001)
anthropicKeystringYour own Anthropic API key
Example response
{ "expanded": "tel aviv this week Israel protests IDF military Mediterranean" }
200 OK 400 Missing query

Embedding & Query

POST /api/embed Generate 768-dim text embedding
Generates a 768-dimensional vector using Google Gemini gemini-embedding-001.
Request Body
ParameterTypeDescription
text requiredstringText to embed
200 OK 400 Missing text
POST /api/query Raw Pinecone vector query
Queries the Pinecone vector index directly with a vector and optional metadata filter.
Request Body
ParameterTypeDescription
vector requirednumber[]768-dim embedding
host requiredstringPinecone host (from /api/resolve-host)
topKintegerMax results (default 100)
filterobjectPinecone metadata filter
200 OK 400 Missing vector/host
GET /api/resolve-host Get Pinecone index host URL
Returns the Pinecone index host URL. Required for /api/query.
Response
{ "host": "corpus-v1-abc1234.svc.us-east1-gcp.pinecone.io" }
200 OK

Geocoding

GET /api/geocode?q={place} Place name → coordinates
Looks up coordinates for a place name via OpenCage. Returns up to 5 results.
Query Parameters
ParameterTypeDescription
q requiredstringPlace name to geocode
Example
GET /api/geocode?q=Tel%20Aviv
200 OK 400 Missing q

Performance

StepDurationNotes
AI extraction1–2sClaude call. Parallel with expansion.
AI expansion1–2sClaude call. Parallel with extraction.
Embedding200–400msGemini API
Pinecone query300–800msDepends on topK and filter
Firestore fetch300–600msOnly if rerank=true
LLM rerank2–5sOnly if rerank=true

Total without rerank: ~2–4s. With rerank: ~5–9s. Set expand: false and extractMeta: false for ~1s latency.

Priority Order

When multiple sources provide the same parameter:

Parameters
Manual (request body) AI extraction Default
Time resolution
startMs/endMs timePreset (manual) timePreset (AI) "all"
Timezone
AI-detected location tz timezone (request) "UTC"
Error Handling
StatusCause
400Missing required parameter
405Wrong HTTP method
500Internal error (Pinecone, Claude, Gemini, or Firestore)

AI steps fail gracefully — a failed extraction uses defaults, a failed expansion embeds the raw query, a failed rerank returns null. The search still returns results.

Corpus Stats

Live statistics from the corpus Firestore metadata, Cloudflare Media Stream, and the application database (accessible via BigQuery).

Backfill Progress
2,030,445 of ~5,000,000 records processed
40.6% complete · 2,969,437 remaining · ~278 docs/min · est. ~10,681 min remaining
2.03M
Processed
2.97M
Remaining
118
Errors
Data Sources
SourceContainsAccess
Corpus FirestoreDocument metadata, backfill state, processing cursorsFirestore SDK
Cloudflare StreamVideo hours, stream counts, encoding stats, media metadataCF API
App DatabaseEntity counts, image counts, user data, content statsBigQuery
Pinecone768-dim vectors, metadata fields per record/api/query
Backfill Metadata (Firestore)
{ "docsPerMinute": 278, "estimatedMinutesLeft": 10681, "lastDocId": "52c65696-eba3-42c7-8", "lastProcessedAt": "2026-03-31T17:21:39-04:00", "lastRunBatches": 25, "lastRunDurationMs": 270040, "lastRunSuccess": 1250, "lastRunFailed": 0, "remainingDocs": 2969437, "totalErrors": 118, "totalProcessed": 2030563, "totalSuccess": 2030445 }

Full corpus stats — entity counts, video hours, image counts, and other aggregate metrics — will be surfaced on the corpus homepage via BigQuery and Cloudflare Stream API. See the Roadmap for details.

Roadmap

Planned features and infrastructure work, organized by priority. Items marked Active are in progress.

Active Corpus Homepage Stats

Surface aggregate corpus statistics on the search homepage — entity counts, total images, video hours, media breakdown by type, geographic distribution. Data pulled from BigQuery (app database) and Cloudflare Stream API.

Metrics to include: total entities · total images · total video hours · total text records · total audio records · records by country · records by month · Cloudflare Stream encoding stats · storage usage

Active Cloudflare Media Stats Integration

Pull video duration, encoding status, storage, and stream-level metadata from Cloudflare Stream into corpus stats. Currently video data lives in Cloudflare but isn't aggregated into the corpus dashboard.

Next Memory Benchmarking

Benchmark memory infrastructure against established evaluation frameworks to validate retrieval quality, temporal reasoning, and long-context recall before launch.

Target Benchmarks
MemoryArena AMA-Bench LongMemEval MemoryAgentBench LoCoMo Letta Leaderboard

Active Live ATTN Score Architecture

Live attention score filtering is now available. The attnMin parameter on /api/search filters results by minimum ATTN score. The UI includes a slider (0–100k) with manual input. Results can be sorted by ATTN in the search UI.

✓ ATTN pre-filter in Pinecone metadata · ✓ ATTN post-filter fallback · ✓ Search UI slider + manual input · ✓ Sort by ATTN (high/low) · ✓ ATTN displayed on result cards
  • Remaining: ATTN scoring service → real-time Pinecone metadata update → Firestore ATTN field sync

Next Downloadable Data Sample

Allow visitors and potential integrators to download a representative JSON sample of corpus records — covering all media types — to explore the data schema and content structure without needing API access.

GET /api/data-sample → ~50 representative records across image, video, text, audio · includes metadata fields, coordinates, tags, timestamps

Planned BigQuery Stats Pipeline

Scheduled aggregation of app-level stats (entities, images, user counts) from the application database via BigQuery, surfaced on the corpus homepage and available as a stats API endpoint.

Planned Model-Agnostic Embedding Swap

Support runtime selection of embedding providers — the corpus stores media and metadata, not vectors. At query time, pick Gemini, OpenAI, Cohere, or any provider. Re-embedding happens lazily or in batch.

User Memories

Retrieve all memories stored in the corpus for a specific user. Pass a nickname or a raw userId — the API resolves nicknames automatically via the Patr user database.

GET /api/memories?user={nickname or userId} List memories by user
Accepts a user param — either a nickname or a direct userId. The API first queries the Patr users collection for a matching nickName (case-insensitive). If found, it uses that user's internal ID to query the selected source. If no nickname match, it falls back to treating the input as a raw userId. Results sorted by createdAtMs descending, paginated server-side.
Query Parameters
ParameterTypeDefaultDescription
user requiredstringNickname or userId. Nickname is resolved first; falls back to direct userId. Alias: userId
sourcestringpineconepinecone or firestore. Pinecone is ~50% backfilled — use firestore for complete data.
pageNumberinteger1Page number (1-indexed). Alias: page
pageSizeinteger20Results per page. Range: 1–100. Alias: limit
Source selection: The Pinecone index is ~50% backfilled from the corpus Firestore. Use source=firestore to query the full dataset. Use source=pinecone (default) for the vector-indexed subset. Both return the same response shape.
Resolution order: The user value is first looked up as a nickName in the Patr users collection (case-insensitive). If a match is found, the user's internal ID is used. If no match, the value is used directly as a userId. The response includes resolvedVia ("nickname" or "userId") so you know which path was taken.
Example — by nickname (Pinecone)
GET /api/memories?user=johndoe&pageNumber=1&pageSize=20
Example — full corpus via Firestore
GET /api/memories?user=johndoe&source=firestore&pageSize=50
Example — by direct userId
GET /api/memories?user=iWLWiAxa...&source=firestore
200 OK 400 Missing user / invalid source 405 Wrong method 500 Server error
Response Fields
FieldTypeDescription
userIdstringResolved internal user ID used for the query
nickNamestring|nullMatched nickname, or null if resolved via direct userId
resolvedViastring"nickname" or "userId" — which lookup path succeeded
sourcestring"pinecone" or "firestore" — which backend was queried
totalCountintegerTotal number of memories for this user across all pages
pageintegerCurrent page number (1-indexed)
pageSizeintegerNumber of results per page (as requested)
totalPagesintegerTotal number of pages — ceil(totalCount / pageSize)
hasMorebooleantrue if there are more pages after the current one
timespanobject|nullDate range of memories. Pinecone: spans all user memories. Firestore: spans the current page. Fields: earliestMs, latestMs, earliest (ISO), latest (ISO)
memoriesarrayArray of memory objects for the current page, sorted newest first
timingobjectTiming breakdown: resolveMs, pineconeMs/firestoreMs, totalMs
Response structure
{ "userId": "iWLWiAxa...", // resolved internal ID "nickName": "johndoe", // null if resolved via userId "resolvedVia": "nickname", // "nickname" or "userId" "source": "firestore", // which backend was queried "totalCount": 812, "timespan": { "earliestMs": 1704067200000, "latestMs": 1711929600000, "earliest": "2024-01-01T00:00:00.000Z", "latest": "2026-03-31T00:00:00.000Z" }, "page": 1, "pageSize": 20, "totalPages": 41, "hasMore": true, "memories": [ { "id": "abc-123", "metadata": { "userId": "iWLWiAxa...", "createdAtMs": 1711929600000, "createdAt": "2026-03-31T00:00:00.000Z", "attn": 42000, // attention score (null if not set) "type": "image", "city": "Tel Aviv", "country": "Israel", // ... other metadata fields } } ], "timing": { "resolveMs": 210, "firestoreMs": 430, // or "pineconeMs" depending on source "totalMs": 642 } }
Try it

More Memory Endpoints

Additional memory endpoints planned for future releases. Memory quality will be validated against benchmarks (see Roadmap).

Planned City Memories

Aggregate knowledge about specific cities — trending topics, recurring events, notable locations, local context. Powers location-aware search enrichment and city-specific AI behavior.

POST /api/memories/city · GET /api/memories/city/:name

Planned Location Memories

Fine-grained coordinate-based memories — what has happened at specific GPS coordinates over time. Enables hyper-local search context and spatial pattern recognition.

POST /api/memories/location · GET /api/memories/location?lat=&lng=&radius=

Planned Event Memories

Temporal event tracking — significant events detected across the corpus with time, location, and topic clustering. Supports event-aware search and timeline queries.

POST /api/memories/event · GET /api/memories/events?from=&to=