← Blog

Claude API Embeddings & Vector Database Integration

2026-10-24 · 5 min read · SubToAPI Team

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:

  1. 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 like bge-large / e5-large run locally.
  2. Vector database — stores those vectors and performs similarity search. Options include Pinecone, Weaviate, Qdrant, Chroma, pgvector (Postgres extension), or Milvus.
  3. 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

Choosing a vector database

For most teams starting out, the decision comes down to operational overhead versus scale:

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.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →