API Reference

Base URL: http://localhost:8787/api/v1 (local). For deployed apps, run teeny status and append /api/v1 to the exact URL it prints.

Auth header: Authorization: Bearer <token>

Admin API auth: Authorization: Bearer <ADMIN_SERVICE_TOKEN>

Legacy note: a raw Authorization: <ADMIN_SERVICE_TOKEN> header is still accepted for admin access, but Bearer is the documented format. X-Service-Token is not supported.

CRUD

Insert

POST /table/{table}/insert
json
{
  "values": { "title": "Hello", "body": "World" },
  "returning": "*"
}

Select

GET /table/{table}/select?where=published==true&order=-created&limit=10&select=id,title

Or POST to the same endpoint with JSON body:

json
{
  "where": "published == true",
  "order": "-created",
  "limit": 10,
  "select": "id,title"
}

where uses teenybase expression syntax, not raw SQL. Use operators like ==, !=, =, ~, !~, <, <=, >, >=, &, |, !, in, ||, ->, and ->>.

Examples:

  • content~'%note%'
  • published == true & author == auth.uid
  • role in ['editor','admin']

Do not send raw SQL fragments like content LIKE '%note%' or a = 1 AND b = 2. Use ~ instead of LIKE, and & / | instead of AND / OR.

List (with total count)

GET /table/{table}/list?where=...&limit=10

The same endpoint also accepts POST with the same JSON body shape as select. Returns { "items": [...], "total": 42 }.

View

GET /table/{table}/view/{id}

Update

POST /table/{table}/update
json
{
  "where": "id == 'post-123'",
  "setValues": { "published": 1 },
  "returning": "*"
}

If you omit returning, the response is an empty array [].

Edit (single record shorthand)

POST /table/{table}/edit/{id}
json
{ "title": "Updated Title" }

Returns the updated record (defaults to returning the uid field, or * if no uid mapping).

Delete

POST /table/{table}/delete
json
{
  "where": "id == 'post-123'",
  "returning": "*"
}

If you omit returning, the response is an empty array [].

Auth

All auth endpoints are under /table/{table}/auth/.

Sign up

POST /table/{table}/auth/sign-up
json
{ "username": "alice", "email": "alice@test.com", "password": "secret123", "name": "Alice" }

Returns { "token", "refresh_token", "record", "verified" }.

Body fields must match your auth table schema. If you use the scaffolded authFields, name is required.

If your auth extension sets passwordConfirmSuffix (the default scaffold uses 'Confirm'), also send the matching confirm field, for example passwordConfirm.

Login

POST /table/{table}/auth/login-password
json
{ "identity": "alice@test.com", "password": "secret123" }

identity can be email or username.

Refresh token

POST /table/{table}/auth/refresh-token
json
{ "refresh_token": "..." }

Send the current access token in Authorization: Bearer <token> as well.

Password reset

POST /table/{table}/auth/request-password-reset
{ "email": "alice@test.com" }

POST /table/{table}/auth/confirm-password-reset
{ "token": "from-email", "password": "newpassword" }

Use the user's email address in the email field.

If your auth extension sets passwordConfirmSuffix, include the confirm field here too.

Email verification

POST /table/{table}/auth/request-verification
Authorization: Bearer <token>

POST /table/{table}/auth/confirm-verification
{ "token": "from-email" }

OAuth

GET /table/{table}/auth/oauth/{provider}           # Start redirect flow
GET /table/{table}/auth/oauth/{provider}/callback   # Callback (register in provider dashboard)
POST /table/{table}/auth/google-login               # Google One Tap form POST
POST /table/{table}/auth/login-token                # Bearer token login
POST /table/{table}/auth/logout                     # Invalidate current session
POST /auth/logout                                   # Clear auth cookie only

/auth/google-login expects application/x-www-form-urlencoded with credential and g_csrf_token.

Files

GET /files/{table}/{record_id}/{path}   # Download file by stored file name/path

path is the stored file value from the record, not the field name.

Upload via multipart form data on insert/update:

bash
curl -X POST http://localhost:8787/api/v1/table/posts/insert \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -F '@filePayload=@photo.jpg' \
  -F '@jsonPayload={"values":{"title":"My Post","cover_image":"@filePayload.0"}}'

Other

GET /health          # Health check
GET /doc             # OpenAPI 3.1.0 spec (JSON)
GET /doc/ui          # Swagger UI

Actions

POST /action/{name}
json
{ "post_id": "abc-123" }

Params defined in the action config.