Authenticated endpoints require:
Authorization: Bearer <firebase_id_token>Server routes derive uid from the verified Firebase token and do not trust client-supplied owner IDs.
- GET: fetch authenticated user's resources. Optional query:
collectionId. - POST: create a resource. Body:
title,link,note,tag,is_public,collection_ids,new_collection. - PUT: update an owned resource. Body:
id,title,link,note,tag,is_public,collection_ids. - DELETE: delete an owned resource. Query:
id. - Create/update performs best-effort indexing and returns an
indexingobject. - Saved resources are not AI-searchable until indexing writes
resource_chunksand setsindex_statustoindexed.
- GET: fetch authenticated user's collections, or public shared collections with
?shared=true. - POST: create a collection for the authenticated user.
- PUT: update an owned collection. Body:
collectionId. - PATCH: reorder owned collections. Body:
orderedIds. - DELETE: delete an owned collection. Query:
collectionId.
- POST: add an owned resource to an owned collection. Body:
collectionId,resourceId. - DELETE: remove an owned resource from an owned collection. Body or query:
collectionId,resourceId.
- GET: fetch public resources from other users. Requires auth.
- POST: copy a public resource to the authenticated user's private dump. Body:
resourceId.
- POST: create or update authenticated user's profile.
- GET: get authenticated user's profile, or stats with
?type=stats. - PUT: update authenticated user's profile.
- POST: public metadata extraction. Body:
{ "url": "https://example.com" }. - Response:
{ title, description, suggestedTag, favicon }.
- GET or POST: check username uniqueness.
- POST: semantic search across indexed chunks.
- Body:
{ "query": "firebase auth", "mode": "mine" | "shared" | "all", "limit": 8 }. - Response:
{ success, results }. - Requires Firestore vector indexes for the selected mode.
- POST: RAG answer generation with citations.
- Body:
{ "question": "What should I read about Firebase auth?", "mode": "mine" | "shared" | "all", "limit": 8 }. - Response:
{ success, answer, sources }. - Retrieval runs before answer generation. If no matching chunks are found, the API returns an answer explaining that no indexed resources matched.
- Uses
GEMINI_MODEL, recommendedgemini-2.5-flash, for answer generation.
- POST: retry indexing for an owned resource.
- Body:
{ "resourceId": "..." }. - Response:
{ success, status, chunksIndexed, error? }. - Use this when
index_statusisfailed,skipped, or stale after changing a resource URL.
mine: private and public resources owned by the authenticated user.shared: public resources owned by other users.all: authenticated user's resources plus other users' public resources.
GEMINI_API_KEYmust be a valid Google AI Studio / Gemini API key.GEMINI_MODEL=gemini-2.5-flashis recommended for production v1.GEMINI_EMBEDDING_MODEL=gemini-embedding-001.- Firestore vector index for
user_id + embeddingis required formine. - Firestore vector index for
is_public + user_id + embeddingis required forsharedandall. - Resource chunks use 768-dimensional embeddings.
- 400: Bad Request
- 401: Unauthorized
- 404: Not Found
- 409: Conflict
- 429: AI provider quota exceeded
- 500: Internal Server Error
Common AI failure causes:
- Invalid Gemini key: replace
GEMINI_API_KEYwith an AI Studio key and redeploy. - Gemini quota exceeded: use
gemini-2.5-flashor enable billing/quota. - Missing Firestore vector index: create the exact index command returned by Firestore.
- No indexed chunks: save/reindex a resource and wait for
index_status=indexed.