Skill v1.0.0
currentAutomated scan100/100name: qdrant category: data description: > Manage Qdrant vector database via REST API. Use when the user asks to create or delete collections, upsert or search vectors, inspect points, filter by payload fields, manage snapshots, check cluster status, or debug semantic search issues. Covers collection CRUD, point upsert/search/scroll/count, payload indexes, filtering (must/should/must_not), recommend, discover, snapshots, aliases, and cluster operations. compatibility: Requires curl and a running Qdrant instance (default http://localhost:6333) metadata: author: zeph version: "1.0"
Qdrant Vector Database
Base URL: http://localhost:6333 (default). Override with QDRANT_URL env var.
All examples use curl. Replace localhost:6333 with the actual Qdrant endpoint.
Quick Reference
| Task | Endpoint | |
|---|---|---|
| List collections | GET /collections | |
| Create collection | PUT /collections/{name} | |
| Delete collection | DELETE /collections/{name} | |
| Collection info | GET /collections/{name} | |
| Upsert points | PUT /collections/{name}/points | |
| Search | POST /collections/{name}/points/search | |
| Scroll (paginate) | POST /collections/{name}/points/scroll | |
| Get point | GET /collections/{name}/points/{id} | |
| Delete points | POST /collections/{name}/points/delete | |
| Count points | POST /collections/{name}/points/count | |
| Health check | GET /healthz |
Collections
List all collections
curl -s http://localhost:6333/collections | jq
Create collection
curl -s -X PUT http://localhost:6333/collections/my_collection \-H "Content-Type: application/json" \-d '{"vectors": {"size": 384,"distance": "Cosine"}}' | jq
Distance metrics: Cosine, Euclid, Dot, Manhattan.
Create collection with named vectors
curl -s -X PUT http://localhost:6333/collections/my_collection \-H "Content-Type: application/json" \-d '{"vectors": {"content": {"size": 384, "distance": "Cosine"},"title": {"size": 128, "distance": "Cosine"}}}' | jq
Collection info
curl -s http://localhost:6333/collections/my_collection | jq
Key fields: vectors_count, points_count, segments_count, status (green/yellow/red).
Delete collection
curl -s -X DELETE http://localhost:6333/collections/my_collection | jq
Check collection exists
curl -sI http://localhost:6333/collections/my_collection -o /dev/null -w "%{http_code}"# 200 = exists, 404 = not found
Points
Upsert points (insert or update)
curl -s -X PUT http://localhost:6333/collections/my_collection/points \-H "Content-Type: application/json" \-d '{"points": [{"id": 1,"vector": [0.1, 0.2, 0.3, ...],"payload": {"title": "Example", "category": "test", "score": 0.95}},{"id": 2,"vector": [0.4, 0.5, 0.6, ...],"payload": {"title": "Another", "category": "prod", "score": 0.87}}]}' | jq
Point IDs can be integers or UUIDs.
Upsert with named vectors
curl -s -X PUT http://localhost:6333/collections/my_collection/points \-H "Content-Type: application/json" \-d '{"points": [{"id": 1,"vector": {"content": [0.1, 0.2, ...],"title": [0.3, 0.4, ...]},"payload": {"title": "Example"}}]}' | jq
Get point by ID
curl -s http://localhost:6333/collections/my_collection/points/1 | jq
Get multiple points
curl -s -X POST http://localhost:6333/collections/my_collection/points \-H "Content-Type: application/json" \-d '{"ids": [1, 2, 3]}' | jq
Delete points by ID
curl -s -X POST http://localhost:6333/collections/my_collection/points/delete \-H "Content-Type: application/json" \-d '{"points": [1, 2, 3]}' | jq
Delete points by filter
curl -s -X POST http://localhost:6333/collections/my_collection/points/delete \-H "Content-Type: application/json" \-d '{"filter": {"must": [{"key": "category", "match": {"value": "obsolete"}}]}}' | jq
Count points
# Total countcurl -s -X POST http://localhost:6333/collections/my_collection/points/count \-H "Content-Type: application/json" \-d '{}' | jq '.result.count'# Count with filtercurl -s -X POST http://localhost:6333/collections/my_collection/points/count \-H "Content-Type: application/json" \-d '{"filter": {"must": [{"key": "category", "match": {"value": "test"}}]},"exact": true}' | jq '.result.count'
Search
Basic vector search
curl -s -X POST http://localhost:6333/collections/my_collection/points/search \-H "Content-Type: application/json" \-d '{"vector": [0.1, 0.2, 0.3, ...],"limit": 10,"with_payload": true,"with_vector": false}' | jq
Search with filter
curl -s -X POST http://localhost:6333/collections/my_collection/points/search \-H "Content-Type: application/json" \-d '{"vector": [0.1, 0.2, 0.3, ...],"limit": 5,"with_payload": true,"filter": {"must": [{"key": "category", "match": {"value": "prod"}}],"must_not": [{"key": "archived", "match": {"value": true}}]}}' | jq
Search with score threshold
curl -s -X POST http://localhost:6333/collections/my_collection/points/search \-H "Content-Type: application/json" \-d '{"vector": [0.1, 0.2, 0.3, ...],"limit": 10,"score_threshold": 0.7,"with_payload": true}' | jq
Search with named vector
curl -s -X POST http://localhost:6333/collections/my_collection/points/search \-H "Content-Type: application/json" \-d '{"vector": {"name": "content","vector": [0.1, 0.2, 0.3, ...]},"limit": 10,"with_payload": true}' | jq
Scroll (paginate through all points)
# First pagecurl -s -X POST http://localhost:6333/collections/my_collection/points/scroll \-H "Content-Type: application/json" \-d '{"limit": 100,"with_payload": true,"with_vector": false}' | jq# Next page (use next_page_offset from previous response)curl -s -X POST http://localhost:6333/collections/my_collection/points/scroll \-H "Content-Type: application/json" \-d '{"limit": 100,"offset": NEXT_PAGE_OFFSET,"with_payload": true}' | jq
Recommend (find similar to existing points)
curl -s -X POST http://localhost:6333/collections/my_collection/points/recommend \-H "Content-Type: application/json" \-d '{"positive": [1, 2],"negative": [3],"limit": 10,"with_payload": true}' | jq
Filtering
Filters use must (AND), should (OR), must_not (NOT) clauses.
Condition types
// Exact match{"key": "city", "match": {"value": "Berlin"}}// Match any{"key": "color", "match": {"any": ["red", "blue", "green"]}}// Match except{"key": "status", "match": {"except": ["deleted", "archived"]}}// Range (numeric){"key": "price", "range": {"gte": 10.0, "lte": 100.0}}// Range (dates as strings){"key": "created_at", "range": {"gte": "2025-01-01T00:00:00Z"}}// Geo bounding box{"key": "location", "geo_bounding_box": {"top_left": {"lat": 52.52, "lon": 13.38},"bottom_right": {"lat": 52.50, "lon": 13.42}}}// Geo radius{"key": "location", "geo_radius": {"center": {"lat": 52.52, "lon": 13.405},"radius": 1000.0}}// Has key (field exists){"has_id": [1, 2, 3]}// Is empty (field missing or null){"is_empty": {"key": "optional_field"}}// Is null{"is_null": {"key": "nullable_field"}}// Nested filter{"nested": {"key": "tags", "filter": {"must": [{"key": "tags[].name", "match": {"value": "important"}}]}}}// Values count{"values_count": {"key": "tags", "gte": 2}}
Combined filter example
curl -s -X POST http://localhost:6333/collections/my_collection/points/search \-H "Content-Type: application/json" \-d '{"vector": [0.1, 0.2, ...],"limit": 10,"filter": {"must": [{"key": "status", "match": {"value": "active"}},{"key": "score", "range": {"gte": 0.5}}],"should": [{"key": "category", "match": {"value": "A"}},{"key": "category", "match": {"value": "B"}}],"must_not": [{"is_empty": {"key": "embedding"}}]}}' | jq
Payload Indexes
Create indexes on payload fields for faster filtering.
# Create keyword indexcurl -s -X PUT http://localhost:6333/collections/my_collection/index \-H "Content-Type: application/json" \-d '{"field_name": "category", "field_schema": "keyword"}' | jq# Create integer indexcurl -s -X PUT http://localhost:6333/collections/my_collection/index \-H "Content-Type: application/json" \-d '{"field_name": "score", "field_schema": "integer"}' | jq# Create float indexcurl -s -X PUT http://localhost:6333/collections/my_collection/index \-H "Content-Type: application/json" \-d '{"field_name": "price", "field_schema": "float"}' | jq# Delete indexcurl -s -X DELETE http://localhost:6333/collections/my_collection/index/category | jq
Index types: keyword, integer, float, bool, geo, datetime, text, uuid.
Payload Operations
Set payload on existing points
curl -s -X POST http://localhost:6333/collections/my_collection/points/payload \-H "Content-Type: application/json" \-d '{"payload": {"new_field": "value", "score": 0.99},"points": [1, 2, 3]}' | jq
Delete payload keys
curl -s -X POST http://localhost:6333/collections/my_collection/points/payload/delete \-H "Content-Type: application/json" \-d '{"keys": ["old_field", "deprecated"],"points": [1, 2, 3]}' | jq
Snapshots
curl -s http://localhost:6333/collections/my_collection/snapshots | jq # listcurl -s -X POST http://localhost:6333/collections/my_collection/snapshots | jq # createcurl -s -o snap.tar http://localhost:6333/collections/my_collection/snapshots/NAME # downloadcurl -s -X DELETE http://localhost:6333/collections/my_collection/snapshots/NAME | jq # delete
Aliases
# Create/swap alias (atomic)curl -s -X POST http://localhost:6333/aliases \-H "Content-Type: application/json" \-d '{"actions": [{"create_alias": {"alias_name": "prod", "collection_name": "v2"}}]}' | jq# List aliasescurl -s http://localhost:6333/aliases | jq
Service & Health
# Health checkcurl -s http://localhost:6333/healthz# Instance infocurl -s http://localhost:6333/ | jq# Cluster infocurl -s http://localhost:6333/cluster | jq# Telemetrycurl -s http://localhost:6333/telemetry | jq# Prometheus metricscurl -s http://localhost:6333/metrics
Common Workflows
Inspect collection health
# 1. Check collection statuscurl -s http://localhost:6333/collections/my_collection | jq '.result.status, .result.points_count, .result.vectors_count'# 2. Check optimizer statuscurl -s http://localhost:6333/collections/my_collection | jq '.result.optimizer_status'# 3. Check segment count (high count = needs optimization)curl -s http://localhost:6333/collections/my_collection | jq '.result.segments_count'
Debug search quality
# Search with vectors returned for inspectioncurl -s -X POST http://localhost:6333/collections/my_collection/points/search \-H "Content-Type: application/json" \-d '{"vector": [0.1, 0.2, ...],"limit": 5,"with_payload": true,"with_vector": true}' | jq '.result[] | {id, score, payload}'
Important Notes
- Qdrant default ports: 6333 (HTTP), 6334 (gRPC)
- Point IDs are either unsigned integers or UUIDs (string format)
- Vectors must match the collection's configured dimension exactly
with_payload: truereturns all payload; usewith_payload: ["field1", "field2"]for specific fields- Filters on non-indexed fields cause full scan — create payload indexes for fields used in filters
- Collection status:
green= fully optimized,yellow= optimizing,red= error - Upsert is idempotent — re-upserting a point with the same ID overwrites it
- Scroll with
offset: nullstarts from the beginning - Batch operations are more efficient than individual requests