Docs

HTTP API: vectors and embeddings

Vector columns and indexes in your tables, similarity and hybrid search, automatic embeddings, and vector collections with their records.

Updated Oct 18, 2026

Embeddings and similarity search over HTTP: pgvector in your own tables (recommended), automatic embeddings, and simpler vector collections. Guide: Vector search and embeddings.

Base URLhttps://<project-ref>.sovarias.in — your project URL from Connect.
KeysSend the project's key as apikey. Calls made for a signed-in user also send Authorization: Bearer <access token>.
ErrorsA status code and {"detail": …} — a sentence, or {code, message} for errors your code may branch on (HTTP API).

Vectors in your tables (pgvector)

GET/api/v1/data/rel/vector/status

Whether pgvector is installed and which vector columns exist.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/status

Returns

availableboolean
The extension can be installed.
enabledboolean
It is installed.
versionstring
pgvector version.
columnsarray<object>
Vector columns: table, column, dimensions.

Responses

  • 200Success.
  • 401No valid session or key.
curl -s "$URL/api/v1/data/rel/vector/status" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
  "available": true,
  "enabled": true,
  "version": "0.8.0",
  "columns": [
    {
      "table": "documents",
      "column": "embedding",
      "dimensions": 1536
    }
  ]
}

POST/api/v1/data/rel/vector/enable

Install (or check) the pgvector extension.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/enable

Body

enabledbooleanoptionaldefault true
true to install.

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/data/rel/vector/enable" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"enabled": true}'
Response
{
  "available": true,
  "enabled": true,
  "version": "0.8.0",
  "columns": [
    {
      "table": "documents",
      "column": "embedding",
      "dimensions": 1536
    }
  ]
}

POST/api/v1/data/rel/vector/tables

Create a table for embeddings: id, content, metadata and a vector column.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/tables

Body

table_namestringrequired
The new table.
1–63 characters
dimensionsintegerrequired
Vector size of your embedding model (e.g. 1536).
1.0–16000.0
owner_rowsbooleanoptionaldefault false
Add owner_id and row-level security so each user only sees their own rows.

Responses

  • 200Success.
  • 400Bad name or dimensions, or the table exists.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/data/rel/vector/tables" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"table_name": "documents", "dimensions": 1536, "owner_rows": true}'
Response
{
  "status": "ok",
  "table": "documents",
  "dimensions": 1536,
  "owner_rows": true
}

POST/api/v1/data/rel/vector/columns

Add a vector column to an existing table.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/columns

Body

table_namestringrequired
The table.
1–63 characters
column_namestringoptionaldefault embedding
The new column (default embedding).
1–63 characters
dimensionsintegerrequired
Vector size (1–16,000; HNSW indexes work up to 2,000).
1.0–16000.0

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/data/rel/vector/columns" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"table_name": "products", "column_name": "embedding", "dimensions": 768}'
Response
{
  "status": "ok",
  "table": "products",
  "column": "embedding",
  "dimensions": 768
}

POST/api/v1/data/rel/vector/indexes

Create an HNSW index on a vector column for fast similarity search.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/indexes

Body

table_namestringrequired
The table.
1–63 characters
column_namestringoptionaldefault embedding
The vector column.
1–63 characters
metricstringoptionaldefault cosine
cosine, l2 or inner_product — use the one you search with.
One of cosine, l2, inner_product

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/data/rel/vector/indexes" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"table_name": "documents", "metric": "cosine"}'
Response
{
  "status": "ok",
  "index": "documents_embedding_cosine_idx",
  "method": "hnsw",
  "metric": "cosine"
}

POST/api/v1/data/rel/vector/rows

Insert rows with their vectors (up to 500 per request).

Vectors are bound as parameters. A vector of the wrong size fails with an error naming the expected size.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/rows

Body

table_namestringrequired
The table.
1–63 characters
column_namestringoptionaldefault embedding
The vector column.
1–63 characters
rowsarray<object>required
1–500 objects: column values, with the vector under column_name.
1–500 items

Responses

  • 200Success.
  • 400Wrong vector size, or a column that doesn't exist.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/data/rel/vector/rows" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"table_name": "documents", "rows": [{"content": "How to reset your password", "metadata": {"lang": "en"}, "embedding": [0.012, -0.044, "…"]}]}'
Response
{
  "status": "ok",
  "inserted": 1
}

POST/api/v1/data/rel/vector/search

Find the rows closest to a vector — or to text, with keyword and hybrid ranking.

Runs as the caller, so row-level security applies, and still returns k results: the index keeps scanning past rows the caller can't see. Send vector for similarity search, text for keyword (full-text) search, or both (hybrid, the default when text is given): results are fused by rank.

Who
Your app: the project's anon key (apikey: <anon key>), with the user's access token once they are signed in.
Also at
/rest/rel/vector/search

Body

table_namestringrequired
The table.
1–63 characters
column_namestringoptionaldefault embedding
The vector column.
1–63 characters
vectorarray<number> | nulloptional
The query vector (same size as the column).
textstring | nulloptional
Query text for keyword / hybrid search; with auto-embeddings on, it's embedded for you.
1–2,000 characters
modestring | nulloptional
vector, keyword or hybrid.
One of vector, keyword, hybrid
text_columnsarray<string> | nulloptional
Columns for keyword search (default: the auto-embedding sources, else content).
1–10 items
languagestringoptionaldefault simple
Postgres text-search configuration (simple, english…).
pattern `^[a-z_]{1,32} HTTP API: vectors and embeddings | Sovaria Docs
kintegeroptionaldefault 5
How many results (1–100).
1.0–100.0
metricstringoptionaldefault cosine
cosine, l2 or inner_product.
One of cosine, l2, inner_product
selectarray<string> | nulloptional
Columns to return (default: all but the vector).
0–50 items
filterobject<string, string | integer | number | boolean | null>optional
Exact-match filters on columns, e.g. {"lang": "en"}.
max_distancenumber | nulloptional
Drop results farther than this.

Returns

resultsarray<object>
The selected columns plus distance (smaller is closer; inner product is reported positive). Hybrid adds score (fused), vector_rank and keyword_rank; keyword mode adds keyword_score.
mode, metric, kstring, string, integer
What ran.

Responses

  • 200Success.
  • 400Neither vector nor text, a size mismatch, or an unknown column.
  • 403Refused by your access policies.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/data/rel/vector/search" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"table_name": "documents", "text": "I forgot my login", "k": 3, "select": ["id", "content"], "filter": {"lang": "en"}}'
Response
{
  "table": "documents",
  "metric": "cosine",
  "k": 3,
  "mode": "hybrid",
  "results": [
    {
      "id": 12,
      "content": "How to reset your password",
      "distance": 0.182,
      "score": 0.0325,
      "vector_rank": 1,
      "keyword_rank": 1
    },
    {
      "id": 7,
      "content": "Signing in with a magic link",
      "distance": 0.247,
      "score": 0.0317,
      "vector_rank": 2,
      "keyword_rank": 3
    }
  ]
}

Automatic embeddings

GET/api/v1/data/rel/vector/auto

Tables that embed their rows automatically, and the embedding model.

The model is openai/<model>@<dims> or gemini/<model>@<dims> when an embedding provider is configured, otherwise local-hash-<dims> (hash-based: matches words, not meaning).

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/auto

Responses

  • 200Success.
  • 401No valid session or key.
curl -s "$URL/api/v1/data/rel/vector/auto" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
  "model": {
    "model": "openai/text-embedding-3-small@1536",
    "dim": 1536,
    "semantic": true
  },
  "tables": [
    {
      "table": "documents",
      "column": "embedding",
      "source_columns": [
        "title",
        "content"
      ],
      "model": "openai/text-embedding-3-small@1536",
      "embedded": 3120,
      "pending": 0,
      "synced_at": "2026-10-17T13:10:00Z",
      "last_error": null
    }
  ]
}

POST/api/v1/data/rel/vector/auto

Embed a table's rows automatically from text columns (and keep them up to date).

Adds the vector column if needed and embeds existing rows in the background; new and changed rows are embedded as they are written. Recorded as a migration you can roll back.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/auto

Body

table_namestringrequired
The table.
1–63 characters
column_namestringoptionaldefault embedding
Vector column (created if missing).
1–63 characters
source_columnsarray<string>required
1–10 text columns to embed (joined).
1–10 items
rebuildbooleanoptionaldefault false
Clear every vector and embed the table again.

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/data/rel/vector/auto" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"table_name": "documents", "source_columns": ["title", "content"]}'
Response
{
  "status": "ok",
  "table": "documents",
  "column": "embedding",
  "source_columns": [
    "title",
    "content"
  ],
  "model": "openai/text-embedding-3-small@1536",
  "dimensions": 1536,
  "created_column": true,
  "background": true,
  "embedded": 128,
  "migration_version": "20261017131500",
  "reversible": true
}

POST/api/v1/data/rel/vector/auto/sync

Embed rows that are still waiting (up to 256 per call).

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/auto/sync

Body

table_namestring | nulloptional
One table (default: all).
1–63 characters
limitintegeroptionaldefault 128
Rows per call (1–256).
1.0–256.0

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/data/rel/vector/auto/sync" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"table_name": "documents", "limit": 128}'
Response
{
  "tables": [
    {
      "table": "documents",
      "embedded": 64
    }
  ],
  "embedded": 64
}

DELETE/api/v1/data/rel/vector/auto/{table_name}

Stop embedding a table automatically (the vectors stay).

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.
Also at
/rest/rel/vector/auto/{table_name}

Path parameters

table_namestringrequired
The table.

Responses

  • 200Success.
  • 401No valid session or key.
curl -s -X DELETE "$URL/api/v1/data/rel/vector/auto/documents" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
  "status": "ok",
  "table": "documents",
  "enabled": false,
  "migration_version": "20261017132000",
  "reversible": true
}

Vector collections

POST/api/v1/vectors/upsert

Add or update texts in a vector collection; Sovaria embeds them.

The collections API embeds for you with the project's embedding model (see semantic in the list response: without a configured provider the built-in embeddings are hash-based, fine for exact-ish matching, not for meaning — Vector search and embeddings).

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.

Body

collectionstringrequired
The collection (created on first use).
1–64 characters
docsarray<object>required
1–256 documents.
1–256 items
3 fields
idstring | nulloptional
Your id; a new one is generated when left out.
textstringrequired
The text to embed.
metadataobjectoptional
Any JSON, for filtering.

Returns

inserted, updatedinteger
diminteger
Vector size.
sizeinteger
Records in the collection now.

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/vectors/upsert" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"collection": "help-articles", "docs": [{"id": "a1", "text": "How to reset your password", "metadata": {"lang": "en"}}, {"id": "a2", "text": "Exporting invoices as PDF", "metadata": {"lang": "en"}}]}'
Response
{
  "inserted": 2,
  "updated": 0,
  "dim": 1536,
  "size": 2
}

POST/api/v1/vectors/search

Search a vector collection by text.

App users can search a collection when it has app_search on (PATCH /api/v1/collections/{collection}).

Who
Your app: the project's anon key (apikey: <anon key>), with the user's access token once they are signed in.

Body

collectionstringrequired
The collection.
1–64 characters
querystringrequired
The search text.
1–2,000 characters
top_kintegeroptionaldefault 5
How many results (1–100).
1.0–100.0
metadata_filterobjectoptional
Only records whose metadata has these values.
modestring | nulloptional
vector, keyword or hybrid.
One of vector, keyword, hybrid

Returns

resultsarray<object>
{id, text, metadata, score}, best first.
semanticboolean
Whether the model captures meaning (a real embedding model) or is hash-based.

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/vectors/search" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"collection": "help-articles", "query": "I forgot my login", "top_k": 2, "metadata_filter": {"lang": "en"}}'
Response
{
  "results": [
    {
      "id": "a1",
      "text": "How to reset your password",
      "metadata": {
        "lang": "en"
      },
      "score": 0.83
    }
  ],
  "count": 1,
  "mode": "vector",
  "model": "openai/text-embedding-3-small@1536",
  "semantic": true
}

POST/api/v1/embed

Get embedding vectors for texts (up to 512).

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.

Body

textsarray<string>required
1–512 texts.
1–512 items

Returns

vectorsarray<array<number>>required
dimintegerrequired
countintegerrequired
modelstringoptional

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X POST "$URL/api/v1/embed" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"texts": ["red running shoes", "blue sandals"]}'
Response
{
  "vectors": [
    [
      0.012,
      -0.044,
      "…"
    ],
    [
      0.031,
      0.007,
      "…"
    ]
  ],
  "dim": 1536,
  "count": 2,
  "model": "openai/text-embedding-3-small@1536"
}

GET/api/v1/collections

The project's vector collections and the embedding model.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.

Responses

  • 200Success.
  • 401No valid session or key.
curl -s "$URL/api/v1/collections" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
  "collections": [
    {
      "name": "help-articles",
      "dim": 1536,
      "size": 2,
      "model": "openai/text-embedding-3-small@1536",
      "app_search": false
    }
  ],
  "model": "openai/text-embedding-3-small@1536",
  "semantic": true
}

PATCH/api/v1/collections/{collection}

Change a collection's settings.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.

Path parameters

collectionstringrequired
The collection.

Body

app_searchboolean | nulloptional
Let signed-in app users search it.

Responses

  • 200Success.
  • 401No valid session or key.
  • 422The body is missing a required field or has a field of the wrong type.
curl -s -X PATCH "$URL/api/v1/collections/help-articles" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"app_search": true}'
Response
{
  "collection": "help-articles",
  "settings": {
    "app_search": true
  }
}

GET/api/v1/collections/{collection}/records

A collection's records.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.

Path parameters

collectionstringrequired
The collection.

Query parameters

limitintegeroptionaldefault 100
How many.
1–500
offsetintegeroptionaldefault 0
How many to skip.
0–…

Responses

  • 200Success.
  • 401No valid session or key.
curl -s "$URL/api/v1/collections/help-articles/records" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
  "collection": "help-articles",
  "dim": 1536,
  "total": 2,
  "records": [
    {
      "id": "a1",
      "text": "How to reset your password",
      "metadata": {
        "lang": "en"
      }
    }
  ]
}

DELETE/api/v1/collections/{collection}/records/{record_id}

Delete one record.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.

Path parameters

collectionstringrequired
The collection.
record_idstringrequired
The record's id.

Responses

  • 204Success, with no body.
  • 401No valid session or key.
curl -s -X DELETE "$URL/api/v1/collections/help-articles/records/a2" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

DELETE/api/v1/collections/{collection}

Delete a collection and its records.

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.

Path parameters

collectionstringrequired
The collection.

Responses

  • 204Success, with no body.
  • 401No valid session or key.
curl -s -X DELETE "$URL/api/v1/collections/help-articles" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

POST/api/v1/collections/{collection}/reembed

Embed every record again with the current model (after changing models).

Who
Your team or your backend: a member's session, or a server key (apikey: <service role or custom key>). Never from a browser or app.

Path parameters

collectionstringrequired
The collection.

Responses

  • 200Success.
  • 401No valid session or key.
curl -s -X POST "$URL/api/v1/collections/help-articles/reembed" \
  -H "apikey: $ANON_KEY" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
  "collection": "help-articles",
  "records": 2,
  "model": "openai/text-embedding-3-small@1536"
}
Something unclear or missing on this page?Tell us