---
slug: vectors
title: Vector database overview
kind: explanation
surface: vectors
summary: The Aetherfy vector database is a Qdrant-compatible service reached over REST at https://vectors.aetherfy.com or through the Python and JavaScript SDKs, authenticated with an afy_ API key.
sources:
  - dashboard/src/pages/api/proxy/collections.js
  - vectordb:backend/routes/proxy.js
  - aetherfy-vectors-python-sdk:aetherfy_vectors/client.py
  - aetherfy-vectors-js-sdk:src/client.ts
---

# Aetherfy vector database

## What the Aetherfy vector database is

The Aetherfy vector database stores vectors with attached JSON payloads and
answers nearest-neighbour queries over them. It is a managed service: you create
collections, upsert points, and search. There are no nodes, shards, or index
build settings to operate — collection creation configuration is fixed
server-side, and Aetherfy owns it.

The unit of storage is a **collection**: a named set of points that all share one
vector size and one distance metric. A **point** is an id, a vector, and an
optional payload dictionary. Search returns points ordered by similarity score,
optionally narrowed by a payload filter.

Collection names are tenant-scoped server-side by Aetherfy. You always use your
own bare collection name — two accounts can both own a collection called
`articles` without collision, and you never prefix or namespace it yourself.

## Qdrant compatibility in the Aetherfy vector database

The Aetherfy vector database exposes a Qdrant-compatible API. Everything under
`/api/v1/collections/{name}/points/**` is forwarded to Qdrant verbatim, so
Qdrant's filter DSL, point shapes, and query bodies work unchanged. If you have
written a Qdrant filter before, it is the same filter here.

Compatibility is not total, and Aetherfy is explicit about the edges:

| Qdrant behaviour | Status on Aetherfy |
|---|---|
| `PUT /collections/{name}` (native create) | Not supported — 405 `METHOD_NOT_ALLOWED`; use `POST /api/v1/collections` |
| `PATCH` with `optimizers_config` / `hnsw_config` | Not supported — 400; only `description` is mutable |
| `POST /collections/{name}/points` as upsert | Not upsert on Aetherfy — upsert is `PUT`; `POST` falls through to Qdrant's batch retrieve, which expects `body.ids` |
| Snapshots, `/telemetry`, `/metrics`, `/cluster`, `/locks`, shard endpoints | Not supported — 404 "Unsupported endpoint" |
| Payload keys beginning `__aetherfy_` | Reserved by Aetherfy and stripped from reads, except `__aetherfy_agent_id` — the attested author, which is returned and which you may send back unchanged (Aetherfy ignores the value and sets it from your credential). The rest are rejected on write with 400 `RESERVED_FIELD` |

The full route list is on [the REST API reference](/vectors/api).

## Authenticating against the Aetherfy vector database

Every request to the Aetherfy vector database carries an API key in an
`Authorization: Bearer` header. Keys look like `afy_live_...` or `afy_test_...`
and match the regex `^afy_(live|test)_[a-zA-Z0-9]{16,}$` — a permissive
client-side check, not the issued format, which is the prefix plus exactly 32
hexadecimal characters (see [API keys](/platform/api-keys)). Create and revoke
keys at [https://app.aetherfy.com/dashboard/settings/api-keys](https://app.aetherfy.com/dashboard/settings/api-keys).

Both SDKs read the key from the environment when you do not pass one, checking
`AETHERFY_API_KEY` first and `AETHERFY_VECTORS_API_KEY` second.

A raw request against Aetherfy looks like this:

```bash
curl -X POST https://vectors.aetherfy.com/api/v1/collections \
  -H "Authorization: Bearer $AETHERFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"articles","vectors":{"size":4,"distance":"Cosine"}}'
```

A missing or malformed header returns 401 `MISSING_API_KEY`; a key that does not
resolve returns 401 `INVALID_API_KEY`. See [errors](/vectors/errors).

## The Aetherfy client SDKs

Aetherfy ships two first-party clients over the same REST surface. They are
distributed under the same name in each ecosystem and are both at version 1.1.0.

| | Python | JavaScript / TypeScript |
|---|---|---|
| Install | `pip install aetherfy-vectors` | `npm install aetherfy-vectors` |
| Runtime | Python >= 3.9 | Node >= 20 |
| Import packages | `aetherfy_vectors`, `aetherfy_memory` | package root only |
| Call style | Synchronous | `async` / `await` |

### Python

```python
import os

from aetherfy_vectors import AetherfyVectorsClient, Point
from aetherfy_vectors.models import VectorConfig, DistanceMetric

client = AetherfyVectorsClient(api_key=os.environ["AETHERFY_API_KEY"])

client.create_collection(
    collection_name="articles",
    vectors_config=VectorConfig(size=4, distance=DistanceMetric.COSINE),
)

client.upsert(
    collection_name="articles",
    points=[
        Point(id=1, vector=[0.1, 0.2, 0.3, 0.4], payload={"title": "First"}),
        Point(id=2, vector=[0.2, 0.1, 0.4, 0.3], payload={"title": "Second"}),
    ],
)

results = client.search("articles", query_vector=[0.1, 0.2, 0.3, 0.4], limit=2)
for hit in results:
    print(hit.id, hit.score, hit.payload)

client.close()
```

### JavaScript / TypeScript

```typescript
import { AetherfyVectorsClient, DistanceMetric } from 'aetherfy-vectors';

const client = new AetherfyVectorsClient({
  apiKey: process.env.AETHERFY_API_KEY,
});

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

await client.upsert('articles', [
  { id: 1, vector: [0.1, 0.2, 0.3, 0.4], payload: { title: 'First' } },
  { id: 2, vector: [0.2, 0.1, 0.4, 0.3], payload: { title: 'Second' } },
]);

const results = await client.search('articles', [0.1, 0.2, 0.3, 0.4], {
  limit: 2,
});
for (const hit of results) {
  console.log(hit.id, hit.score, hit.payload);
}

client.dispose();
```

The two SDKs are not mirror images of each other — defaults, units, and field
names diverge in ways that change results. Those divergences are tabulated on
[the SDK reference](/vectors/sdk).

## Regions and replication in the Aetherfy vector database

Where your data lives depends on your plan, and Aetherfy does not replicate
every account's collections.

| Plan | Regional behaviour |
|---|---|
| Free | Single region — the region is fixed by the first resource you create |
| Starter | Single region — the region is fixed by the first resource you create |
| Performance | Multi-region replication |
| Enterprise | Multi-region replication |

Multi-region replication begins at the plan named **Performance**. On Free and
Starter, a request that asks for a region other than the account's own region is
refused with 422 `STARTER_REGION_CONSISTENCY`, and a collection that already
exists elsewhere returns 409 `COLLECTION_EXISTS_IN_OTHER_REGION`.

The regions the Aetherfy SDKs accept for an explicit regional client are
`us-east-1`, `eu-central-1`, and `ap-southeast-1`. The live region-to-URL map is
served by `GET /api/v1/regions`. Plan details are at
[https://aetherfy.com/pricing](https://aetherfy.com/pricing).

Note that on a replicated plan, stored bytes are counted **per replica** — see
[limits](/vectors/limits).

## Where to go next in the Aetherfy documentation

| Page | What it covers |
|---|---|
| [/vectors/sdk](/vectors/sdk) | Full Python and JavaScript method surface, model shapes, point ID rules, and the per-language divergences |
| [/vectors/api](/vectors/api) | Every REST route, including the workspace-scoped forms and the endpoints Aetherfy deliberately does not support |
| [/vectors/filtering](/vectors/filtering) | Payload filter syntax — `must`, `should`, `must_not`, match and range conditions |
| [/vectors/search-tuning](/vectors/search-tuning) | `search_params` / `searchParams`, including `hnsw_ef`, and how unknown options fail |
| [/vectors/usage-and-metrics](/vectors/usage-and-metrics) | The two analytics reads — plan usage and measured request telemetry, with the coverage rule that separates a real zero from an unobserved one |
| [/vectors/limits](/vectors/limits) | Per-request caps, per-plan caps, rate limiting, and storage accounting |
| [/vectors/errors](/vectors/errors) | The error envelope, every stable error code, and the SDK exception classes |
| [/examples](/examples) | Worked end-to-end examples |
