Skip to Content
Quickstart
Raw

Quickstart — your first vector search

By the end of this page you will have created a collection in the Aetherfy vector database, stored three documents in it, and printed ranked search results. Every step is copy-pasteable in order, and the whole thing runs in one sitting.

Aetherfy exposes a Qdrant-compatible vector API through a Python SDK, a JS/TS SDK, and plain HTTP. This tutorial covers the two SDKs side by side — follow whichever language you use; the steps are the same.

Step 1 — Get your Aetherfy API key

Sign up or sign in at app.aetherfy.com/login  with email or GitHub.

On first login, the Aetherfy welcome modal reveals your default API key’s plaintext. You see that plaintext exactly once. Aetherfy never stores it after that single reveal — only a hash of it — so nobody, including Aetherfy support, can show it to you again. Copy it somewhere safe immediately.

If you lose the key, you cannot recover it; create a replacement at app.aetherfy.com/dashboard/settings/api-keys .

Your Aetherfy API key’s plaintext is shown once, at first login, and is never stored afterwards. If you lose it, create a new key at Settings → API keys .

Aetherfy keys look like afy_live_... for live traffic, or afy_test_... for test traffic. Export the key in your shell:

export AETHERFY_API_KEY="afy_live_your_api_key_here"

Both Aetherfy SDKs read the AETHERFY_API_KEY environment variable automatically, so you never have to pass the key in code.

Step 2 — Install an Aetherfy SDK

The Python and JS/TS clients for Aetherfy are published separately.

Python

The distribution name is aetherfy-vectors; the import package is aetherfy_vectors. Python 3.9 or newer is required.

pip install aetherfy-vectors

JavaScript / TypeScript

The Aetherfy package is unscoped — it is aetherfy-vectors. Node 20 or newer is required.

npm install aetherfy-vectors

Step 3 — Construct the Aetherfy client

Constructing a client takes no arguments, because it reads AETHERFY_API_KEY from the environment.

Python

The Aetherfy Python client is synchronous — no async/await anywhere.

Note that VectorConfig and DistanceMetric are not re-exported from the root package: import them from aetherfy_vectors.models.

from aetherfy_vectors import AetherfyVectorsClient from aetherfy_vectors.models import VectorConfig, DistanceMetric client = AetherfyVectorsClient() # reads AETHERFY_API_KEY

JavaScript / TypeScript

Every method on the Aetherfy JS client is async and returns a promise.

import { AetherfyVectorsClient, DistanceMetric } from 'aetherfy-vectors'; const client = new AetherfyVectorsClient(); // reads AETHERFY_API_KEY

Step 4 — Bring your own embeddings to Aetherfy

Aetherfy stores and searches vectors; it does not generate them. You bring your own embeddings from whichever model you already use.

Throughout this tutorial an embed() function stands in for that model. It is a stub you fill in, and it must return a list of floats whose length matches the size you give the collection in the next step. This tutorial uses 384, a common embedding dimension — change it to match your model.

Aetherfy does not generate embeddings. Fill in the embed() stub with a call to your own embedding model, and make sure it returns exactly as many floats as the collection’s size.

Step 5 — Create an Aetherfy collection

A collection is the container that holds your points. It is created once, with a fixed vector size and distance metric.

size must match the dimension of the embedding model behind embed(). Aetherfy enforces no dimension cap. There are four metrics: DistanceMetric.COSINE, DistanceMetric.EUCLIDEAN, DistanceMetric.DOT, and DistanceMetric.MANHATTAN. Cosine is the usual choice for normalised text embeddings; the SDK reference lists what each one stores.

Python

client.create_collection( "quickstart", VectorConfig(size=384, distance=DistanceMetric.COSINE), )

JavaScript / TypeScript

await client.createCollection('quickstart', { size: 384, distance: DistanceMetric.COSINE, });

Step 6 — Upsert points into Aetherfy

A point is an id, a vector, and an optional payload of metadata you can filter on later. Upserting is idempotent by point id, so re-running the script updates the same three points rather than duplicating them.

An Aetherfy point id is an unsigned integer up to 2**53 − 1, or a UUID string — nothing else. A slug such as "doc-001" is rejected by the SDK validator before the request is sent, so use 1, 2, 3 or real UUIDs.

Point ids must be an unsigned integer up to 2**53 − 1, or a UUID string. A slug like "doc-001" is rejected by the Aetherfy SDK validator.

Aetherfy accepts up to 10 000 points per upsert call.

Python

points = [ {"id": 1, "vector": embed("some text"), "payload": {"text": "some text"}}, ] client.upsert("quickstart", points)

JavaScript / TypeScript

const points = [ { id: 1, vector: await embed('some text'), payload: { text: 'some text' } }, ]; await client.upsert('quickstart', points);

Step 7 — Search your Aetherfy collection

This is the payoff. Searching an Aetherfy collection takes a query vector — produced by the same embedding model that produced the stored vectors — and returns the nearest points, best match first.

Each result carries id, score, payload, and vector. Ask for with_payload / withPayload so the metadata comes back with the hit; otherwise you get an id and a score and have to look the content up yourself.

Python

Returns a List[SearchResult], each with .id, .score, .payload, .vector.

results = client.search( collection_name="quickstart", query_vector=embed("how do I filter by metadata?"), limit=5, with_payload=True, )

JavaScript / TypeScript

Returns a SearchResult[], each with id, score, payload, vector.

const results = await client.search('quickstart', queryVector, { limit: 5, withPayload: true, });

The complete Python script for Aetherfy

Save this as aetherfy_quickstart.py, fill in embed(), and run it with python aetherfy_quickstart.py. It creates the collection, stores three short documents, searches them, and prints ranked results.

"""Aetherfy quickstart: create a collection, upsert documents, search them.""" import os # Or export AETHERFY_API_KEY in your shell instead. An already-exported key wins. os.environ.setdefault("AETHERFY_API_KEY", "afy_live_your_api_key_here") from aetherfy_vectors import AetherfyVectorsClient from aetherfy_vectors.models import VectorConfig, DistanceMetric COLLECTION = "quickstart" EMBEDDING_SIZE = 384 def embed(text: str) -> list: """Turn text into a list of EMBEDDING_SIZE floats. Aetherfy does not generate embeddings — you bring your own vectors. Replace this body with a call to your embedding model, and make sure it returns exactly EMBEDDING_SIZE floats. """ raise NotImplementedError(f"Fill in embed() with your model; got: {text!r}") DOCUMENTS = [ {"id": 1, "text": "Cosine distance compares the angle between two vectors."}, {"id": 2, "text": "A collection stores points, and every point has a vector."}, {"id": 3, "text": "Payload fields let you filter search results by metadata."}, ] def main() -> None: client = AetherfyVectorsClient() # reads AETHERFY_API_KEY client.create_collection( COLLECTION, VectorConfig(size=EMBEDDING_SIZE, distance=DistanceMetric.COSINE), ) points = [ { "id": doc["id"], "vector": embed(doc["text"]), "payload": {"text": doc["text"]}, } for doc in DOCUMENTS ] client.upsert(COLLECTION, points) results = client.search( collection_name=COLLECTION, query_vector=embed("how do I filter by metadata?"), limit=5, with_payload=True, ) for result in results: print(f"{result.score:.4f} #{result.id} {result.payload['text']}") client.close() if __name__ == "__main__": main()

The complete JavaScript/TypeScript script for Aetherfy

Save this as aetherfy-quickstart.ts, fill in embed(), and run it with your usual TypeScript toolchain. The imports are ESM, so set "type": "module" in your package.json. It creates the collection, stores three short documents, searches them, and prints ranked results.

/** Aetherfy quickstart: create a collection, upsert documents, search them. */ import { AetherfyVectorsClient, DistanceMetric } from 'aetherfy-vectors'; const COLLECTION = 'quickstart'; const EMBEDDING_SIZE = 384; /** * Turn text into an array of EMBEDDING_SIZE floats. * * Aetherfy does not generate embeddings — you bring your own vectors. Replace * this body with a call to your embedding model, and make sure it returns * exactly EMBEDDING_SIZE floats. */ async function embed(text: string): Promise<number[]> { throw new Error(`Fill in embed() with your model; got: ${text}`); } const DOCUMENTS = [ { id: 1, text: 'Cosine distance compares the angle between two vectors.' }, { id: 2, text: 'A collection stores points, and every point has a vector.' }, { id: 3, text: 'Payload fields let you filter search results by metadata.' }, ]; async function main(): Promise<void> { const client = new AetherfyVectorsClient(); // reads AETHERFY_API_KEY await client.createCollection(COLLECTION, { size: EMBEDDING_SIZE, distance: DistanceMetric.COSINE, }); const points = await Promise.all( DOCUMENTS.map(async (doc) => ({ id: doc.id, vector: await embed(doc.text), payload: { text: doc.text }, })), ); await client.upsert(COLLECTION, points); const queryVector = await embed('how do I filter by metadata?'); const results = await client.search(COLLECTION, queryVector, { limit: 5, withPayload: true, }); for (const result of results) { console.log( `${result.score.toFixed(4)} #${result.id} ${result.payload?.text}`, ); } client.dispose(); } main().catch((error) => { console.error(error); process.exit(1); });

Three ranked results, best match first, means Aetherfy is working end to end.

What’s next with Aetherfy

  • Examples — a cookbook of complete tasks, each in both Python and JS/TS, including bringing your own embeddings.
  • SDK reference — every method on both Aetherfy clients.
  • Filtering — narrow a search using the payload fields you stored alongside each vector.
  • Limits — the quotas and caps your Aetherfy plan applies.
  • Deploy an agent — run your own code on Aetherfy, as a service or as a scheduled task.
  • Pricing  — plans, and which of them include multi-region replication.
Last updated on