> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.vellum.ai/product/documents/metadata-filtering/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.vellum.ai/_mcp/server. # Improve Retrieval Results with Metadata Filtering > Learn how to refine searches using metadata filtering for precise document retrieval. Perfect for targeted searches. Some use-cases of Vellum Search require you to narrow in on a subset of documents prior to searching based on keyword match / semantic similarity. For example, you might want to search across historical conversations *for a specific user* or only across documents *that have specific tags*. You can do this through metadata filtering. Metadata filtering requires that you: 1. Provide structured metadata for your documents either upon initial upload or later; and 2. Provide filter criteria when performing a search. Let’s see how to do each. # Specifying Metadata You can specify metadata for documents through both the UI and API. ### Through the UI You can provide metadata upon initial upload. ![Metadata Specification](https://storage.googleapis.com/vellum-public/help-docs/document_metadata_specification.png) You can also view metadata associated with a document and edit it after it’s been uploaded. ![Viewing Metadata](https://storage.googleapis.com/vellum-public/help-docs/edit_document_metadata.png) ### Through the API You can provide metadata as *stringified* JSON upon initial upload using the [upload Documents API here](https://docs.vellum.ai/api-reference/api-reference/documents/upload). You can also update a document’s metadata after-the-fact using the the `Document - Partial Update` [endpoint here](https://docs.vellum.ai/api-reference/api-reference/documents/partial-update). Note that in this endpoint, you can simply provide a JSON object (rather than a stringified JSON object as is required during initial upload). ## Filtering Against Metadata You use the `search` endpoint to perform a search against an index (documented [here](https://docs.vellum.ai/api-reference/api-reference/search)). This endpoint exposes an `options.filters.metadata` field for filtering against your provided metadata prior to matching on keywords/semantic similarity. The syntax of the `metadata` property supports complex boolean logic and was borrowed from [React Query Builder](https://react-querybuilder.js.org/). You can use their [demo here](https://react-querybuilder.js.org/demo#addRuleToNewGroups=false\&autoSelectField=true\&autoSelectOperator=true\&debugMode=false\&disabled=false\&enableDragAndDrop=false\&independentCombinators=false\&justifiedLayout=false\&listsAsArrays=false\&parseNumbers=false\&resetOnFieldChange=true\&resetOnOperatorChange=false\&showBranches=false\&showCloneButtons=false\&showCombinatorsBetweenRules=false\&showLockButtons=false\&showNotToggle=false\&validateQuery=false) to get a feel for the query syntax. Note that values for fields must be JSON-deserializable. If you're looking to filter against a string, then the value passed in should contain escaped double quotes. ### Example Suppose you have two documents with the following metadata: ```json // Document A { "tags": [ "customer-facing", "needs-triage", "bug" ], "priority": "high" } // Document B { "tags": [ "needs-triage", "bug" ], "priority": "low" } ``` And you wanted to perform a search across all documents that are marked as high priority, customer-facing bugs, you would use the following query: ```json { ..., "options": { "filters": { "metadata": { "combinator": "AND", "rules": [ { "field": "tags", "operator": "contains", "value": "\"customer-facing\"" }, { "field": "tags", "operator": "contains", "value": "\"bug\"" }, { "priority": "tags", "operator": "+", "value": "high" } ], "negated": false } } } } ``` > Learn how to refine searches using metadata filtering for precise document retrieval. Perfect for targeted searches.