API reference

Accounts

Sign up, log in, who you are.

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

Sign up

POST /v1/signup no key

Makes a person, their first tenant and its first API key (full access, scope admin): the answer's key is ready to use and shown only here. Make narrower keys (read or write, some namespaces, caps) for apps and agents with POST /v1/keys.

Body application/json

emailstringrequired
namestringrequiredYour name; also your first tenant's name.
passwordstringrequired

Answer

idintegerYour user id.
tenant_idintegerYour first tenant (it owns namespaces, keys and usage).
keystringYour first API key, full access (scope admin): shown only here. Send it as Authorization: Bearer . Make narrower keys for apps and agents with POST /v1/keys.
key_idinteger
key_prefixstringThe key's first characters, as key listings show it.
scopestringadmin.

Status codes

201Created
400Malformed: not the JSON expected.
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).
curl -s https://api.skimmerdb.com/v1/signup \
  -d '{"email":"ada@example.com","name":"Ada","password":"correct horse"}'
from skimmerdb import SkimmerDB
from skimmerdb._api.api.accounts import signup
from skimmerdb._api.models import SignupRequest

db = SkimmerDB()  # SKIMMERDB_KEY
answer = signup.sync(client=db.api, body=SignupRequest.from_dict({"email":"ada@example.com","name":"Ada","password":"correct horse"}))
import { SkimmerDB } from "skimmerdb";
import { signup } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await signup({ client: db.client, body: {"email":"ada@example.com","name":"Ada","password":"correct horse"} });
201 answer
{
  "id": 42,
  "tenant_id": 42,
  "key": "tb_3q2-Xw9Lk2bFz0aQvP1mYc7RnT4sUe8d",
  "key_id": 7,
  "key_prefix": "tb_3q2-Xw9",
  "scope": "admin"
}

Log in

POST /v1/login no key

A login token (JWT, valid a day) for managing your account: keys, tenants, billing. It acts for your default tenant, or the one named by X-Tenant. Not needed to start: signup's answer has a key.

Body application/json

emailstringrequired
passwordstringrequired

Answer

tokenstring

Status codes

200OK
400Malformed: not the JSON expected.
401No key, or an unknown or revoked one.
curl -s https://api.skimmerdb.com/v1/login \
  -d '{"email":"ada@example.com","password":"correct horse"}'
from skimmerdb import SkimmerDB
from skimmerdb._api.api.accounts import login
from skimmerdb._api.models import LoginRequest

db = SkimmerDB()  # SKIMMERDB_KEY
answer = login.sync(client=db.api, body=LoginRequest.from_dict({"email":"ada@example.com","password":"correct horse"}))
import { SkimmerDB } from "skimmerdb";
import { login } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await login({ client: db.client, body: {"email":"ada@example.com","password":"correct horse"} });
200 answer
{
  "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0MiJ9.c2lnbmF0dXJl"
}

Verify an email

POST /v1/email/verify no key

Uses the link a signup's email carries (single use, 7 days; skimmerdb.com/verify-email sends it here). Until an owner's email is verified a free tenant gets 1% of the free plan (402 email_unverified past it); after, all of it.

Body application/json

tokenstringrequiredFrom the emailed link (its token= part).

Answer

verifiedboolean

Status codes

200OK
400Malformed: not the JSON expected.
curl -s https://api.skimmerdb.com/v1/email/verify \
  -d '{"token":"q7Xc2bN0rT5mVw8sKe1dZy4uHf6jLa3p"}'
from skimmerdb import SkimmerDB
from skimmerdb._api.api.accounts import verify_email

db = SkimmerDB()  # SKIMMERDB_KEY
answer = verify_email.sync(client=db.api)
import { SkimmerDB } from "skimmerdb";
import { verifyEmail } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await verifyEmail({ client: db.client, body: {"token":"q7Xc2bN0rT5mVw8sKe1dZy4uHf6jLa3p"} });
200 answer
{
  "verified": true
}

Send a new verification link

POST /v1/email/verify/resend

Emails the signed-in person (or the key's person) a new link, at most once a minute. verified: true when there is nothing to verify.

Answer

verifiedboolean
sentboolean

Status codes

202OK
400Malformed: not the JSON expected.
401No key, or an unknown or revoked one.
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 POST https://api.skimmerdb.com/v1/email/verify/resend \
  -H "Authorization: Bearer $KEY"
from skimmerdb import SkimmerDB
from skimmerdb._api.api.accounts import resend_verification

db = SkimmerDB()  # SKIMMERDB_KEY
answer = resend_verification.sync(client=db.api)
import { SkimmerDB } from "skimmerdb";
import { resendVerification } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await resendVerification({ client: db.client });
202 answer
{
  "verified": false,
  "sent": true
}

Ask for a password reset link

POST /v1/password/forgot no key

Emails a reset link (single use, an hour) to the address if it has an account. The answer is the same either way.

Body application/json

emailstringrequired

Answer

sentboolean

Status codes

202OK
400Malformed: not the JSON expected.
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/password/forgot \
  -d '{"email":"ada@example.com"}'
from skimmerdb import SkimmerDB
from skimmerdb._api.api.accounts import forgot_password

db = SkimmerDB()  # SKIMMERDB_KEY
answer = forgot_password.sync(client=db.api)
import { SkimmerDB } from "skimmerdb";
import { forgotPassword } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await forgotPassword({ client: db.client, body: {"email":"ada@example.com"} });
202 answer
{
  "sent": true
}

Set a new password

POST /v1/password/reset no key

Uses a reset link's token (once) to set the password; it also verifies the email, and the account's other reset links stop working.

Body application/json

tokenstringrequired
passwordstringrequired

Answer

resetboolean

Status codes

200OK
400Malformed: not the JSON expected.
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).
curl -s https://api.skimmerdb.com/v1/password/reset \
  -d '{"token":"q7Xc2bN0rT5mVw8sKe1dZy4uHf6jLa3p","password":"a better horse"}'
from skimmerdb import SkimmerDB
from skimmerdb._api.api.accounts import reset_password

db = SkimmerDB()  # SKIMMERDB_KEY
answer = reset_password.sync(client=db.api)
import { SkimmerDB } from "skimmerdb";
import { resetPassword } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await resetPassword({ client: db.client, body: {"token":"q7Xc2bN0rT5mVw8sKe1dZy4uHf6jLa3p","password":"a better horse"} });
200 answer
{
  "reset": true
}

Who am I

GET /v1/me

You, the tenant you act for (tenant_id), its plan, your scope and a key's namespaces.

Answer

idinteger
emailstring
namestring
org_idinteger
org_namestring
planPlan
plan.namestring
plan.price_monthnumber
plan.included_gb_monthsnumber
plan.included_write_gbnumber
plan.included_queriesinteger
plan.included_writesinteger
plan.included_embed_tokensinteger
plan.per_gb_monthnumber
plan.per_gb_writtennumber
plan.per_million_queriesnumber
plan.per_million_embed_tokensnumber
plan.per_million_store_getsnumber
plan.hard_limitboolean
plan.qpsinteger
plan.concurrencyinteger
plan.storage_quota_gbnumber
plan.read_inflight_mbinteger
plan.sql_secondsinteger
plan.sql_concurrencyinteger
plan.query_secondsinteger
plan.max_namespacesinteger
plan.included_cpu_secondsnumber
plan.included_store_getsinteger
plan.included_out_gbnumber
plan.max_creates_dayinteger
plan.unverified_sharenumber
tenant_idintegerThe tenant this call acts for.
scopestringread, write or admin.
key_idintegerThe key used (0: a login).
namespacesstring[]
is_adminboolean
email_verifiedbooleanfalse: until verified, a free tenant has 1% of the plan (plan shows what applies now).

Status codes

200OK
401No key, or an unknown or revoked one.
curl -s https://api.skimmerdb.com/v1/me \
  -H "Authorization: Bearer $KEY"
from skimmerdb import SkimmerDB
from skimmerdb._api.api.accounts import get_me

db = SkimmerDB()  # SKIMMERDB_KEY
answer = get_me.sync(client=db.api)
import { SkimmerDB } from "skimmerdb";
import { getMe } from "skimmerdb/api";

const db = new SkimmerDB(); // SKIMMERDB_KEY
const { data } = await getMe({ client: db.client });