Skip to main content

Overview

The Search Service provides unified search capabilities across all content in Macro. It indexes documents, emails, channel messages, and projects in OpenSearch and provides fast, relevant search results with filtering and pagination. Base URL: /search Authentication: JWT authentication required via the Authorization header.

Core Concepts

Unified search queries across all content types simultaneously:
  • Documents
  • Email threads and messages
  • Channel messages
  • Projects/folders
Results are ranked by relevance and recency, then combined and sorted. Simple search endpoints provide type-specific search with simpler query syntax and filters.

Search Indexing

Content is indexed asynchronously:
  1. Service sends events to SQS queue when content changes
  2. Search processing service extracts and indexes content
  3. OpenSearch makes content searchable (typically within seconds)

Unified Search

Search All Content

POST /search
Performs a unified search across all content types.
terms
array
required
Array of search terms/keywords
search_on
array
Content types to search: documents, emails, channels, projects, chats
filters
object
Additional filters (date range, owner, etc.)
page_size
integer
Number of results per page (default: 10, max: 100)
cursor
string
Base64-encoded pagination cursor from previous response
results
array
Array of search result items from all content types
next_cursor
string
Cursor for next page of results (null if no more results)
Results are enriched with metadata from respective services (document names, email subjects, channel names) before being returned. Empty or deleted items are filtered out.
{
  "terms": ["product", "roadmap"],
  "search_on": ["documents", "channels"],
  "filters": {
    "date_range": {
      "start": "2026-01-01T00:00:00Z",
      "end": "2026-03-04T23:59:59Z"
    }
  }
}

Simple Search

Simple search endpoints provide type-specific search with straightforward query syntax.

Search Documents

POST /search/simple/documents
Searches only documents.
query
string
required
Search query string
filters
object
Document-specific filters
filters.project_id
string
Filter to specific project
filters.owner_id
string
Filter to specific owner
filters.created_after
datetime
Filter to documents created after date
page_size
integer
Results per page
cursor
string
Pagination cursor
results
array
Array of document search results
next_cursor
string
Next page cursor

Search Emails

POST /search/simple/emails
Searches email threads and messages.
query
string
required
Search query
filters
object
Email filters
filters.from
string
Filter by sender email
filters.to
string
Filter by recipient email
filters.has_attachment
boolean
Filter to emails with attachments
filters.unread
boolean
Filter to unread emails

Search Channels

POST /search/simple/channels
Searches channel messages.
query
string
required
Search query
filters
object
Channel filters
filters.channel_id
string
Filter to specific channel
filters.sender_id
string
Filter by message sender

Search Projects

POST /search/simple/projects
Searches projects and folders.
query
string
required
Search query
filters.owner_id
string
Filter by project owner

Search Chats

POST /search/simple/chats
Searches chat messages (distinct from channels).
query
string
required
Search query

Search Features

Query Syntax

The unified search supports: Basic queries:
  • Single terms: roadmap
  • Multiple terms: ["product", "roadmap"] (matches documents with both)
  • Phrases: Use multiple terms for phrase-like matching
Filters:
  • Date ranges
  • Content type restrictions
  • Owner/creator filters
  • Project/folder filters

Ranking

Results are ranked by:
  1. Relevance score - How well the content matches the query
  2. Recency - More recent content ranks higher
  3. User activity - Frequently accessed items rank higher
Within the unified search, results are sorted by updated_at after type-specific ranking.

Result Enrichment

Raw OpenSearch results are enriched with metadata:
  • Document names and owners
  • Email subjects and senders
  • Channel names
  • Project hierarchy
Deleted or inaccessible items are filtered from results.

Error Codes

Common Errors

  • 200 - Success
  • 400 - Bad Request (invalid query syntax)
  • 401 - Unauthorized
  • 500 - Internal Server Error
  • 503 - Service Unavailable (OpenSearch down)

Service-Specific Errors

  • INVALID_QUERY - Query syntax is invalid
  • INVALID_CURSOR - Pagination cursor is malformed or expired
  • SEARCH_TIMEOUT - Query took too long to execute
  • INDEX_NOT_READY - Search index is still building
{
  "error": "INVALID_QUERY",
  "message": "Search terms cannot be empty"
}

Data Models

Unified Search Request

interface UnifiedSearchRequest {
  terms: string[];                  // Search keywords
  search_on?: SearchEntityType[];   // Content types to search
  filters?: SearchFilters;
}

type SearchEntityType = 
  | "documents" 
  | "emails" 
  | "channels" 
  | "projects" 
  | "chats";

Unified Search Response

interface UnifiedSearchResponse {
  results: UnifiedSearchResponseItem[];
  next_cursor?: string;
}

type UnifiedSearchResponseItem = 
  | DocumentSearchResult
  | EmailSearchResult
  | ChannelSearchResult
  | ProjectSearchResult
  | ChatSearchResult;

Document Search Result

interface DocumentSearchResult {
  type: "document";
  id: string;
  name: string;
  snippet: string;                  // Highlighted excerpt
  score: number;                    // Relevance score (0-1)
  updated_at: string;
  owner_id: string;
  project_id?: string;
}

Email Search Result

interface EmailSearchResult {
  type: "email";
  id: string;
  thread_id: string;
  subject: string;
  snippet: string;
  score: number;
  updated_at: string;
  from: string;
  to: string[];
  has_attachments: boolean;
}

Channel Search Result

interface ChannelSearchResult {
  type: "channel_message";
  id: string;
  channel_id: string;
  channel_name: string;
  content: string;
  score: number;
  updated_at: string;
  sender_id: string;
}

Search Pagination

interface SearchPaginationParams {
  page?: number;
  page_size?: number;
  cursor?: string;                  // Base64-encoded cursor
}

Search Filters

interface SearchFilters {
  date_range?: {
    start?: string;                 // ISO 8601
    end?: string;
  };
  owner_id?: string;
  project_id?: string;
  // Type-specific filters based on entity
}

Build docs developers (and LLMs) love