HTTP API reference

Asteroid Cloud routes require Authorization: Bearer <api-key> except /health. Bodies are JSON unless noted.

Method & pathDescription
PUT /v1/indexCreate the index: set {dim, metric} once, before any write. 409 if already initialized.
GET /v1/indexIndex state: {initialized, dim, metric}.
DELETE /v1/indexDelete the index and all data; returns to uninitialized. Destructive.
POST /v1/vectorsInsert a vector (with optional metadata).
PUT /v1/vectors/:idUpsert (replace) the vector for an id.
GET /v1/vectors/:idFetch a vector.
DELETE /v1/vectors/:idDelete a vector.
GET /v1/vectors/:id/payloadGet the JSON payload.
PUT /v1/vectors/:id/payloadReplace the payload.
PATCH /v1/vectors/:id/payloadMerge-patch the payload (RFC 7396).
POST /v1/vectors/batchBatch insert {id, vector, metadata?} items (incremental, caller ids, payloads inline). Returns {inserted}.
POST /v1/searchk-NN search (vector, k, optional ef_search, filter).
POST /v1/build/bulkBulk 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/statsIndex stats: {vectors, dim, metric, memory_bytes} (live vector count; working-set memory excluding OS file cache).
GET /healthUnauthenticated liveness check.
GET /readyDB 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

StatusMeaningTypical 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+.

MethodNotes
create_index(dim, metric="l2") -> dictSet the index dimension + metric, once, before any write. 409 if already initialized.
get_index() -> dict{initialized, dim, metric}.
delete_index() -> dictDelete 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) -> intBatched insert of (id, vector[, metadata]) items.
bulk_build(vectors, threads=0, payloads=None) -> dictOne-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]"):

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).