Vector stores
Managed, OpenAI-compatible knowledge bases — upload files, we chunk, embed, and search them
A managed retrieval layer: attach files and Melious chunks, embeds, and indexes them so you can search by meaning. OpenAI-compatible — the openai SDK works unmodified, including the create_and_poll / upload_and_poll helpers. A vector store is a private, vault-encrypted knowledge base; you can also manage the same stores in your Melious account.
Base path: /v1/vector_stores
Auth: Bearer token or x-api-key. Requires vault access on the key, plus scope kit.knowledge.read (search/read) or kit.knowledge.write (create/attach/delete).
Vector stores are end-to-end encrypted, so the API key must have vault access enabled (toggle it in Account → API keys while your vault is unlocked). A key without it returns 403:
{
"error": {
"message": "This API key lacks vault access. Enable 'vault access' for the key in account settings to create or use vector stores.",
"type": "authentication_error",
"param": null,
"code": "insufficient_permissions"
}
}Create a store
POST /v1/vector_stores| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | Display name. |
file_ids | string[] | no | Files to attach at creation. |
expires_after | object | no | { "anchor": "last_active_at", "days": <positive int> }. |
chunking_strategy | object | no | { "type": "auto" } or { "type": "static", "static": { "max_chunk_size_tokens", "chunk_overlap_tokens" } }. |
metadata | object | no | Up to 16 key-value pairs. |
from openai import OpenAI
client = OpenAI(api_key="sk-mel-<YOUR_API_KEY>", base_url="https://api.melious.ai/v1")
vs = client.vector_stores.create(name="Company Handbook")
client.vector_stores.files.create_and_poll(vector_store_id=vs.id, file_id="file-abc123")curl https://api.melious.ai/v1/vector_stores \
-H "Authorization: Bearer sk-mel-<YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"name": "Company Handbook", "file_ids": ["file-abc123"]}'Response:
{
"id": "9195f348-323e-47a4-ae32-95489a1b2c3d",
"object": "vector_store",
"created_at": 1699999999,
"name": "Company Handbook",
"usage_bytes": 0,
"file_counts": { "in_progress": 0, "completed": 1, "failed": 0, "cancelled": 0, "total": 1 },
"status": "completed",
"expires_after": { "anchor": "last_active_at", "days": 30 },
"expires_at": 1702591999,
"metadata": {}
}Vector store IDs are UUIDs. The vs_… placeholder in the examples below stands for the id returned here.
List, retrieve, update, delete
GET /v1/vector_stores # list (limit 1–100, order asc/desc, after/before cursors)
GET /v1/vector_stores/{id} # retrieve
POST /v1/vector_stores/{id} # update name / metadata / expires_after
DELETE /v1/vector_stores/{id} # deleteclient.vector_stores.update("vs_...", name="Renamed", metadata={"team": "hr"})
client.vector_stores.delete("vs_...")Attach a file
POST /v1/vector_stores/{id}/filesThe file is fetched, parsed, chunked, embedded, and indexed. The returned vector_store.file keeps the same id as the file_id you attached.
| Field | Type | Description |
|---|---|---|
file_id | string | The uploaded file to attach. |
attributes | object | Per-file metadata used for search filtering. |
chunking_strategy | object | Override the store's chunking for this file. |
vsf = client.vector_stores.files.create_and_poll(
vector_store_id="vs_...",
file_id="file-abc123",
attributes={"category": "finance", "year": 2025},
)
assert vsf.id == "file-abc123"curl https://api.melious.ai/v1/vector_stores/vs_.../files \
-H "Authorization: Bearer sk-mel-<YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"file_id": "file-abc123", "attributes": {"category": "finance"}}'Attaching the same file_id twice is idempotent. Two different files with identical content are both kept.
Direct ingest (Melious extensions)
Skip the separate upload, or ingest a URL / raw text straight into a store:
# Upload a file directly into the store
curl https://api.melious.ai/v1/vector_stores/vs_.../files/upload \
-H "Authorization: Bearer sk-mel-<YOUR_API_KEY>" -F file=@handbook.pdf
# Scrape + ingest a web page
curl https://api.melious.ai/v1/vector_stores/vs_.../sources/url \
-H "Authorization: Bearer sk-mel-<YOUR_API_KEY>" -d '{"url": "https://example.com/docs"}'
# Ingest raw text
curl https://api.melious.ai/v1/vector_stores/vs_.../sources/text \
-H "Authorization: Bearer sk-mel-<YOUR_API_KEY>" -d '{"name": "note", "text": "Paris is the capital of France."}'File operations
GET /v1/vector_stores/{id}/files # list
GET /v1/vector_stores/{id}/files/{file_id} # retrieve
POST /v1/vector_stores/{id}/files/{file_id} # update attributes
GET /v1/vector_stores/{id}/files/{file_id}/content # parsed chunk text
DELETE /v1/vector_stores/{id}/files/{file_id} # detachfiles.content returns the parsed text in OpenAI's page shape:
{
"object": "vector_store.file_content.page",
"data": [{ "type": "text", "text": "..." }],
"has_more": false,
"next_page": null
}File batches
Attach many files in one call; batches are persisted, so the poll / retrieve helpers work.
POST /v1/vector_stores/{id}/file_batches # create
GET /v1/vector_stores/{id}/file_batches/{batch_id} # retrieve
GET /v1/vector_stores/{id}/file_batches/{batch_id}/files # list files in the batch
POST /v1/vector_stores/{id}/file_batches/{batch_id}/cancelbatch = client.vector_stores.file_batches.create_and_poll(
vector_store_id="vs_...", file_ids=["file-1", "file-2"]
)
print(batch.status, batch.file_counts){
"id": "vsfb_abc123",
"object": "vector_store.file_batch",
"created_at": 1699999999,
"vector_store_id": "vs_...",
"status": "completed",
"file_counts": { "in_progress": 0, "completed": 2, "failed": 0, "cancelled": 0, "total": 2 }
}Search
POST /v1/vector_stores/{id}/search| Field | Type | Default | Description |
|---|---|---|---|
query | string | — | Search query (required, non-empty). |
max_num_results | integer | 10 | Max results. |
filters | object | none | Attribute filter (see below). |
rewrite_query | boolean | false | Rewrite the query for better recall. |
results = client.vector_stores.search(
"vs_...",
query="What is the vacation policy?",
max_num_results=5,
filters={"type": "eq", "key": "category", "value": "hr"},
)
for r in results.data:
print(r.file_id, r.score, r.content[0]["text"][:100])curl https://api.melious.ai/v1/vector_stores/vs_.../search \
-H "Authorization: Bearer sk-mel-<YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"query": "vacation policy", "max_num_results": 5}'Filters
Filter on the attributes you set on files. Comparison and compound filters are supported:
// comparison — type ∈ eq | ne | gt | gte | lt | lte
{ "type": "eq", "key": "category", "value": "hr" }
// compound — type ∈ and | or
{ "type": "and", "filters": [
{ "type": "eq", "key": "category", "value": "hr" },
{ "type": "gte", "key": "year", "value": 2024 }
] }An invalid filter (unknown type, missing key/value, empty compound) returns 400.
Response:
{
"object": "vector_store.search_results",
"search_query": "vacation policy",
"data": [
{
"file_id": "file-abc123",
"filename": "handbook.pdf",
"score": 0.83,
"content": [{ "type": "text", "text": "Employees accrue 25 days..." }],
"attributes": { "category": "hr" }
}
]
}Use in chat (file_search)
The same stores power the built-in file_search tool: when enabled, the model searches your configured stores during a chat completion and grounds its answer in the results. The tool takes a query (and optional max_num_results); which stores it searches is part of your assistant/tool configuration.
Billing
Storage is billed by processed size (chunk text + embeddings) per GB-day, time-weighted — you pay for the time data is stored. Each plan includes a free allowance; usage beyond it is charged from your credit balance. See Pricing. If an account stays negative on storage past the grace window, its stores are removed.
Errors
All errors use the OpenAI envelope { "error": { "message", "type", "param", "code" } }.
- 400
invalid_request_error— emptyquery, invalidfilters, or non-positiveexpires_after.days. - 401
authentication_error— missing or invalid API key. - 403
authentication_error— the key lacks vault access. - 404
invalid_request_error— store, file, or batch not found.
Related
Files for the upload side • Chat completions for the file_search tool • Embeddings and Rerank if you'd rather build retrieval yourself • Privacy and data residency for how stored content is handled.