Skip to content

Vector Stores API

Index your files once and search them by meaning. A vector store holds the passages of the files attached to it; a search returns the passages closest to a query, with the file they came from and a similarity score. There is no embedding pipeline, chunker or vector database to run — attach a file and search it.

Why Choose the Vector Stores API?

  • Search by Meaning
    A query finds the passages that answer it, not the ones sharing its words.

  • Attach and Forget
    Upload a file with the Files API, attach it, and it becomes searchable — indexing runs in the background.

  • Attribute Filters
    Tag files with up to 16 attributes and restrict a search to the ones that match.

  • File Batches
    Attach many files in one request and follow their progress with a single identifier.

  • Expiration Policies
    Expire a store after a number of days without a search, so scratch stores do not accumulate.

  • Your Own Account
    Documents, passages and vectors are stored in your AWS account, and never leave it.

  • Bring Your Own Knowledge Base
    Address an Amazon Bedrock knowledge base you already run as a vector store, through the same endpoints.

Available Endpoints

Endpoint Method What It Does MCP Tool
/v1/vector_stores POST Create a vector store openai_vector_store_create
/v1/vector_stores GET List vector stores openai_vector_store_list
/v1/vector_stores/{vector_store_id} GET Retrieve a vector store openai_vector_store_get
/v1/vector_stores/{vector_store_id} POST Update name, metadata or expiration openai_vector_store_update
/v1/vector_stores/{vector_store_id} DELETE Delete a vector store openai_vector_store_delete
/v1/vector_stores/{vector_store_id}/search POST Search the indexed passages openai_vector_store_search
/v1/vector_stores/{vector_store_id}/files POST Attach a file openai_vector_store_file_create
/v1/vector_stores/{vector_store_id}/files GET List the attached files openai_vector_store_file_list
/v1/vector_stores/{vector_store_id}/files/{file_id} GET Retrieve an attached file openai_vector_store_file_get
/v1/vector_stores/{vector_store_id}/files/{file_id} POST Replace a file's attributes openai_vector_store_file_update
/v1/vector_stores/{vector_store_id}/files/{file_id} DELETE Detach a file openai_vector_store_file_delete
/v1/vector_stores/{vector_store_id}/files/{file_id}/content GET Read a file's indexed passages openai_vector_store_file_content
/v1/vector_stores/{vector_store_id}/file_batches POST Attach several files at once openai_vector_store_file_batch_create
/v1/vector_stores/{vector_store_id}/file_batches/{batch_id} GET Retrieve a file batch openai_vector_store_file_batch_get
/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel POST Cancel a file batch openai_vector_store_file_batch_cancel
/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/files GET List a file batch's files openai_vector_store_file_batch_file_list

Feature Compatibility

A store this server owns and a knowledge base store answer the same endpoints, but not always the same way. Where the two differ, the row says which one it is talking about.

Feature Status Notes
Creating a store
name, description Up to 256 and 512 characters
file_ids Up to 2000, indexed in the background; a rejected file leaves no store behind
chunking_strategy auto, or static with the bounds in Chunking; becomes the store's own strategy
expires_after anchor: "last_active_at" and a day count — see Expiration
metadata Up to 16 pairs, 64-character keys, 512-character values
Knowledge base stores An Amazon Bedrock knowledge base you already run, served through these same endpoints as vs_kb_...
Creating one of those A knowledge base is addressed, never created: no request field names one
Managing a store
Retrieve On a knowledge base store, name, description, creation time and status are read from it
Update name, metadata, expires_after expires_after: null clears the policy. 400 on a knowledge base store — the three are read from it
Delete 400 on a knowledge base store, which is managed outside this server
limit, order, after, before On every listing: 1 to 100, default 20, newest first — see Listing Order
filter on a file listing Returns only the files with the named status
Attaching a file
file_id A file uploaded with the Files API
attributes Up to 16 pairs within a 2048-byte budget. On a knowledge base store they are indexed and searchable but never reported back on the file, and the key stdapi-filename is reserved — 400
chunking_strategy on an attach 400 on a knowledge base store, which chooses its own passage boundaries
Replace a file's attributes Replaces the whole set. 400 on a knowledge base store — attach the file again with the attributes it should carry
Retrieve, detach Detaching a document of the corpus behind a knowledge base store is 400; it is removed where that corpus comes from
Read a file's indexed passages 400 on a knowledge base store — download the file itself instead
File batches
file_ids or files Exactly one of the two, up to 2000 entries; files carries per-file attributes and chunking_strategy. 400 on a knowledge base store
Batch-level attributes, chunking_strategy Applied to every file_ids entry
Retrieve, cancel, list a batch's files A cancel stops the files that have not started; the ones already indexed stay. 400 on a knowledge base store
Searching
query A string, or up to 16 strings searched together, on either kind of store
max_num_results 1 to 50, default 10
filters All eight comparison operators and both combinators, nestable, on either kind of store — see Filters
ranking_options.score_threshold 400 on a knowledge base store, whose relevance value is not comparable between searches; use max_num_results there
ranking_options.ranker Accepted and ignored — results are always ranked by the store's own relevance, and any value is taken
rewrite_query Accepted and ignored — the query is searched as written
has_more / next_page on a results page Always false and null: a search returns one complete page

Legend:

  • Supported — Fully compatible with OpenAI API
  • Partial — Supported with limitations
  • Unsupported — Not available in this implementation
  • Extra Feature — Enhanced capability beyond OpenAI API

Model Support

No request field names a model: a store embeds with the model it was built with, and a search embeds its query with that same one. Which model that is depends on the kind of store.

Store Embeds with
One this server owns VECTOR_STORE_EMBEDDING_MODEL, recorded on the store when it is created
A knowledge base store The embedding model of the knowledge base itself — the setting above is not used, and the knowledge base embeds the query on its side

Any model this deployment serves that produces embeddings is eligible. To shortlist them, call search_models with route=openai_embedding. A model that produces something else is refused with 400, naming it, when a store is created — never silently, and never at search time.

No reranking stage

A search is a single pass: the passages closest to the query, in that order. Nothing re-scores them afterwards, so ranking_options.ranker names no model and selects nothing — see the Rerank API to re-order results yourself. A Bedrock managed knowledge base may rerank inside its own retrieval, which is its behaviour rather than this server's.

Listing Order

Every listing — stores, a store's files, a batch's files — is ordered by the created_at it reports for each object, most recent first; order=asc reverses it. Objects sharing a second are ordered by identifier, so the sequence is stable from one page to the next.

Object created_at is
Store When the store was created.
File When the file was attached to that store — not when it was uploaded. Attaching the same file again moves it to the newest end.

The after and before cursors are positions in that order: after returns the objects that follow the named one, before the page that ends just before it, both in the direction order asks for. Neither restarts the listing from the top when the object it names has since been deleted.

Quick Start

import time

from openai import OpenAI

client = OpenAI(base_url="https://your-gateway/v1", api_key="YOUR_API_KEY")

uploaded = client.files.create(file=open("handbook.txt", "rb"), purpose="assistants")
store = client.vector_stores.create(name="handbook", file_ids=[uploaded.id])

# Indexing is asynchronous: wait until the store reports it finished.
deadline = time.monotonic() + 300
while client.vector_stores.retrieve(store.id).status == "in_progress":
    assert time.monotonic() < deadline, "indexing did not finish"
    time.sleep(2)

for result in client.vector_stores.search(
    store.id, query="How much parental leave do I get?"
):
    print(result.score, result.filename, result.content[0].text)

Indexing Is Asynchronous

Attaching a file returns immediately with status="in_progress". Poll the file, or the store, until it settles:

Object Field Settled when
Store status completed — no attached file is still being indexed.
Store file_counts in_progress reaches 0; the other counters sum to total.
File status completed, failed or cancelled.
Batch status / file_counts Same, for the files of that batch only.

The counters summarise the files, so they can trail a file that has just settled — a store still reporting in_progress for a file already completed converges within a moment. Poll the file itself when you need the earliest possible answer.

Indexing is bounded server-wide: attaching many files at once never indexes more than a couple at a time, so a large attach queues rather than being refused. A poll always terminates: a file whose indexing was interrupted and cannot be resumed settles as failed with last_error.code="server_error", and attaching it again indexes it.

Durable Indexing

Whether an interruption costs you anything depends on one deployment setting, AWS_SQS_VECTOR_STORE_QUEUE_URL:

Setting What happens when the server indexing a file is replaced
Unset (default) The file settles as failed. Attach it again.
Set Another server picks the work up and finishes it. The file stays in_progress a little longer, then settles as completed.

Nothing about the API changes: the same fields, the same statuses, the same polling. A file only takes longer to settle. Indexing stays at-least-once and never bills twice — work that already completed is not redone.

Ask your administrator which of the two your deployment runs before designing a client around it.

Supported Files

Files must be text: plain text, Markdown, source code, CSV, JSON, XML, YAML and anything else whose bytes decode as UTF-8 and whose content type is not a known binary one — a text file uploaded as application/octet-stream or application/pdf is refused on its content type, before its bytes are read.

A file that is not text settles as status="failed" with last_error.code="unsupported_file". The message names what that store indexes, and — when another kind of store would take the file as it stands — where to send it instead:

This file type cannot be indexed by this vector store. It indexes text only. Provide the content as a text file. A knowledge base store indexes this file type as it stands.

Convert documents to text otherwise — RAG Pipelines shows a document-conversion stage that produces Markdown from PDF and office formats.

last_error.code Meaning
unsupported_file The file is not one this store indexes.
invalid_file The file is text but holds nothing to index, or is too large.
server_error Indexing failed, or was interrupted; attach the file again.

A knowledge base store indexes more than text — PDF and office documents as they stand, and media on a Bedrock managed one. Its own refusals list the formats that store accepts.

Chunking

A file is split into overlapping passages before it is indexed. Send a chunking_strategy to choose the split:

{
  "type": "static",
  "static": {"max_chunk_size_tokens": 800, "chunk_overlap_tokens": 400}
}
Field Range Default
max_chunk_size_tokens 100 to 4096 800
chunk_overlap_tokens 0 to half the chunk size 400

"type": "auto" inherits the store's own strategy — the one given when it was created — which also applies to every file attached without a strategy at all. A store created without one falls back to the server default, which comes from VECTOR_STORE_CHUNK_SIZE_TOKENS.

Chunk sizes are approximate

The chunk size is applied as a text-length budget, and a cut is moved back to the nearest line or word boundary, so a passage never ends mid-word. The resulting passages therefore do not match another provider's split character for character. A passage is additionally capped by what the configured embedding model accepts in one input, so a very large max_chunk_size_tokens may produce shorter passages than asked for.

GET /v1/vector_stores/{id}/files/{file_id}/content returns the passages a file was indexed as, in document order — the fastest way to see what a chunking strategy actually produced.

Searching

page = client.vector_stores.search(
    store.id,
    query="parental leave",
    max_num_results=5,
    filters={"key": "department", "type": "eq", "value": "hr"},
    ranking_options={"score_threshold": 0.4},
)
Parameter Default Notes
query A string, or an array of strings searched together.
max_num_results 10 1 to 50.
filters A comparison or compound filter over the files' attributes.
ranking_options.score_threshold Drops results scoring below it.
ranking_options.ranker Accepted and ignored: results are always ranked by similarity.
rewrite_query false Accepted and ignored: the query is searched as written.

Each result carries file_id, filename, the file's attributes, the matching content, and a score between 0 and 1 where 1 is an exact match. Results are ordered best first, and the page is complete — search is never paginated.

Scores on a knowledge base store

On a vs_kb_... store the score is the relevance value the knowledge base measured, reported unchanged. It orders the results within one response and is not the 0-to-1 similarity above, so never compare it across stores or against a fixed threshold — ranking_options.score_threshold is refused on those stores for that reason.

Filters

type Matches
eq, ne Equal / not equal — string, number or boolean
gt, gte, lt, lte Numeric comparison — value must be a number
in, nin Value in / not in an array
and, or Combine filters, nestable

Filters apply to the attributes of the attached file, never to its content. A filter that matches nothing returns an empty page rather than an error, while an ordering operator given a non-numeric value is rejected with 400: store a date as a number (for example 20260115) to compare ranges of it.

Attributes

Up to 16 key-value pairs per attached file, with string, number or boolean values. They are returned on the file and on every search result, and are what filters matches against.

Limit Value
Key-value pairs 16
Key length 64
String value length 512
Total size of all attributes 2048 bytes

Attributes larger than the total budget are rejected with 400, naming the limit. POST /v1/vector_stores/{id}/files/{file_id} replaces the whole set; the new values apply to later searches once the file is completed. Replacing the attributes of a file that is still in_progress is accepted, but the indexing in flight writes the attributes it started with — wait for the file to settle, then replace them.

Expiration

{"expires_after": {"anchor": "last_active_at", "days": 7}}

expires_at is last_active_at plus days. Only a search refreshes last_active_at — attaching, reading or updating a store does not — so a store that is written to but never searched still expires. Once past its expiration a store reads back with status="expired" and returns no search result; its indexed content is released and a search never brings it back. Send "expires_after": null on an update to remove the policy.

Knowledge Base Stores

A vector store can also be served by an Amazon Bedrock knowledge base you already created. Allowlist it in AWS_BEDROCK_KNOWLEDGE_BASE_IDS and it is addressed as the vector store vs_kb_<knowledgeBaseId> — the knowledge base identifier is ten alphanumeric characters — on every /v1/vector_stores endpoint, and returned by GET /v1/vector_stores next to the stores the server owns.

Amazon Bedrock builds a knowledge base over documents in two ways, and both are served:

Knowledge base API type
Bedrock managed — Amazon Bedrock owns the datastore, the embedding model, the parser and the reranker MANAGED
Customer-managed — you provision the vector store and choose the embedding model VECTOR

They differ in two things a client can see; everything else on this page holds for either.

A structured-data knowledge base is not one of them

A knowledge base connected to a structured data store (SQL) answers a query with database rows rather than passages, and one backed by an Amazon Kendra GenAI index (KENDRA) is a search index rather than a vector store. Neither is served here — allowlist only the two above.

The knowledge base stays yours. It is addressed, never created and never deleted; the server searches it and manages the documents of its data source. Its name, description, creation time and status are read from the knowledge base itself.

Attaching a file needs a custom data source

A file attached through this API becomes an in-line document, which only a custom data source takes — on either kind. Point the allowlist entry at one, as <knowledgeBaseId>/<dataSourceId>; pointed at a data source that syncs its corpus from a bucket or another service, the store answers 400 to an attach and keeps serving search, listing and reading. A knowledge base can hold both kinds.

store = client.vector_stores.retrieve("vs_kb_ABCDE12345")

uploaded = client.files.create(file=open("handbook.pdf", "rb"), purpose="assistants")
client.vector_stores.files.create(
    vector_store_id=store.id, file_id=uploaded.id, attributes={"department": "hr"}
)

for result in client.vector_stores.search(
    store.id, query="How much parental leave do I get?", max_num_results=5
):
    print(result.score, result.filename, result.content[0].text)

What Works

Request On a vs_kb_... store
GET /v1/vector_stores Lists it alongside the stores the server owns.
GET /v1/vector_stores/{id} Name, description, creation time and status, as the knowledge base reports them.
POST /v1/vector_stores/{id}/files Attaches an uploaded file: it becomes a document of the knowledge base's custom data source, with its attributes kept searchable.
GET /v1/vector_stores/{id}/files Lists the documents of the store's data source, including the ones put there outside this API.
GET /v1/vector_stores/{id}/files/{file_id} Retrieves one document, including one a search returned from elsewhere in the knowledge base.
DELETE /v1/vector_stores/{id}/files/{file_id} Removes a document this API attached.
POST /v1/vector_stores/{id}/search Searches it, with filters and max_num_results.

filters works in full: all eight comparison operators (eq, ne, gt, gte, lt, lte, in, nin) and both combinators (and, or), over any metadata key, with no schema to declare beforehand.

What Is Refused

Request Answer
POST /v1/vector_stores creating one Not creatable: the store is addressed, never created. No request field names a knowledge base.
DELETE /v1/vector_stores/{id} 400 — the store is managed outside the server.
POST /v1/vector_stores/{id} (name, metadata, expires_after) 400 — they are read from the knowledge base.
chunking_strategy on an attach 400 — the store chooses its own passage boundaries.
POST /v1/vector_stores/{id}/files/{file_id} (attribute rewrite) 400 — attach the file again with the attributes it should carry.
GET /v1/vector_stores/{id}/files/{file_id}/content 400 — the passages a file was indexed as cannot be listed. Download the file itself with the Files API.
POST /v1/vector_stores/{id}/files on a store whose data source syncs its corpus 400 — that corpus is maintained where it comes from. Use a store this server owns, or ask for one that accepts uploads.
DELETE /v1/vector_stores/{id}/files/{file_id} on a document of the corpus 400 — it was not attached here, and is removed where the corpus comes from.
POST /v1/vector_stores/{id}/file_batches and the other batch routes 400 — attach and follow files one at a time.
ranking_options.score_threshold 400 — the store's relevance scores are not comparable between searches; use max_num_results instead.
A query over the length limit 400 naming the limit. The query is never truncated.

usage_bytes, file_counts, and a file's chunking_strategy and attributes are reported as unknown — zero, or absent — rather than invented: the corpus is yours, and the server does not claim to know what it holds.

A document's created_at is the only time the knowledge base reports for it: the instant it last ingested that document, which for a document ingested once is when it was created. The document listing is ordered on that same value, so a page never reports a time that contradicts its own order.

Identifiers

A file you attach keeps its own file-... identifier. A document that was already in the knowledge base — one of the corpus behind it — is reported under an opaque kbdoc_... identifier, and the per-file routes accept it.

A search covers the whole knowledge base, not only the documents attached here, so a result may name a document of a corpus this API never wrote to. Its kbdoc_... identifier still reads back: GET /v1/vector_stores/{id}/files/{file_id} answers for it, wherever in the knowledge base it lives. Removing it is the one thing refused — that corpus is maintained where it comes from.

Document Formats

Files are indexed as they stand, with no conversion step:

Formats Indexed by
.txt, .md, .html, .csv, .doc, .docx, .xls, .xlsx, .pdf Every knowledge base
.ppt, .pptx, images, audio and video A Bedrock managed knowledge base, additionally
Anything else whose bytes decode as text Every knowledge base, indexed as text

One file is at most 5 MiB.

A format outside that table is refused when the file is attached — 400, naming the formats this store takes — rather than accepted and then reported as failed. A file that is attached and then fails is one of a format the store does take, so it settles with last_error.code="server_error".

Where the Two Kinds Differ

Only two things differ from the client's point of view:

Difference Customer-managed Bedrock managed
Document formats indexed The table above Also .ppt, .pptx, images, audio, video
query length 1,000 characters 10,000 characters

Cost

A knowledge base search costs more than a search on a store the server owns, and a knowledge base backed by an always-on vector database bills whether it is queried or not. This is information for choosing between the two, not a recommendation.

What the usage log reports differs per kind, because the retrieval runs inside the knowledge base rather than through an embedding model of the server's:

Knowledge base Search Attaching a file
Bedrock managed One search_units unit per query, at the published flat rate Not reported: index storage is billed monthly per GB
Customer-managed Not reported: no per-retrieval rate is published for it Not reported: billed by its own embedding model

Everything left unreported is on your AWS bill and readable from AWS Cost Explorer. Full detail in Cost Management.

Limits

Limit Value
Files per file batch 2000
Queries per search 16
Results per search 50
Store metadata 16 pairs, 64-character keys, 512-character values
File size 100 MiB, or MAX_INPUT_FILE_SIZE when it is lower

A file above the size limit is not rejected at request time: it settles as status="failed" with last_error.code="invalid_file", like any other file that cannot be indexed.

Errors

Status When
400 Attributes above the total budget, a chunking strategy outside its bounds, a gt/gte/lt/lte filter given a non-numeric value, or a request a knowledge base store does not accept.
404 An identifier that names no store, attached file or batch. A vs_kb_... identifier that is not allowlisted answers exactly like any unknown store.
409 The store is being updated concurrently by another request; retry it.
503 The deployment has no vector storage configured.

Prerequisites

Vector stores are stored in your own AWS account, in an Amazon S3 vector bucket you create yourself. Set AWS_S3_VECTORS_BUCKET to its name and AWS_S3_VECTORS_REGION to its Region; the endpoints answer 503 until both a vector bucket and AWS_S3_BUCKET are configured. The gateway's IAM role needs the Vector Stores permissions.

The model that turns text into vectors is VECTOR_STORE_EMBEDDING_MODEL. It is recorded on each store when the store is created, so changing the setting only affects stores created afterwards — existing stores keep answering with the model they were built with.

Indexing survives a server being replaced only when AWS_SQS_VECTOR_STORE_QUEUE_URL names an Amazon SQS queue you created, with the durable indexing permissions on it — see Durable indexing.

Knowledge base stores need none of the above: they need AWS_BEDROCK_KNOWLEDGE_BASE_IDS, the knowledge base permissions, and a knowledge base in the first AWS_BEDROCK_REGIONS entry. They bring their own storage and their own embedding model, and they are listed and served even when no vector bucket is configured.

See Also