Melious
API Reference

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
FieldTypeRequiredDescription
namestringnoDisplay name.
file_idsstring[]noFiles to attach at creation.
expires_afterobjectno{ "anchor": "last_active_at", "days": <positive int> }.
chunking_strategyobjectno{ "type": "auto" } or { "type": "static", "static": { "max_chunk_size_tokens", "chunk_overlap_tokens" } }.
metadataobjectnoUp 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}       # delete
client.vector_stores.update("vs_...", name="Renamed", metadata={"team": "hr"})
client.vector_stores.delete("vs_...")

Attach a file

POST /v1/vector_stores/{id}/files

The file is fetched, parsed, chunked, embedded, and indexed. The returned vector_store.file keeps the same id as the file_id you attached.

FieldTypeDescription
file_idstringThe uploaded file to attach.
attributesobjectPer-file metadata used for search filtering.
chunking_strategyobjectOverride 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}         # detach

files.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}/cancel
batch = 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 }
}
POST /v1/vector_stores/{id}/search
FieldTypeDefaultDescription
querystringSearch query (required, non-empty).
max_num_resultsinteger10Max results.
filtersobjectnoneAttribute filter (see below).
rewrite_querybooleanfalseRewrite 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" }
    }
  ]
}

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 — empty query, invalid filters, or non-positive expires_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.

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.

On this page