Supermemory provides two complementary filtering mechanisms that work independently or together to help you find exactly what you need. How Filtering Works Supermemory uses two types of filters for different purposes:
Container Tags Organize memories into isolated spaces by user, project, or workspace
Metadata Filtering Query memories by custom properties like category, status, or date
Both filtering types can be used: Independently - Use container tags alone OR metadata filters alone Together - Combine both for precise filtering (most common) Think of it as: [Container Tags] → [Your Memories] ← [Metadata Filters] Container tags create isolated memory spaces. They’re perfect for multi-tenant applications, user profiles, and project organization. Exact matching : Arrays must match exactly. A memory tagged with ["user_123", "project_ai"] will NOT match a search for just ["user_123"] Isolation : Each container tag combination creates a separate knowledge graph Naming patterns : Use consistent patterns like user_{id}, project_{id}, or org_{id}_team_{id} Basic Usage // Search within a user's memories const results = await client . search . documents ({ q: "machine learning notes" , containerTags: [ "user_123" ], limit: 10 }); // Search within a project const projectResults = await client . search . documents ({ q: "requirements" , containerTags: [ "project_ai" ], limit: 10 });
# Search within a user's memories results = client.search.documents( q = "machine learning notes" , container_tags = [ "user_123" ], limit = 10 ) # Search within a project project_results = client.search.documents( q = "requirements" , container_tags = [ "project_ai" ], limit = 10 )
# Search within a user's memories curl -X POST "https://api.supermemory.ai/v3/search" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY " \ -H "Content-Type: application/json" \ -d '{ "q": "machine learning notes", "containerTags": ["user_123"], "limit": 10 }'
Container Tag Patterns Best Practice : Use single container tags when possible. Multi-tag arrays require exact matching, which can be restrictive.
Recommended Patterns User isolation: user_{userId} Project grouping: project_{projectId} Workspace separation: workspace_{workspaceId} Hierarchical: org_{orgId}_team_{teamId} Temporal: user_{userId}_2024_q1 API Differences Endpoint Field Name Type Example /v3/searchcontainerTagsArray ["user_123"]/v4/searchcontainerTagString "user_123"/v3/documents/listcontainerTagsArray ["user_123"]
Metadata filters let you query memories by any custom property. They use SQL-like AND/OR logic with explicit grouping. Filter Structure All metadata filters must be wrapped in AND or OR arrays: // ✅ Correct - wrapped in AND array filters : { AND : [ { key: "category" , value: "tech" , negate: false } ] } // ❌ Wrong - not wrapped filters : { key : "category" , value : "tech" , negate : false }
Why Explicit Grouping? Without explicit grouping, this SQL query is ambiguous: category = 'tech' OR status = 'published' AND priority = 'high'
Our structure forces clarity: // Clear: (category = 'tech') OR (status = 'published' AND priority = 'high') { OR : [ { key: "category" , value: "tech" }, { AND: [ { key: "status" , value: "published" }, { key: "priority" , value: "high" } ]} ] }
// Single condition const results = await client . search . documents ({ q: "neural networks" , filters: { AND: [ { key: "category" , value: "ai" , negate: false } ] }, limit: 10 }); // Multiple AND conditions const filtered = await client . search . documents ({ q: "research" , filters: { AND: [ { key: "category" , value: "science" , negate: false }, { key: "status" , value: "published" , negate: false }, { key: "year" , value: "2024" , negate: false } ] }, limit: 10 });
# Single condition results = client.search.documents( q = "neural networks" , filters = { "AND" : [ { "key" : "category" , "value" : "ai" , "negate" : False } ] }, limit = 10 ) # Multiple AND conditions filtered = client.search.documents( q = "research" , filters = { "AND" : [ { "key" : "category" , "value" : "science" , "negate" : False }, { "key" : "status" , "value" : "published" , "negate" : False }, { "key" : "year" , "value" : "2024" , "negate" : False } ] }, limit = 10 )
# Single condition curl -X POST "https://api.supermemory.ai/v3/search" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY " \ -H "Content-Type: application/json" \ -d '{ "q": "neural networks", "filters": { "AND": [ {"key": "category", "value": "ai", "negate": false} ] }, "limit": 10 }'
Filter Types in Detail Supermemory supports four filter types, each designed for specific use cases. 1. String Equality (Default) Exact string matching with optional case-insensitive comparison. Basic
Case-Insensitive
Negation
// Case-sensitive exact match (default) { key : "status" , value : "Published" , negate : false }
// Matches "published", "Published", "PUBLISHED" { key : "status" , value : "PUBLISHED" , ignoreCase : true , negate : false }
// Exclude specific status { key : "status" , value : "draft" , negate : true }
2. String Contains Search for substrings within text fields. Basic
Case-Insensitive
Exclusion
// Find all documents containing "machine learning" { filterType : "string_contains" , key : "description" , value : "machine learning" , negate : false }
// Case-insensitive substring search { filterType : "string_contains" , key : "title" , value : "NEURAL" , ignoreCase : true , negate : false }
// Exclude documents containing "deprecated" { filterType : "string_contains" , key : "content" , value : "deprecated" , negate : true }
3. Numeric Comparisons Filter by numeric values with comparison operators. Basic Operators
With Negation
// Greater than or equal { filterType : "numeric" , key : "score" , value : "80" , numericOperator : ">=" , negate : false } // Less than { filterType : "numeric" , key : "readingTime" , value : "10" , numericOperator : "<" , negate : false }
// NOT equal to 5 (becomes !=) { filterType : "numeric" , key : "priority" , value : "5" , numericOperator : "=" , negate : true } // NOT less than 80 (becomes >=) { filterType : "numeric" , key : "score" , value : "80" , numericOperator : "<" , negate : true }
Numeric Negation Mapping : When using negate: true with numeric filters, operators are reversed: < → >= <= → > > → <= >= → < = → != 4. Array Contains Check if an array field contains a specific value. Basic
Exclusion
Multiple Checks
// Find documents with specific participant { filterType : "array_contains" , key : "participants" , value : "john.doe" , negate : false }
// Exclude documents with specific tag { filterType : "array_contains" , key : "tags" , value : "archived" , negate : true }
// Must have both participants (use AND) { AND : [ { filterType: "array_contains" , key: "participants" , value: "project.manager" }, { filterType: "array_contains" , key: "participants" , value: "lead.developer" } ] }
Common Patterns Ready-to-use filtering patterns for common scenarios. User-Specific Content with Category const results = await client . search . documents ({ q: "project updates" , containerTags: [ "user_123" ], filters: { AND: [ { key: "category" , value: "work" , negate: false }, { key: "visibility" , value: "private" , negate: false } ] }, limit: 10 });
results = client.search.documents( q = "project updates" , container_tags = [ "user_123" ], filters = { "AND" : [ { "key" : "category" , "value" : "work" , "negate" : False }, { "key" : "visibility" , "value" : "private" , "negate" : False } ] }, limit = 10 )
Recent High-Priority Content const results = await client . search . documents ({ q: "important tasks" , filters: { AND: [ { filterType: "numeric" , key: "priority" , value: "7" , numericOperator: ">=" , negate: false }, { filterType: "numeric" , key: "created_timestamp" , value: "1704067200" , // 2024-01-01 numericOperator: ">=" , negate: false } ] }, limit: 20 });
results = client.search.documents( q = "important tasks" , filters = { "AND" : [ { "filterType" : "numeric" , "key" : "priority" , "value" : "7" , "numericOperator" : ">=" , "negate" : False }, { "filterType" : "numeric" , "key" : "created_timestamp" , "value" : "1704067200" , # 2024-01-01 "numericOperator" : ">=" , "negate" : False } ] }, limit = 20 )
Team Collaboration Filter const results = await client . search . documents ({ q: "meeting notes" , containerTags: [ "project_alpha" ], filters: { AND: [ { OR: [ { filterType: "array_contains" , key: "participants" , value: "alice" }, { filterType: "array_contains" , key: "participants" , value: "bob" } ] }, { key: "type" , value: "meeting" , negate: false } ] }, limit: 15 });
results = client.search.documents( q = "meeting notes" , container_tags = [ "project_alpha" ], filters = { "AND" : [ { "OR" : [ { "filterType" : "array_contains" , "key" : "participants" , "value" : "alice" }, { "filterType" : "array_contains" , "key" : "participants" , "value" : "bob" } ] }, { "key" : "type" , "value" : "meeting" , "negate" : False } ] }, limit = 15 )
Exclude Drafts and Deprecated Content const results = await client . search . documents ({ q: "documentation" , filters: { AND: [ { key: "status" , value: "draft" , negate: true // Exclude drafts }, { filterType: "string_contains" , key: "content" , value: "deprecated" , negate: true // Exclude deprecated }, { filterType: "array_contains" , key: "tags" , value: "archived" , negate: true // Exclude archived } ] }, limit: 10 });
results = client.search.documents( q = "documentation" , filters = { "AND" : [ { "key" : "status" , "value" : "draft" , "negate" : True # Exclude drafts }, { "filterType" : "string_contains" , "key" : "content" , "value" : "deprecated" , "negate" : True # Exclude deprecated }, { "filterType" : "array_contains" , "key" : "tags" , "value" : "archived" , "negate" : True # Exclude archived } ] }, limit = 10 )
API-Specific Notes Different endpoints have slightly different requirements: Endpoint Container Tag Field Type Filter Format Notes /v3/searchcontainerTagsArray JSON object Document search /v4/searchcontainerTagString JSON object Memory search /v3/documents/listcontainerTagsArray JSON string Must use JSON.stringify()
List API Special Requirement : The /v3/documents/list endpoint requires filters as a JSON string:// ✅ Correct for List API filters : JSON . stringify ({ AND: [ ... ] }) // ❌ Wrong for List API (but correct for Search API) filters : { AND : [ ... ] }
Most real-world applications combine both filtering types for precise control. Example: User’s Work Documents from 2024 const results = await client . search . documents ({ q: "quarterly report" , containerTags: [ "user_123" ], // User isolation filters: { AND: [ { key: "category" , value: "work" }, { key: "type" , value: "report" }, { filterType: "numeric" , key: "year" , value: "2024" , numericOperator: "=" } ] }, limit: 10 });
results = client.search.documents( q = "quarterly report" , container_tags = [ "user_123" ], # User isolation filters = { "AND" : [ { "key" : "category" , "value" : "work" }, { "key" : "type" , "value" : "report" }, { "filterType" : "numeric" , "key" : "year" , "value" : "2024" , "numericOperator" : "=" } ] }, limit = 10 )
Example: Project’s Active High-Priority Tasks const results = await client . search . documents ({ q: "implementation" , containerTags: [ "project_alpha" ], // Project isolation filters: { AND: [ { key: "status" , value: "completed" , negate: true // Not completed }, { filterType: "numeric" , key: "priority" , value: "7" , numericOperator: ">=" , negate: false }, { filterType: "array_contains" , key: "assignees" , value: "current_user" } ] }, limit: 20 });
results = client.search.documents( q = "implementation" , container_tags = [ "project_alpha" ], # Project isolation filters = { "AND" : [ { "key" : "status" , "value" : "completed" , "negate" : True # Not completed }, { "filterType" : "numeric" , "key" : "priority" , "value" : "7" , "numericOperator" : ">=" , "negate" : False }, { "filterType" : "array_contains" , "key" : "assignees" , "value" : "current_user" } ] }, limit = 20 )
Document-Specific Search Search within a single large document using the docId parameter: // Search within a specific book or manual const results = await client . search . documents ({ q: "neural architecture" , docId: "doc_textbook_ml_2024" , limit: 20 });
# Search within a specific book or manual results = client.search.documents( q = "neural architecture" , doc_id = "doc_textbook_ml_2024" , limit = 20 )
Use this for: Large textbooks or manuals Multi-chapter books Long podcast transcripts Course materials Validation & Limits Pattern : /^[a-zA-Z0-9_.-]+$/ Allowed : Letters, numbers, underscore, hyphen, dot Max length : 64 characters No spaces or special characters Valid vs Invalid Keys // ✅ Valid keys "user_email" "created-date" "version.number" "priority_level_2" // ❌ Invalid keys "user email" // Spaces not allowed "created@date" // @ not allowed "priority!" // ! not allowed "very_long_key_name_that_exceeds_64_characters_limit" // Too long
Query Complexity Limits Maximum conditions : 200 per query Maximum nesting depth : 8 levels Container tag arrays : Must match exactly Troubleshooting No Results Returned
Problem : Container tags must match exactly as arrays.Solution : Verify the exact array structure. ["user_123"] ≠ ["user_123", "project_1"]
Wrong metadata key casing
Problem : Keys are case-sensitive by default.Solution : Check exact key spelling and casing, or use ignoreCase: true for values.
Problem : Using negate: true when you meant false.Solution : Review your negate values. false = include, true = exclude.
Validation Errors
Invalid metadata key format
Error : “Invalid metadata key: contains unsafe characters”Solution : Remove spaces, special characters. Use only alphanumeric, underscore, hyphen, dot.
Error : “Invalid filter structure”Solution : Ensure all conditions are wrapped in AND or OR arrays.
Error : “Invalid filter format”Solution : For /v3/documents/list, use JSON.stringify() on the filter object.
Problem : Complex nested OR conditions with many branches.Solution : Simplify logic, reduce nesting, or split into multiple queries.
Hitting complexity limits
Problem : “Query exceeds maximum complexity”Solution : Reduce conditions (max 200) or nesting depth (max 8).