HTTP API reference
Asteroid Cloud routes require
Authorization: Bearer <api-key> except /health.
Bodies are JSON unless noted.
| Method & path | Description |
|---|---|
PUT /v1/index | Create the index: set {dim, metric} once, before any write. 409 if already initialized. |
GET /v1/index | Index state: {initialized, dim, metric}. |
DELETE /v1/index | Delete the index and all data; returns to uninitialized. Destructive. |
POST /v1/vectors | Insert a vector (with optional metadata). |
PUT /v1/vectors/:id | Upsert (replace) the vector for an id. |
GET /v1/vectors/:id | Fetch a vector. |
DELETE /v1/vectors/:id | Delete a vector. |
GET /v1/vectors/:id/payload | Get the JSON payload. |
PUT /v1/vectors/:id/payload | Replace the payload. |
PATCH /v1/vectors/:id/payload | Merge-patch the payload (RFC 7396). |
POST /v1/vectors/batch | Batch insert {id, vector, metadata?} items (incremental, caller ids, payloads inline). Returns {inserted}. |
POST /v1/search | k-NN search (vector, k, optional ef_search, filter). |
POST /v1/build/bulk | Bulk build (raw float32 body; X-LSMVec-N / X-LSMVec-Dim headers). Empty DB only. Optional: a JSON array of n payloads appended after the float32 blob. |
GET /v1/stats | Index stats: {vectors, dim, metric, memory_bytes} (live vector count; working-set memory excluding OS file cache). |
GET /health | Unauthenticated liveness check. |
GET /ready | DB open & responsive. |
Set the index dimension first: data routes return 409
index_not_initialized until PUT /v1/index is called. See
Create your index. Supported
dim range is 1–4000.
Use sequential IDs. Asteroid keys vectors by sequential,
dense integers — assign IDs in order starting at 0. Large or
sparse IDs (hashes, timestamps, snowflake) are not recommended on the pilot;
keep that mapping in your application and use a sequential counter.
Errors use a JSON body with error and code fields.
Common status codes are 400 invalid argument,
401 unauthorized, 404 not found,
413 payload too large, 429 rate limited, and
5xx server error.
Request examples
Insert a vector
curl -sX POST https://api.lsmvec.com/v1/vectors \
-H "Authorization: Bearer sk-live-..." \
-H "Content-Type: application/json" \
-d '{"id": 1, "vector": [0.10, 0.20, 0.30], "metadata": {"source": "docs"}}'
Batch insert
curl -sX POST https://api.lsmvec.com/v1/vectors/batch \
-H "Authorization: Bearer sk-live-..." -H "Content-Type: application/json" \
-d '{"items":[{"id":0,"vector":[...],"metadata":{"k":"v"}},
{"id":1,"vector":[...]}]}'
# -> {"inserted": 2}
Upsert a vector
curl -sX PUT https://api.lsmvec.com/v1/vectors/1 \
-H "Authorization: Bearer sk-live-..." \
-H "Content-Type: application/json" \
-d '{"vector": [0.12, 0.18, 0.33]}'
Search
curl -sX POST https://api.lsmvec.com/v1/search \
-H "Authorization: Bearer sk-live-..." \
-H "Content-Type: application/json" \
-d '{"vector": [0.11, 0.19, 0.31], "k": 10, "ef_search": 128}'
Search with a metadata filter
curl -sX POST https://api.lsmvec.com/v1/search \
-H "Authorization: Bearer sk-live-..." \
-H "Content-Type: application/json" \
-d '{"vector": [0.11, 0.19, 0.31],
"k": 10,
"filter": {"source": {"$eq": "docs"}}}'
Replace metadata
curl -sX PUT https://api.lsmvec.com/v1/vectors/1/payload \
-H "Authorization: Bearer sk-live-..." \
-H "Content-Type: application/json" \
-d '{"source": "docs", "title": "intro"}'
Merge metadata
curl -sX PATCH https://api.lsmvec.com/v1/vectors/1/payload \
-H "Authorization: Bearer sk-live-..." \
-H "Content-Type: application/json" \
-d '{"views": 42}'
Errors
| Status | Meaning | Typical fix |
|---|---|---|
400 |
Invalid request, invalid JSON, wrong vector dimension, or invalid filter. | Check the request body and use the configured vector dimension. |
401 |
Missing or invalid API key. | Send Authorization: Bearer <api-key>. |
404 |
Vector or payload not found. | Insert the vector first, then retry the read/update. |
413 |
Request body is too large. | Split the request into smaller parts. |
429 |
Request rate is too high for the current pilot limit. | Retry with backoff or contact us if you need more throughput. |
5xx |
Server-side error. | Retry, then contact us with the request and timestamp if it persists. |
{
"error": "vector dimension mismatch",
"code": "invalid_argument"
}
Error responses carry a JSON body; the Python client preserves it on
LSMVecError.details — e.g. inserted / failed_index
on a mid-batch error, or rebuild_required on a failed
bulk_build(payloads=…). IDs should be sequential, dense
integers starting at 0 (Asteroid keys vectors by ID
position); floats/negatives return 400.
Python client reference
pip install lsmvec-client — dependency-free (stdlib
urllib; numpy optional for bulk_build).
Requires Python 3.9+.
| Method | Notes |
|---|---|
create_index(dim, metric="l2") -> dict | Set the index dimension + metric, once, before any write. 409 if already initialized. |
get_index() -> dict | {initialized, dim, metric}. |
delete_index() -> dict | Delete the index and all data (destructive); returns to uninitialized. Idempotent. |
insert(id, vector, metadata=None) | Insert with optional metadata. |
upsert(id, vector) | Insert or replace the vector for an ID. |
get(id) -> dict | {"id", "vector"}. |
delete(id) | |
get_payload(id) / set_payload(id, p) / merge_payload(id, p) | Payload read / replace / merge-patch. |
search(vector, k=10, ef_search=None, filter=None) | Returns [SearchResult(id, distance)]. |
insert_batch(items, chunk_size=1000) -> int | Batched insert of (id, vector[, metadata]) items. |
bulk_build(vectors, threads=0, payloads=None) -> dict | One-pass initial load for a new, empty index. IDs are assigned in input order. The returned report includes payloads_written. |
stats() -> dict | {vectors, dim, metric, memory_bytes}. |
health() / ready() | Liveness / readiness checks. |
Errors map to typed exceptions (all subclass LSMVecError):
InvalidArgument (400), Unauthorized (401),
NotFound (404), Conflict (409),
PayloadTooLarge (413), RateLimited (429),
ServerError (5xx). Conflict carries
index_not_initialized or index_already_initialized in
its code.
Embeddings
The lsmvec_client.ingest module (the local model needs
pip install "lsmvec-client[embed]"):
chunk(text, max_tokens=512, overlap_tokens=64) -> [Chunk(text, index)]LocalEmbedder(model="BAAI/bge-small-en-v1.5")·ProviderEmbedder(dim, api_key, model, base_url=...)·FakeEmbedder(dim)ingest_text(client, doc_id, text, embedder, start_id, *, max_tokens=512, overlap_tokens=64, payload=None) -> [int]search_text(client, query, embedder, *, k=10, ef_search=None, filter=None) -> [Hit(id, distance, text, doc_id, chunk_index, payload)]delete_doc(client, ids) -> int
from lsmvec_client import Client
from lsmvec_client.ingest import LocalEmbedder, ingest_text, search_text
c = Client(api_key="sk-live-...", base_url="https://api.lsmvec.com")
e = LocalEmbedder("BAAI/bge-small-en-v1.5")
ingest_text(c, "doc-1", "…", e, start_id=0)
hits = search_text(c, "…", e, k=5)
Build from source
Prerequisites: a C++17 compiler (GCC 8+/Clang 10+), CMake ≥ 3.10, Boost (headers), and zstd. On macOS also jemalloc. (Aster is built zstd-only, so snappy/lz4/bz2/zlib are not needed.)
# initialize the Aster submodule, then build
git submodule update --init --recursive
make aster # builds lib/aster/librocksdb.a (required first)
make # builds the static + shared libs and the test binary
For the Python engine module (requires Python 3.9+, Aster built, and ninja):
python -m pip install . # builds and installs the astervec module
python -c "import astervec; print('OK')"
Run the server (self-host)
Self-host the same HTTP API as Asteroid Cloud. Run the
astervec_http server (or the astervec Docker image),
then point lsmvec-client at your own host
(base_url="http://localhost:8000") — everything in the
Asteroid Cloud section applies unchanged.
# environment knobs (graph params + threads)
ASTERVEC_M=8 ASTERVEC_MMAX=24 ASTERVEC_EFC=32 ASTERVEC_HTTP_THREADS=1 \
./build/bin/astervec_http # serves the REST API on :8000
Back to Asteroid Cloud · Asteroid Database (AsterVec).