Search API Usage Guide

Overview

The Flipdare search API supports flexible querying across different content types (users, groups, dares, friends) with various scoping options.

Search Parameters

SearchType (Who’s Content)

Controls whose content to search:

  • None - Default, Public content, anyone can see (no authentication required)
  • MINE - User’s own content only (requires authentication)
  • FRIENDS - Content from user’s friends only (requires authentication)

SearchCategory (What to Search For)

Controls which type of objects to return:

  • ALL - All content types
  • USER - User profiles only
  • GROUP - Groups only
  • DARE - Dares (challenges) only
  • FRIEND - Friend connections only (special case)
  • GROUP_DARE - Dares specific to groups (filtered from DARE)

SearchSortType (How to Order Results)

Controls result ranking:

  • RELEVANCE - Best matches first (score + views)
  • NEWEST - Most recent first (creation date)
  • OLDEST - Oldest first (creation date)
  • POPULAR - Most viewed first (views + score)
  • DEF - Default (balanced score + recency)

Valid Combinations

✅ Public Search (SearchType.ALL)

Find Users

SearchRequest(
  q: "john",
  // search_type None searches all
  category: SearchCategory.USER,
  sort_type: SearchSortType.RELEVANCE
)

Use Case: Directory search, finding new users to follow

Find Groups

SearchRequest(
  q: "fitness",
  // search_type None searches all
  category: SearchCategory.GROUP,
  sort_type: SearchSortType.POPULAR
)

Use Case: Discover public groups by interest

Find Dares

SearchRequest(
  q: "cooking challenge",
  // search_type None searches all
  category: SearchCategory.DARE,
  sort_type: SearchSortType.NEWEST
)

Use Case: Browse public challenges

Search Everything

SearchRequest(
  q: "marathon",
  // search_type None searches all
  category: SearchCategory.ALL,
  sort_type: SearchSortType.RELEVANCE
)

Use Case: General discovery across all content Note: Returns mixed results (users, groups, dares)


✅ Personal Search (SearchType.MINE)

My Groups

SearchRequest(
  q: "book club",
  search_type: SearchType.MINE,
  category: SearchCategory.GROUP,
  sort_type: SearchSortType.RELEVANCE
)

Use Case: Find a specific group I’m in or own

My Dares

SearchRequest(
  q: "fitness",
  search_type: SearchType.MINE,
  category: SearchCategory.DARE,
  sort_type: SearchSortType.NEWEST
)

Use Case: Search through my active/completed challenges


✅ Friends Search (SearchType.FRIENDS)

Find Friends

SearchRequest(
  q: "sarah",
  search_type: SearchType.FRIENDS,
  category: SearchCategory.USER,
  sort_type: SearchSortType.RELEVANCE
)

Use Case: Quick lookup of a friend in my network

Friends’ Dares

SearchRequest(
  q: "workout",
  search_type: SearchType.FRIENDS,
  category: SearchCategory.DARE,
  sort_type: SearchSortType.NEWEST
)

Use Case: See what challenges my friends are doing

Friends’ Groups

SearchRequest(
  q: "gaming",
  search_type: SearchType.FRIENDS,
  category: SearchCategory.GROUP,
  sort_type: SearchSortType.POPULAR
)

Use Case: Discover groups my friends belong to

Search All Friends’ Content

SearchRequest(
  q: "marathon",
  search_type: SearchType.FRIENDS,
  category: SearchCategory.ALL,
  sort_type: SearchSortType.RELEVANCE
)

Use Case: See all friend activity related to a topic


❌ Invalid Combinations

ALL + FRIEND

// ❌ DON'T DO THIS
SearchRequest(
  // search_type None searches all
  category: SearchCategory.FRIEND  // Invalid
)

Why Invalid: FRIEND category is for specific friend-to-friend connections, not searchable publicly. Alternative: Use SearchType.FRIENDS + SearchCategory.USER to find specific friends

MINE + USER

// ❌ DON'T DO THIS
SearchRequest(
  search_type: SearchType.MINE,
  category: SearchCategory.USER  // Questionable
)

Why Invalid: Searching for “my own user profile” doesn’t make sense. Alternative: Direct profile fetch, not search

MINE + FRIEND

// ❌ DON'T DO THIS
SearchRequest(
  search_type: SearchType.MINE,
  category: SearchCategory.FRIEND  // Invalid
)

Why Invalid: Can’t search “my friends” - friend connections aren’t keyword-searchable. Alternative: Use SearchType.FRIENDS + SearchCategory.USER with query

FRIENDS + FRIEND

// ❌ DON'T DO THIS
SearchRequest(
  search_type: SearchType.FRIENDS,
  category: SearchCategory.FRIEND  // Invalid
)

Why Invalid: Friend connections are relationships, not searchable entities.


Common Use Cases

1. Onboarding - Find Friends

// Search for known contacts
SearchRequest(
  q: "jane.doe@example.com",
  // search_type None searches all
  category: SearchCategory.USER,
  sort_type: SearchSortType.RELEVANCE
)

2. Activity Feed - See What Friends Are Doing

// Latest friend activity
SearchRequest(
  q: "*",  // All content
  search_type: SearchType.FRIENDS,
  category: SearchCategory.DARE,
  sort_type: SearchSortType.NEWEST
)

3. Explore - Discover New Content

// Trending public challenges
SearchRequest(
  q: "*",
  // search_type None searches all
  category: SearchCategory.DARE,
  sort_type: SearchSortType.POPULAR
)

4. Quick Lookup - Find Specific Friend

// Autocomplete for friend mentions
SearchRequest(
  q: "joh",  // Partial match
  search_type: SearchType.FRIENDS,
  category: SearchCategory.USER,
  sort_type: SearchSortType.RELEVANCE,
  auto_complete: true
)

5. Group Discovery - Join Interest Groups

SearchRequest(
  q: "photography",
query_by is used to filter search results based on a relationship.

Common Use Cases

1. Onboarding - Find Friends

// Search for known contacts
SearchRequest(
  q: "jane.doe@example.com",
  // search all by default
  category: SearchCategory.USER,
  sort_type: SearchSortType.RELEVANCE
)

2. Activity Feed - See What Friends Are Doing

// Latest friend activity
SearchRequest(
  q: "*",  // All content
  search_type: SearchType.FRIENDS,
  category: SearchCategory.DARE,
  sort_type: SearchSortType.NEWEST
)

3. Explore - Discover New Content

// Trending public challenges
SearchRequest(
  q: "*",
  // search all by default
  category: SearchCategory.DARE,
  sort_type: SearchSortType.POPULAR
)

4. Quick Lookup - Find Specific Friend

// Autocomplete for friend mentions
SearchRequest(
  q: "joh",  // Partial match
  search_type: SearchType.FRIENDS,
  category: SearchCategory.USER,
  sort_type: SearchSortType.RELEVANCE,
  auto_complete: true
)

5. Group Discovery - Join Interest Groups

SearchRequest(
  q: "photography",
  // search all by default
  category: SearchCategory.GROUP,
  sort_type: SearchSortType.POPULAR
)

6. Personal Archive - Find Old Challenge

SearchRequest(
  q: "30 day plank",
  search_type: SearchType.MINE,
  category: SearchCategory.DARE,
  sort_type: SearchSortType.OLDEST
)

6. Personal Archive - Find Old Challenge

SearchRequest(
  q: "30 day plank",
  search_type: SearchType.MINE,
  category: SearchCategory.DARE,
  sort_type: SearchSortType.OLDEST
)

Performance Tips

1. Be Specific with Categories

// ✅ GOOD - Fast, searches one collection
SearchRequest(category: SearchCategory.USER, ...)

// ⚠️ SLOWER - Searches multiple collections, merges results
SearchRequest(category: SearchCategory.ALL, ...)

2. Use Autocomplete for Suggestions

// ✅ Optimized for typeahead
SearchRequest(
  q: "joh",
  auto_complete: true,
  per_page: 10  // Smaller page size for autocomplete
)

3. Leverage Caching

  • Identical searches are cached for 5 minutes (configurable)
  • Cache key includes: uid, query, page, search_type, category
  • Cache disabled in dev/emulator mode

4. Pagination Strategy

// First page
SearchRequest(page_num: 1, ...)

// Subsequent pages - reuse same query params
SearchRequest(page_num: 2, ...)  // Cached results help

Error Handling

Authentication Required

// Error: SearchType.MINE or SearchType.FRIENDS without auth
{
  "code": "SEARCH_KNOWN_NO_UID",
  "message": "We had a problem verifying your account..."
}

Solution: Ensure user is authenticated before using MINE/FRIENDS

Invalid Query

// Error: Empty or malformed query
{
  "code": "SEARCH_ERROR",
  "message": "Our bad. We couldn't search for your awesome query."
}

Solution: Validate query before submission

No Results

// Success with no matches
{
  "found": 0,
  "results": [],
  "page": 1,
  "out_of": 0
}

Not an error - Just no matches found


Response Format

Success Response

{
  "q": "fitness",
  "found": 42,
  "page": 1,
  "out_of": 5,
  "collection_name": "dare",
  "results": [
    {
      "id": "dare_123",
      "fromUid": "user_456",
      "title": "30-Day Fitness Challenge",
      "description": "Complete 30 days of exercise...",
      // ... other dare fields
    },
    // ... more results
  ],
  "highlights": [  // Optional, for search term highlighting
    {
      "field": "title",
      "matched_tokens": ["fitness"],
      "snippet": "30-Day <mark>Fitness</mark> Challenge"
    }
  ]
}

Error Response

{
  "code": "SEARCH_ERROR",
  "title": "Search Error",
  "message": "Our bad. We couldn't search for your awesome query.",
  "details": {
    "endpoint": "c_search",
    "timestamp": "2026-03-07T10:30:00Z"
  }
}

Migration Notes

For Existing Code Using Old API:

Removed: SearchType.MEMBER

// OLD (deprecated)
SearchType.MEMBER

// NEW (use instead)
SearchType.FRIENDS  // For friend network content
// OR
SearchType.MINE + filter for group membership
// OLD - Single "general" collection
// All searches hit one big collection

// NEW - Separate collections
// SearchCategory.USER → user collection
// SearchCategory.GROUP → group collection
// SearchCategory.DARE → dare collection
// SearchCategory.FRIEND → friend collection

Impact: Faster queries, but SearchCategory.ALL now requires multi-search