> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://api.qdrant.tech/v-1-17-x/api-reference/points/upsert-points/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://api.qdrant.tech/_mcp/server. # Upsert points PUT http://localhost:6333/collections/{collection_name}/points Content-Type: application/json Performs the insert + update action on specified points. Any point with an existing \{id} will be overwritten. Reference: https://api.qdrant.tech/api-reference/points/upsert-points ## Authentication - `api-key` header (required) — API Key authentication via header ## Servers - `http://localhost:6333` (http, default) - `https://localhost:6333` (https) ## Request ### Path parameters - `collection_name` (string, required) — Name of the collection to update from ### Query parameters - `wait` (boolean, optional) — If true, wait for changes to actually happen - `ordering` (enum, optional) — define ordering guarantees for the operation - Allowed values: `weak`, `medium`, `strong` - `timeout` (integer, optional) — Timeout for the operation ### Body (application/json) This endpoint expects a PointInsertOperations. - `PointInsertOperations` ## Response ### 200 successful operation - `usage` (CollectionsCollectionNamePointsPutResponsesContentApplicationJsonSchemaUsage, optional) - `time` (double, optional) — Time spent to process this request - `status` (string, optional) - `result` (UpdateResult, optional) ## Types ### PointsBatch - `batch` (Batch, required) - `shard_key` (PointsBatchShardKey, optional) - `update_filter` (PointsBatchUpdateFilter, optional) — Filter to apply when updating existing points. Only points matching this filter will be updated. Points that don't match will keep their current state. New points will be inserted regardless of the filter. - `update_mode` (PointsBatchUpdateMode, optional) — Mode of the upsert operation: insert_only, upsert (default), update_only ### PointsList - `points` (list of PointStruct, required) - `shard_key` (PointsListShardKey, optional) - `update_filter` (PointsListUpdateFilter, optional) — Filter to apply when updating existing points. Only points matching this filter will be updated. Points that don't match will keep their current state. New points will be inserted regardless of the filter. - `update_mode` (PointsListUpdateMode, optional) — Mode of the upsert operation: insert_only, upsert (default), update_only ### CollectionsCollectionNamePointsPutResponsesContentApplicationJsonSchemaUsage ### UpdateResult - `status` (enum, required) — `Acknowledged` - Request is saved to WAL and will be process in a queue. `Completed` - Request is completed, changes are actual. `WaitTimeout` - Request is waiting for timeout. - Allowed values: `acknowledged`, `completed`, `wait_timeout` - `operation_id` (uint64, optional, nullable) — Sequential number of the operation ### Batch - `ids` (list of ExtendedPointId, required) - `vectors` (BatchVectorStruct, required) - `payloads` (list of BatchPayloadsItems, optional, nullable) ### PointsBatchShardKey ### PointsBatchUpdateFilter Filter to apply when updating existing points. Only points matching this filter will be updated. Points that don't match will keep their current state. New points will be inserted regardless of the filter. ### PointsBatchUpdateMode Mode of the upsert operation: insert_only, upsert (default), update_only ### PointStruct - `id` (ExtendedPointId, required) — Type, used for specifying point ID in user interface - `vector` (VectorStruct, required) — Full vector data per point separator with single and multiple vector modes - `payload` (PointStructPayload, optional) — Payload values (optional) ### PointsListShardKey ### PointsListUpdateFilter Filter to apply when updating existing points. Only points matching this filter will be updated. Points that don't match will keep their current state. New points will be inserted regardless of the filter. ### PointsListUpdateMode Mode of the upsert operation: insert_only, upsert (default), update_only ### Usage Usage of the hardware resources, spent to process the request - `hardware` (UsageHardware, optional) - `inference` (UsageInference, optional) ### ExtendedPointId Type, used for specifying point ID in user interface ### BatchVectorStruct ### BatchPayloadsItems ### Filter - `should` (FilterShould, optional) — At least one of those conditions should match - `min_should` (FilterMinShould, optional) — At least minimum amount of given conditions should match - `must` (FilterMust, optional) — All conditions must match - `must_not` (FilterMustNot, optional) — All conditions must NOT match ### VectorStruct Full vector data per point separator with single and multiple vector modes ### PointStructPayload Payload values (optional) ### UsageHardware ### UsageInference ### FilterShould At least one of those conditions should match ### FilterMinShould At least minimum amount of given conditions should match ### FilterMust All conditions must match ### FilterMustNot All conditions must NOT match ### Document WARN: Work-in-progress, unimplemented Text document for embedding. Requires inference infrastructure, unimplemented. - `text` (string, required) — Text of the document. This field will be used as input for the embedding model. - `model` (string, required) — Name of the model used to generate the vector. List of available models depends on a provider. - `options` (DocumentOptions, optional) — Additional options for the model, will be passed to the inference service as-is. See model cards for available options. ### Image WARN: Work-in-progress, unimplemented Image object for embedding. Requires inference infrastructure, unimplemented. - `image` (any, required) — Image data: base64 encoded image or an URL - `model` (string, required) — Name of the model used to generate the vector. List of available models depends on a provider. - `options` (map from string to any, optional, nullable) — Parameters for the model Values of the parameters are model-specific ### InferenceObject WARN: Work-in-progress, unimplemented Custom object for embedding. Requires inference infrastructure, unimplemented. - `object` (any, required) — Arbitrary data, used as input for the embedding model. Used if the model requires more than one input or a custom input. - `model` (string, required) — Name of the model used to generate the vector. List of available models depends on a provider. - `options` (map from string to any, optional, nullable) — Parameters for the model Values of the parameters are model-specific ### HardwareUsage Usage of the hardware resources, spent to process the request - `cpu` (integer, required) - `payload_io_read` (integer, required) - `payload_io_write` (integer, required) - `payload_index_io_read` (integer, required) - `payload_index_io_write` (integer, required) - `vector_io_read` (integer, required) - `vector_io_write` (integer, required) ### InferenceUsage - `models` (map from string to ModelUsage, required) ### MinShould - `conditions` (list of Condition, required) - `min_count` (integer, required) ### DocumentOptions Option variants for text documents. Ether general-purpose options or BM25-specific options. BM25-specific will only take effect if the `qdrant/bm25` is specified as a model. ### ModelUsage - `tokens` (uint64, required) ### Condition ### Bm25Config Configuration of the local bm25 models. - `k` (double, optional, default: 1.2) — Controls term frequency saturation. Higher values mean term frequency has more impact. Default is 1.2 - `b` (double, optional, default: 0.75) — Controls document length normalization. Ranges from 0 (no normalization) to 1 (full normalization). Higher values mean longer documents have less impact. Default is 0.75. - `avg_len` (double, optional, default: 256) — Expected average document length in the collection. Default is 256. - `tokenizer` (enum, optional) - Allowed values: `prefix`, `whitespace`, `word`, `multilingual` - `language` (string, optional, nullable) — Defines which language to use for text preprocessing. This parameter is used to construct default stopwords filter and stemmer. To disable language-specific processing, set this to `"language": "none"`. If not specified, English is assumed. - `lowercase` (boolean, optional, nullable) — Lowercase the text before tokenization. Default is `true`. - `ascii_folding` (boolean, optional, nullable) — If true, normalize tokens by folding accented characters to ASCII (e.g., "ação" -> "acao"). Default is `false`. - `stopwords` (Bm25ConfigStopwords, optional) — Configuration of the stopwords filter. Supports list of pre-defined languages and custom stopwords. Default: initialized for specified `language` or English if not specified. - `stemmer` (Bm25ConfigStemmer, optional) — Configuration of the stemmer. Processes tokens to their root form. Default: initialized Snowball stemmer for specified `language` or English if not specified. - `min_token_len` (integer, optional, nullable) — Minimum token length to keep. If token is shorter than this, it will be discarded. Default is `None`, which means no minimum length. - `max_token_len` (integer, optional, nullable) — Maximum token length to keep. If token is longer than this, it will be discarded. Default is `None`, which means no maximum length. ### FieldCondition All possible payload filtering conditions - `key` (string, required) — Payload key - `match` (FieldConditionMatch, optional) — Check if point has field with a given value - `range` (FieldConditionRange, optional) — Check if points value lies in a given range - `geo_bounding_box` (FieldConditionGeoBoundingBox, optional) — Check if points geolocation lies in a given area - `geo_radius` (FieldConditionGeoRadius, optional) — Check if geo point is within a given radius - `geo_polygon` (FieldConditionGeoPolygon, optional) — Check if geo point is within a given polygon - `values_count` (FieldConditionValuesCount, optional) — Check number of values of the field - `is_empty` (boolean, optional, nullable) — Check that the field is empty, alternative syntax for `is_empty: "field_name"` - `is_null` (boolean, optional, nullable) — Check that the field is null, alternative syntax for `is_null: "field_name"` ### IsEmptyCondition Select points with empty payload for a specified field - `is_empty` (PayloadField, required) — Payload field ### IsNullCondition Select points with null payload for a specified field - `is_null` (PayloadField, required) — Payload field ### HasIdCondition ID-based filtering condition - `has_id` (list of ExtendedPointId, required) ### HasVectorCondition Filter points which have specific vector assigned - `has_vector` (string, required) ### NestedCondition - `nested` (Nested, required) — Select points with payload for a specified nested field ### Bm25ConfigStopwords Configuration of the stopwords filter. Supports list of pre-defined languages and custom stopwords. Default: initialized for specified `language` or English if not specified. ### Bm25ConfigStemmer Configuration of the stemmer. Processes tokens to their root form. Default: initialized Snowball stemmer for specified `language` or English if not specified. ### FieldConditionMatch Check if point has field with a given value ### FieldConditionRange Check if points value lies in a given range ### FieldConditionGeoBoundingBox Check if points geolocation lies in a given area ### FieldConditionGeoRadius Check if geo point is within a given radius ### FieldConditionGeoPolygon Check if geo point is within a given polygon ### FieldConditionValuesCount Check number of values of the field ### PayloadField Payload field - `key` (string, required) — Payload field name ### Nested Select points with payload for a specified nested field - `key` (string, required) - `filter` (Filter, required) ### GeoBoundingBox Geo filter request Matches coordinates inside the rectangle, described by coordinates of lop-left and bottom-right edges - `top_left` (GeoPoint, required) — Geo point payload schema - `bottom_right` (GeoPoint, required) — Geo point payload schema ### GeoRadius Geo filter request Matches coordinates inside the circle of `radius` and center with coordinates `center` - `center` (GeoPoint, required) — Geo point payload schema - `radius` (double, required) — Radius of the area in meters ### GeoPolygon Geo filter request Matches coordinates inside the polygon, defined by `exterior` and `interiors` - `exterior` (GeoLineString, required) — Ordered sequence of GeoPoints representing the line - `interiors` (list of GeoLineString, optional, nullable) — Interior lines (if present) bound holes within the surface each GeoLineString must consist of a minimum of 4 points, and the first and last points must be the same. ### ValuesCount Values count filter request - `lt` (integer, optional, nullable) — point.key.length() \< values\_count.lt - `gt` (integer, optional, nullable) — point.key.length() > values_count.gt - `gte` (integer, optional, nullable) — point.key.length() >= values_count.gte - `lte` (integer, optional, nullable) — point.key.length() \<= values\_count.lte ### GeoPoint Geo point payload schema - `lon` (double, required) - `lat` (double, required) ### GeoLineString Ordered sequence of GeoPoints representing the line - `points` (list of GeoPoint, required) ## Examples **Request** ```json { "batch": { "ids": [ 42 ], "vectors": {} } } ``` **Response** ```json { "usage": { "hardware": { "cpu": 1, "payload_io_read": 1, "payload_io_write": 1, "payload_index_io_read": 1, "payload_index_io_write": 1, "vector_io_read": 1, "vector_io_write": 1 }, "inference": { "models": {} } }, "time": 0.002, "status": "ok", "result": { "status": "acknowledged", "operation_id": 1 } } ``` **SDK Code** ```python from qdrant_client import QdrantClient, models client = QdrantClient(url="http://localhost:6333") client.upsert( collection_name="{collection_name}", points=[ models.PointStruct( id=1, payload={ "color": "red", }, vector=[0.9, 0.1, 0.1], ), models.PointStruct( id=2, payload={ "color": "green", }, vector=[0.1, 0.9, 0.1], ), models.PointStruct( id=3, payload={ "color": "blue", }, vector=[0.1, 0.1, 0.9], ), ], ) ``` ```java import static io.qdrant.client.PointIdFactory.id; import static io.qdrant.client.VectorFactory.vector; import static io.qdrant.client.VectorsFactory.namedVectors; import java.util.List; import java.util.Map; import io.qdrant.client.QdrantClient; import io.qdrant.client.QdrantGrpcClient; import io.qdrant.client.grpc.Points.PointStruct; QdrantClient client = new QdrantClient( QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); client .upsertAsync( "{collection_name}", List.of( PointStruct.newBuilder() .setId(id(1)) .setVectors( namedVectors( Map.of( "image", vector(List.of(0.9f, 0.1f, 0.1f, 0.2f)), "text", vector(List.of(0.4f, 0.7f, 0.1f, 0.8f, 0.1f, 0.1f, 0.9f, 0.2f))))) .build(), PointStruct.newBuilder() .setId(id(2)) .setVectors( namedVectors( Map.of( "image", List.of(0.2f, 0.1f, 0.3f, 0.9f), "text", List.of(0.5f, 0.2f, 0.7f, 0.4f, 0.7f, 0.2f, 0.3f, 0.9f)))) .build())) .get(); ``` ```go package client import ( "context" "fmt" "github.com/qdrant/go-client/qdrant" ) func upsert() { client, err := qdrant.NewClient(&qdrant.Config{ Host: "localhost", Port: 6334, }) if err != nil { panic(err) } response, err := client.Upsert(context.Background(), &qdrant.UpsertPoints{ CollectionName: "{collection_name}", Points: []*qdrant.PointStruct{ { Id: qdrant.NewIDNum(1), Vectors: qdrant.NewVectors(0.9, 0.1, 0.1), Payload: qdrant.NewValueMap(map[string]any{ "color": "red", }), }, { Id: qdrant.NewIDNum(2), Vectors: qdrant.NewVectors(0.1, 0.9, 0.1), Payload: qdrant.NewValueMap(map[string]any{ "color": "green", }), }, { Id: qdrant.NewIDNum(3), Vectors: qdrant.NewVectors(0.1, 0.1, 0.9), Payload: qdrant.NewValueMap(map[string]any{ "color": "blue", }), }, }, }) if err != nil { panic(err) } fmt.Println("Upsert status: ", response.GetStatus()) } ``` ```typescript import { QdrantClient } from "@qdrant/js-client-rest"; const client = new QdrantClient({ host: "localhost", port: 6333 }); client.upsert("{collection_name}", { points: [ { id: 1, payload: { color: "red" }, vector: [0.9, 0.1, 0.1], }, { id: 2, payload: { color: "green" }, vector: [0.1, 0.9, 0.1], }, { id: 3, payload: { color: "blue" }, vector: [0.1, 0.1, 0.9], }, ], }); ``` ```rust use qdrant_client::qdrant::{PointStruct, UpsertPointsBuilder}; use qdrant_client::{Qdrant, Payload}; use serde_json::json; let client = Qdrant::from_url("http://localhost:6334").build()?; client .upsert_points( UpsertPointsBuilder::new( "{collection_name}", vec![ PointStruct::new( 1, vec![0.9, 0.1, 0.1], Payload::try_from(json!( {"color": "red"} )) .unwrap(), ), PointStruct::new( 2, vec![0.1, 0.9, 0.1], Payload::try_from(json!( {"color": "green"} )) .unwrap(), ), PointStruct::new( 3, vec![0.1, 0.1, 0.9], Payload::try_from(json!( {"color": "blue"} )) .unwrap(), ), ], ) .wait(true), ) .await?; ``` ```csharp using Qdrant.Client; using Qdrant.Client.Grpc; var client = new QdrantClient("localhost", 6334); await client.UpsertAsync( collectionName: "{collection_name}", points: new List { new() { Id = 1, Vectors = new[] { 0.9f, 0.1f, 0.1f }, Payload = { ["city"] = "red" } }, new() { Id = 2, Vectors = new[] { 0.1f, 0.9f, 0.1f }, Payload = { ["city"] = "green" } }, new() { Id = 3, Vectors = new[] { 0.1f, 0.1f, 0.9f }, Payload = { ["city"] = "blue" } } } ); ``` ```ruby require 'uri' require 'net/http' url = URI("http://localhost:6333/collections/collection_name/points") http = Net::HTTP.new(url.host, url.port) request = Net::HTTP::Put.new(url) request["api-key"] = '' request["Content-Type"] = 'application/json' request.body = "{\n \"batch\": {\n \"ids\": [\n 42\n ],\n \"vectors\": {}\n }\n}" response = http.request(request) puts response.read_body ``` ```php request('PUT', 'http://localhost:6333/collections/collection_name/points', [ 'body' => '{ "batch": { "ids": [ 42 ], "vectors": {} } }', 'headers' => [ 'Content-Type' => 'application/json', 'api-key' => '', ], ]); echo $response->getBody(); ``` ```swift import Foundation let headers = [ "api-key": "", "Content-Type": "application/json" ] let parameters = ["batch": [ "ids": [42], "vectors": [] ]] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "http://localhost:6333/collections/collection_name/points")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "PUT" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```