Claude API Embeddings & Vector Database Integration
Does Claude have an embeddings API?
No. Claude's API handles text generation, tool use, and vision — it does not expose an embeddings endpoint. If you're building retrieval-augmented generation (RAG), semantic search, or a knowledge base chatbot, you need a separate embedding model to generate vectors, a vector database to store and query them, and Claude to generate the final answer from the retrieved context. This is a standard three-piece architecture, and it's actually more flexible than a single "all-in-one" embeddings API would be, because you can swap any piece independently.
This article covers the practical setup: which embedding models work well with Claude, how to wire up a vector database, and a complete retrieval pipeline you can adapt.
The architecture: embeddings + vector DB + Claude
A Claude-powered RAG pipeline has three distinct jobs:
- Embedding model — converts text chunks into numeric vectors. Common choices: OpenAI's
text-embedding-3-small/large, Voyage AI (Anthropic's recommended partner for embeddings), or open-source models likebge-large/e5-largerun locally. - Vector database — stores those vectors and performs similarity search. Options include Pinecone, Weaviate, Qdrant, Chroma, pgvector (Postgres extension), or Milvus.
- Claude — receives the user's question plus the top-k retrieved chunks as context, and generates a grounded answer.
Claude never touches the vectors directly. It only ever sees plain text — the retrieved chunks get inserted into the prompt as context.
Why Voyage AI is a common pairing
Anthropic has publicly recommended Voyage AI embeddings for Claude-based RAG systems, partly because Voyage models are tuned on similar data distributions and perform well on retrieval benchmarks for technical and business documents. That said, any embedding model works — the embedding step is model-agnostic from Claude's perspective.
Step 1: Chunk and embed your documents
Split documents into chunks of roughly 300–800 tokens with some overlap (50–100 tokens) so you don't cut sentences mid-thought at chunk boundaries.
import { VoyageAIClient } from "voyageai";
const voyage = new VoyageAIClient({ apiKey: process.env.VOYAGE_API_KEY });
async function embedChunks(chunks) {
const response = await voyage.embed({
input: chunks,
model: "voyage-3",
inputType: "document",
});
return response.data.map((d) => d.embedding);
}
Step 2: Store vectors in your database
Using Qdrant as an example (the pattern is nearly identical across providers):
await qdrantClient.upsert("docs_collection", {
points: chunks.map((chunk, i) => ({
id: chunk.id,
vector: embeddings[i],
payload: { text: chunk.text, source: chunk.source },
})),
});
If you're already on Postgres, pgvector lets you skip adding a new infrastructure dependency entirely — a single vector column and an ivfflat or hnsw index is often enough for mid-size document sets (under a few million chunks).
Step 3: Retrieve and query Claude
At query time, embed the user's question with the same embedding model, run a similarity search, and pass the top results to Claude as context.
async function askWithRAG(question) {
const [queryEmbedding] = await embedChunks([question]);
const results = await qdrantClient.search("docs_collection", {
vector: queryEmbedding,
limit: 5,
});
const context = results
.map((r) => `Source: ${r.payload.source}\n${r.payload.text}`)
.join("\n\n---\n\n");
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SUBTOAPI_KEY}`,
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-5",
max_tokens: 1024,
system:
"Answer only using the provided context. If the context doesn't contain the answer, say so.",
messages: [
{
role: "user",
content: `Context:\n${context}\n\nQuestion: ${question}`,
},
],
}),
});
return response.json();
}
This separates concerns cleanly: the vector database handles retrieval, Claude handles reasoning and synthesis. If you're routing API calls for this pipeline through SubToAPI, you get the same /v1/messages interface backed by your existing Claude access, with application-scoped keys so you can issue a separate key per RAG service or environment and track usage per key from the dashboard. See the quickstart and the messages endpoint docs for request/response details.
Practical tips for production RAG with Claude
- Re-embed consistently. If you change embedding models, you must re-embed your entire corpus — vectors from different models aren't comparable.
- Keep chunk metadata. Store source filenames, page numbers, and timestamps alongside vectors so Claude's answers can cite sources and you can debug bad retrievals.
- Use a reranker for precision-sensitive use cases. A cheap vector search followed by a reranking pass (e.g., Voyage's rerank API or Cohere's) often outperforms pulling more top-k results into Claude's context window.
- Cap context size deliberately. Dumping 20 retrieved chunks into every prompt increases cost and latency without improving answer quality. Five well-ranked chunks usually beats fifteen mediocre ones.
- Stream the final answer. Once Claude starts generating from the retrieved context, streaming the response improves perceived latency, especially for longer answers. See streaming docs if you're using SubToAPI's streaming endpoint.
- Let Claude call tools for live data. If some of your "retrieval" is really a live database lookup rather than static document search, Claude's tool use can trigger a function call directly instead of pre-computing embeddings for data that changes constantly.
Choosing a vector database
For most teams starting out, the decision comes down to operational overhead versus scale:
- pgvector — best if you already run Postgres and have under a few million vectors. Zero new infrastructure.
- Qdrant / Weaviate — good for self-hosted or open-source-first setups with strong filtering support.
- Pinecone — fully managed, scales to hundreds of millions of vectors, less ops burden but a separate bill.
- Chroma — simplest for prototyping and local development, not ideal for high-scale production.
Start with pgvector or Chroma for an MVP, then migrate to a dedicated vector database once query volume or corpus size demands it. Migration mainly means re-indexing — the embedding and Claude-querying code barely changes.
Questions
Does Claude generate embeddings itself? No. Claude's API only handles generation, tool use, and vision. You need a separate embedding model (Voyage AI, OpenAI, or open-source) to produce vectors for retrieval.
Which vector database works best with Claude? Any of them — pgvector, Pinecone, Qdrant, Weaviate, and Chroma are all commonly used. The choice depends on your scale and ops preferences, not on Claude compatibility, since Claude only ever receives plain-text context.
Can SubToAPI generate embeddings for me? No — SubToAPI exposes Claude's messages, streaming, and tool-use API as a clean HTTPS endpoint. For embeddings, pair it with a dedicated embedding provider and vector database, then send retrieved context to Claude via /v1/messages.