API reference

Views

SQL queries kept as per-segment partials, read as tables by name.

Kept in this tab only and sent only to api.skimmerdb.com. Requests run against your account and count as usage. Make a key.

Create a view

POST /v1/namespaces/{name}/views metered: query

A view is a SQL query over one namespace (FROM docs) whose answer is kept as partials per segment: COUNT, SUM, MIN, MAX, AVG, COUNT(DISTINCT ...), COUNT_IF and f(...) FILTER (WHERE ...) over any WHERE, GROUP BY any expressions (DATE_TRUNC buckets, CASE, ...), with HAVING, ORDER BY and LIMIT applied on top. Name it as a table in SQL (SELECT * FROM daily_signups, or join it). It is always exact: a segment's partial is reused only while that segment's visible rows are the ones it was computed from, so a write or delete recomputes only the segments it touched. Views go with their namespace. Its name is the tenant's (not a namespace's name, not docs). Creating one runs it once (metered as a query) and answers its columns. A query that can't run from parts is refused with 422 view_not_decomposable and the reason; past the plan's views, 402 view_limit.

Parameters

namestring · pathrequiredThe namespace's name.

Body application/json

namestringrequired1 to 64 of a-z, 0-9, '-', '_' and '.'
sqlstringrequiredThe query, over docs.

Answer

namestring
namespacestring
sqlstring
created_atstring
columnsstring[]
typesstring[]

Status codes

201Created
400Malformed: not the JSON expected.
401No key, or an unknown or revoked one.
402The free plan's included usage this period is used up (queries, query CPU, object-storage reads, bytes returned, writes or storage; the message says which), or its namespace count or daily namespace creations are reached (code namespace_limit): upgrade to pro.
403The key's scope or namespaces don't allow it, or the tenant is suspended.
404No such namespace, document, key or tenant (or one this key may not see: the same answer).
409Exists already, or not possible in this state.
422Invalid: the message says why (code invalid with fields: which input fields; query_timeout: past the plan's time limit; scan_refused: send scan: true).
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds.
503Object storage failed: retry (nothing was written, unless the code is write_unknown: then it may have been; retrying a write is safe).
curl -s https://api.skimmerdb.com/v1/namespaces/support/views \
  -H "Authorization: Bearer $KEY" \
  -d '{"name":"daily_signups","sql":"SELECT DATE_TRUNC('day', ts) AS day, plan, COUNT(*) AS signups FROM docs WHERE kind = 'signup' GROUP BY 1, 2"}'
from skimmerdb import SkimmerDB
from skimmerdb._api.api.views import create_view

db = SkimmerDB()  # SKIMMERDB_KEY
answer = create_view.sync("support", client=db.api)
import { SkimmerDB } from "skimmerdb";
import { createView } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await createView({ client: db.client, path: { name: "support" }, body: {"name":"daily_signups","sql":"SELECT DATE_TRUNC('day', ts) AS day, plan, COUNT(*) AS signups FROM docs WHERE kind = 'signup' GROUP BY 1, 2"} });
201 answer
{
  "name": "daily_signups",
  "namespace": "events",
  "sql": "SELECT DATE_TRUNC('day', ts) AS day, plan, COUNT(*) AS signups FROM docs WHERE kind = 'signup' GROUP BY 1, 2",
  "created_at": "2026-10-18T09:00:00Z",
  "columns": [
    "day",
    "plan",
    "signups"
  ],
  "types": [
    "int",
    "text",
    "int"
  ]
}

List a namespace's views

GET /v1/namespaces/{name}/views

A view is a SQL query over one namespace (FROM docs) whose answer is kept as partials per segment: COUNT, SUM, MIN, MAX, AVG, COUNT(DISTINCT ...), COUNT_IF and f(...) FILTER (WHERE ...) over any WHERE, GROUP BY any expressions (DATE_TRUNC buckets, CASE, ...), with HAVING, ORDER BY and LIMIT applied on top. Name it as a table in SQL (SELECT * FROM daily_signups, or join it). It is always exact: a segment's partial is reused only while that segment's visible rows are the ones it was computed from, so a write or delete recomputes only the segments it touched. Views go with their namespace.

Parameters

namestring · pathrequiredThe namespace's name.

Answer

viewsView[]
views[].namestring
views[].namespacestring
views[].sqlstring
views[].created_atstring

Status codes

200OK
401No key, or an unknown or revoked one.
404No such namespace, document, key or tenant (or one this key may not see: the same answer).
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds.
curl -s https://api.skimmerdb.com/v1/namespaces/support/views \
  -H "Authorization: Bearer $KEY"
from skimmerdb import SkimmerDB
from skimmerdb._api.api.views import list_views

db = SkimmerDB()  # SKIMMERDB_KEY
answer = list_views.sync("support", client=db.api)
import { SkimmerDB } from "skimmerdb";
import { listViews } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await listViews({ client: db.client, path: { name: "support" } });
200 answer
{
  "views": [
    {
      "name": "daily_signups",
      "namespace": "events",
      "sql": "SELECT DATE_TRUNC('day', ts) AS day, COUNT(*) AS signups FROM docs GROUP BY 1",
      "created_at": "2026-10-18T09:00:00Z"
    }
  ]
}

Get a view

GET /v1/namespaces/{name}/views/{view}

Parameters

namestring · pathrequiredThe namespace's name.
viewstring · pathrequired

Answer

namestring
namespacestring
sqlstring
created_atstring

Status codes

200OK
401No key, or an unknown or revoked one.
404No such namespace, document, key or tenant (or one this key may not see: the same answer).
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds.
curl -s https://api.skimmerdb.com/v1/namespaces/support/views/view \
  -H "Authorization: Bearer $KEY"
from skimmerdb import SkimmerDB
from skimmerdb._api.api.views import get_view

db = SkimmerDB()  # SKIMMERDB_KEY
answer = get_view.sync("support", "view", client=db.api)
import { SkimmerDB } from "skimmerdb";
import { getView } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await getView({ client: db.client, path: { name: "support", view: "view" } });
200 answer
{
  "name": "daily_signups",
  "namespace": "events",
  "sql": "SELECT DATE_TRUNC('day', ts) AS day, COUNT(*) AS signups FROM docs GROUP BY 1",
  "created_at": "2026-10-18T09:00:00Z"
}

Delete a view

DELETE /v1/namespaces/{name}/views/{view}

Its kept partials go with the segments they describe.

Parameters

namestring · pathrequiredThe namespace's name.
viewstring · pathrequired

Status codes

204Done (no body)
401No key, or an unknown or revoked one.
403The key's scope or namespaces don't allow it, or the tenant is suspended.
404No such namespace, document, key or tenant (or one this key may not see: the same answer).
429Over the tenant's or the key's rate, concurrency or cap, or writes arriving faster than the namespace commits them (code write_busy): retry after Retry-After seconds.
curl -s -X DELETE https://api.skimmerdb.com/v1/namespaces/support/views/view \
  -H "Authorization: Bearer $KEY"
from skimmerdb import SkimmerDB
from skimmerdb._api.api.views import delete_view

db = SkimmerDB()  # SKIMMERDB_KEY
answer = delete_view.sync("support", "view", client=db.api)
import { SkimmerDB } from "skimmerdb";
import { deleteView } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await deleteView({ client: db.client, path: { name: "support", view: "view" } });