Skip to main content

Overview

Perplexity’s Embeddings API generates high-quality text embeddings for semantic search and retrieval. Choose between standard embeddings for independent texts or contextualized embeddings for document chunks that share context.
We recommend using our official SDKs for a more convenient and type-safe way to interact with the Embeddings API.

Pricing

Pay-as-you-go pricing for all APIs. No subscription required.

Available Models

All models use mean pooling and require no instruction prefix—you can embed text directly without prompt engineering.
Perplexity embeddings are unnormalized. Always compare base64_int8 embeddings via cosine similarity (not inner product or L2 distance). Compare base64_binary embeddings via Hamming distance. See Best Practices for details and normalization helpers.
When to use which:
  • Standard embeddings (pplx-embed-v1-*) - Independent texts, search queries, single sentences
  • Contextualized embeddings (pplx-embed-context-v1-*) - Document chunks that benefit from shared context (e.g., paragraphs from the same article)

Installation

Authentication

Set your API key as an environment variable:
Confirm the key is set without printing it:
Never print the key or any part of it. Commands like env, echo $PERPLEXITY_API_KEY, or a prefix or length check leave the key in shell history, logs, and coding-agent transcripts. Read the key from the environment in code and tests, and don’t paste it into fixtures or commit messages.

Add embeddings to an existing project

A standalone script that embeds a few strings and prints vectors proves the key works, but nothing in your app calls it, so your users never see a result. Instead, one module owns the client, an indexing function takes the records your app already has and saves each vector where that record already lives, and an existing route or view calls a ranking function that reads those stored vectors. The example below adds related help articles to a support app, with Python under app/ and TypeScript under src/.
1

Create one embeddings module

Put the client in a single module so the model ID, batching, decoding, and similarity metric live in one place. The library reads PERPLEXITY_API_KEY from the environment; do not pass the key in code or commit it. embed returns the base64 int8 strings the API sends back. Store that string with the record (a text column, a JSON field, or a document property) and decode it when you compare.Python: app/embeddings.py. TypeScript: src/embeddings.ts.
2

Index the records your app already has, then rank from storage

Two functions, both working against the app’s existing article store. index_articles embeds every article that has body text and no vector yet and saves the vector on that article through the store the app already uses. related_articles embeds only the incoming question and ranks the stored vectors. Neither builds its own client, and the embedding function is a parameter with a default so tests can pass a fake. When an article’s body changes, clear its stored embedding (None in Python, null in TypeScript) in the same update so the next index_articles run embeds the new text.Python: app/support/related_articles.py. TypeScript: src/support/relatedArticles.ts.
Then call it from the route or view that already renders the ticket. The change in the existing handler is one call plus one response field:
3

Test the caller, then run the whole suite

Test the feature, not the API. With an in-memory store and a fake embedding function, check that indexing saves a vector on each article that lacked one, and that ranking uses cosine similarity (a large-magnitude vector must not win on dot product alone). One live check runs only when PERPLEXITY_API_KEY is set.Python: tests/test_related_articles.py. TypeScript: tests/relatedArticles.test.ts.
Run the new test, then the project’s full test command, so the change is checked the same way the rest of the app is:

Prepare vectors for a vector database

The steps above store the base64 string the API returns and decode it when they compare. Most vector databases want float vectors at insert time instead. The adapter below decodes each base64 int8 string into a float32 row, one row per input text in input order, and pairs each row with its record id. It stops there: it does not create a collection or write to a database. Casting the int8 values to float does not restore a full-precision embedding: you store the same quantized vector in a wider type, and cosine similarity still applies. To hand these records to a database:
  • Create the collection or index with the embedding dimension: 2560 for pplx-embed-v1-4b, 1024 for pplx-embed-v1-0.6b, or the dimensions value you requested.
  • Map each record to your database’s upsert shape. Field names and id rules differ: Pinecone expects values, and Qdrant expects vector with integer or UUID ids.
  • Use cosine similarity. If the database only supports inner product, L2-normalize both the stored vectors and the query vectors first (see Best Practices).
The Python example uses NumPy, and the TypeScript example uses Node.js (Buffer). Both stop with an error if the response is missing an embedding.
For contextualized embeddings of chunks from one document, Matryoshka dimension reduction, binary embeddings and Hamming distance, and the RAG pattern, see Best Practices.

Next Steps

Standard Embeddings

Embed independent texts, queries, and sentences.

Contextualized Embeddings

Document-aware embeddings for chunks that share context.

Best Practices

Batch processing, caching, RAG patterns, and performance optimization.

Model Cards

See the model cards on HuggingFace.