Skip to Content
Vector databaseREST API reference
Raw

Aetherfy vector REST API

Base URL and authentication for the Aetherfy vector API

The Aetherfy vector API is served from https://vectors.aetherfy.com. Every customer-facing route lives under /api/v1. Authentication is a bearer token:

Authorization: Bearer <api key>

Collection names are tenant-scoped by Aetherfy on the server side. You always send your own bare collection name — never a prefixed or namespaced one — and Aetherfy resolves it to your account’s collection.

curl -s https://vectors.aetherfy.com/api/v1/collections \ -H "Authorization: Bearer $AETHERFY_API_KEY"

A request with no Authorization header, or one that is not a Bearer header, is refused with 401 MISSING_API_KEY. A syntactically valid key that does not resolve is refused with 401 INVALID_API_KEY. All error shapes are documented on errors.

Collection routes in the Aetherfy vector API

MethodPathPurpose
POST/api/v1/collectionsCreate a collection. Body: {name, vectors:{size,distance}, description?, regions?}. Re-creating an existing collection with the same configuration is idempotent and returns 200; a different configuration under an existing name returns 409 COLLECTION_NAME_TAKEN.
GET/api/v1/collectionsList collections. Workspaceless form only.
GET/api/v1/collections/{name}Collection info.
PATCH/api/v1/collections/{name}Update metadata. description only — any other key returns 400.
DELETE/api/v1/collections/{name}Delete the collection.

Aetherfy fixes the rest of the collection configuration server-side. There is no request field for optimizers_config, hnsw_config, or any other engine tuning at creation time.

Because a same-configuration create is idempotent on Aetherfy, a script may call create unconditionally on every run without checking collection_exists first — the second and later runs return 200 and change nothing. Only a create that asks for a different configuration under a name already in use is an error.

# Create. curl -s -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"},"description":"Article embeddings"}' # Read. curl -s https://vectors.aetherfy.com/api/v1/collections/articles \ -H "Authorization: Bearer $AETHERFY_API_KEY" # Update the description (the only mutable field). curl -s -X PATCH https://vectors.aetherfy.com/api/v1/collections/articles \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"description":"Article embeddings, v2"}' # Delete. curl -s -X DELETE https://vectors.aetherfy.com/api/v1/collections/articles \ -H "Authorization: Bearer $AETHERFY_API_KEY"

Collection names are validated by Aetherfy: 1 to 100 characters, drawn from [a-zA-Z0-9_-] only. Descriptions are at most 500 characters and may not contain HTML angle brackets. Both violations return 400.

Response headers and body on an Aetherfy collection read

GET /api/v1/collections/{name} returns a body of the form {result, schema_version} and carries three response headers that Aetherfy adds:

HeaderMeaning
ETagVersion tag for the collection record
X-Collection-SourceWhich store answered the read
X-Collection-StatusLifecycle status of the collection

These headers are specific to the single-collection read on Aetherfy; the list route does not carry them.

Point routes in the Aetherfy vector API

MethodPathPurpose
PUT/api/v1/collections/{name}/pointsUpsert points (streaming). Body: {"points":[{id, vector, payload?}]}
POST/api/v1/collections/{name}/points/searchSimilarity search
POST/api/v1/collections/{name}/points/retrieveRetrieve by ids. Body: {ids:[...], with_payload?, with_vector?}
GET/api/v1/collections/{name}/points/{id}Retrieve a single point
POST/api/v1/collections/{name}/points/scrollPaginate through points
POST/api/v1/collections/{name}/points/countCount. Body: {filter?, exact?}
POST/api/v1/collections/{name}/points/deleteDelete by {points:[ids]} or by {filter:{...}}

Upsert on Aetherfy is PUT, not POST. This is the single most common mistake against this API — see the unsupported-endpoint section below for what POST on that path actually does.

On the retrieve route the flags are with_payload (default true) and with_vector — singular — defaulting to false. The search body takes the same singular spelling, with_vector. Both Aetherfy SDKs expose this option under the plural name (with_vectors in Python, withVectors in JavaScript), so a hand-written REST search body that says with_vectors is not a flag Aetherfy reads. On the count route a limit key in the body is stripped by Aetherfy before the request reaches the engine, so sending one has no effect.

# Upsert (PUT, not POST). curl -s -X PUT https://vectors.aetherfy.com/api/v1/collections/articles/points \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"points":[ {"id":1,"vector":[0.1,0.2,0.3,0.4],"payload":{"lang":"en"}}, {"id":2,"vector":[0.4,0.3,0.2,0.1],"payload":{"lang":"fr"}} ]}' # Search. curl -s -X POST https://vectors.aetherfy.com/api/v1/collections/articles/points/search \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"vector":[0.1,0.2,0.3,0.4],"limit":5,"with_payload":true}' # Retrieve by id. curl -s -X POST https://vectors.aetherfy.com/api/v1/collections/articles/points/retrieve \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"ids":[1,2],"with_payload":true,"with_vector":false}' # Retrieve a single point. curl -s https://vectors.aetherfy.com/api/v1/collections/articles/points/1 \ -H "Authorization: Bearer $AETHERFY_API_KEY" # Scroll. curl -s -X POST https://vectors.aetherfy.com/api/v1/collections/articles/points/scroll \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"limit":100,"with_payload":true}' # Count. curl -s -X POST https://vectors.aetherfy.com/api/v1/collections/articles/points/count \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"exact":true}' # Delete by id, then by filter. curl -s -X POST https://vectors.aetherfy.com/api/v1/collections/articles/points/delete \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"points":[1,2]}' curl -s -X POST https://vectors.aetherfy.com/api/v1/collections/articles/points/delete \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"filter":{"must":[{"key":"lang","match":{"value":"fr"}}]}}'

Per-request caps on these routes — search and scroll limit, retrieve id count, delete point count, upsert point count and wire size — are on limits.

Payload and index routes in the Aetherfy vector API

MethodPathPurpose
POST/api/v1/collections/{name}/points/payloadSet payload — merge
PUT/api/v1/collections/{name}/points/payloadOverwrite payload — replace
POST/api/v1/collections/{name}/points/payload/deleteDelete named payload keys
PUT or POST/api/v1/collections/{name}/indexCreate a payload field index
DELETE/api/v1/collections/{name}/index/{field}Delete a payload field index

POST merges into the existing payload; PUT replaces it wholesale. Aetherfy reserves every payload key beginning __aetherfy_: writing one returns 400 RESERVED_FIELD, and any such key is stripped from read responses.

# Merge keys into the existing payload. curl -s -X POST https://vectors.aetherfy.com/api/v1/collections/articles/points/payload \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"payload":{"reviewed":true},"points":[1,2]}' # Replace the payload wholesale. curl -s -X PUT https://vectors.aetherfy.com/api/v1/collections/articles/points/payload \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"payload":{"lang":"en"},"points":[1]}' # Remove named keys. curl -s -X POST https://vectors.aetherfy.com/api/v1/collections/articles/points/payload/delete \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"keys":["reviewed"],"points":[1,2]}'

Schema routes in the Aetherfy vector API

MethodPathPurpose
GET/api/v1/schema/{collection}Read the stored payload schema
PUT/api/v1/schema/{collection}Write it. Body: {schema, enforcement_mode, description?}
DELETE/api/v1/schema/{collection}Remove it
POST/api/v1/schema/{collection}/analyzeInfer a schema from stored points. Body: {sample_size?}

enforcement_mode accepts "off", "warn", or "strict"; anything else returns 400 INVALID_ENFORCEMENT_MODE. sample_size must be between 100 and 10 000, or Aetherfy returns 400 INVALID_SAMPLE_SIZE.

The PUT route supports If-Match for compare-and-set. A mismatch returns 412 SCHEMA_VERSION_MISMATCH, whose body carries current_etag so you can re-read and retry.

# Read the current schema. curl -s https://vectors.aetherfy.com/api/v1/schema/articles \ -H "Authorization: Bearer $AETHERFY_API_KEY" # Infer one from the stored points. curl -s -X POST https://vectors.aetherfy.com/api/v1/schema/articles/analyze \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sample_size":500}' # Remove it. curl -s -X DELETE https://vectors.aetherfy.com/api/v1/schema/articles \ -H "Authorization: Bearer $AETHERFY_API_KEY"

Region discovery in the Aetherfy vector API

GET /api/v1/regions returns the region-to-regional-URL map that the Aetherfy SDKs use to build a region-pinned client.

curl -s https://vectors.aetherfy.com/api/v1/regions \ -H "Authorization: Bearer $AETHERFY_API_KEY"

Which regions actually hold your data is a property of your plan, not of this route: Free and Starter accounts are single-region, with the region fixed by the first resource created, and replication across regions begins at the tier named Performance. Asking for a region outside your plan’s scope returns 422 STARTER_REGION_CONSISTENCY or 422 COLLECTION_REGIONS_NOT_IN_SCOPE.

Workspace-scoped routes in the Aetherfy vector API

Every collection route above has a workspace-scoped twin. Insert /workspaces/{workspace} between /api/v1 and /collections:

WorkspacelessWorkspace-scoped
POST /api/v1/collectionsPOST /api/v1/workspaces/{workspace}/collections
GET /api/v1/collections/{name}GET /api/v1/workspaces/{workspace}/collections/{name}
PATCH /api/v1/collections/{name}PATCH /api/v1/workspaces/{workspace}/collections/{name}
DELETE /api/v1/collections/{name}DELETE /api/v1/workspaces/{workspace}/collections/{name}
PUT /api/v1/collections/{name}/pointsPUT /api/v1/workspaces/{workspace}/collections/{name}/points
POST /api/v1/collections/{name}/points/searchPOST /api/v1/workspaces/{workspace}/collections/{name}/points/search

The collection name in the workspace-scoped form must be bare — it may not contain a /. The collection list route (GET /api/v1/collections) exists in the workspaceless form only.

curl -s -X POST https://vectors.aetherfy.com/api/v1/workspaces/research/collections/articles/points/search \ -H "Authorization: Bearer $AETHERFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"vector":[0.1,0.2,0.3,0.4],"limit":5}'

Both Aetherfy SDKs reach the workspace-scoped routes through the workspace client option rather than by hand-building the path — see the SDK reference.

Distance values accepted by the Aetherfy vector API

Aetherfy normalizes the distance string case-insensitively at collection creation.

You send (any case)Aetherfy stores and returns
cosineCosine
euclidEuclid
euclideanEuclid
dotDot
manhattanManhattan

Euclidean is the one value that does not round-trip through Aetherfy, and it catches SDK users too: DistanceMetric.EUCLIDEAN sends the string Euclidean, so a collection created with it reads back config.distance == "Euclid" and an equality check against Euclidean silently fails. Every other name comes back exactly as the table’s left column, capitalised.

Qdrant compatibility and forwarding in the Aetherfy vector API

Anything under /api/v1/collections/{name}/points/** is forwarded verbatim to Qdrant by Aetherfy. Nothing inspects or rewrites the body, which is why Qdrant’s filter DSL, point shapes, and query bodies work unchanged — and why an Aetherfy-side typo in a filter key is silently accepted rather than rejected. Filter syntax and the one key-name defect worth knowing about are on filtering.

The one consequence to internalise: Aetherfy validates the envelope (auth, tenancy, caps, reserved keys), and Qdrant validates the query. An option Aetherfy does not know about is not an error at the Aetherfy layer.

Endpoints the Aetherfy vector API does not support

Aetherfy is Qdrant-compatible but not a Qdrant passthrough. These are refused, deliberately, and no amount of retrying will change the answer.

RequestResultUse instead
PUT /collections/{name} (Qdrant-native create)405 METHOD_NOT_ALLOWEDPOST /api/v1/collections
PATCH /collections/{name} with optimizers_config, hnsw_config, or any non-description key400Only description is mutable
POST /collections/{name}/points expecting upsertNot upsert — falls through to Qdrant’s batch retrieve, which expects body.idsPUT /api/v1/collections/{name}/points
Snapshot endpoints404 “Unsupported endpoint”
/telemetry, /metrics404 “Unsupported endpoint”
/cluster, /locks, shard endpoints404 “Unsupported endpoint”
Collection creation with engine tuning fieldsNot accepted — configuration is fixed server-side by Aetherfy
Any payload key beginning __aetherfy_400 RESERVED_FIELD on write; stripped from readsChoose another key

Query-time tuning is the one engine knob Aetherfy does expose, and it goes in the request body’s params field — see search tuning.

Last updated on