Reference

HTTP API reference

Base URL https://api.atberth.com/v1. JSON in and out, except where a route says otherwise. The machine readable version is /v1/openapi.json (OpenAPI 3.1), generated from the same route table the server dispatches with.

Send credentials as Authorization: Bearer <key or token>. A publishable key may go in apikey instead. Every response has X-Request-Id; errors look like {"error", "message", "request_id"} and are listed in Limits and errors. The examples run in order and create the app they use.

Platform and accounts

GET/v1/health

curl -sS https://api.atberth.com/v1/health

GET/v1/status

Returns ok, version, database, functions_runtime, and uptime_seconds.

curl -sS https://api.atberth.com/v1/status

GET/v1/openapi.json

curl -sS https://api.atberth.com/v1/openapi.json | jq -r '.paths | keys[]'

POST/v1/signup

Body {"email"}. Answers 202 {"sent": true, "email"} and emails a 6 digit code.

curl -sS -X POST https://api.atberth.com/v1/signup \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com"}'

POST/v1/login

With {"email"} it emails a code (202). With {"email", "code", "key_name"?} it returns {"key": "bak_...", "account"}. The key is shown once.

curl -sS -X POST https://api.atberth.com/v1/login \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com"}'
curl -sS -X POST https://api.atberth.com/v1/login \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","code":"123456","key_name":"laptop"}'

GET/v1/me

Any credential. role is account, secret, publishable, or user.

curl -sS https://api.atberth.com/v1/me \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY"

GET/v1/account

curl -sS https://api.atberth.com/v1/account \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY"

GET/v1/account/keys

curl -sS https://api.atberth.com/v1/account/keys \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY"

POST/v1/account/keys

Body {"name"}. 201 {"key", "secret": "bak_..."}.

KEY_ID=$(curl -sS -X POST https://api.atberth.com/v1/account/keys \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"ci"}' | jq -er .key.id)

DELETE/v1/account/keys/{key_id}

curl -sS -X DELETE https://api.atberth.com/v1/account/keys/$KEY_ID \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY"

DELETE/v1/account?confirm=<email>

Deletes the account and all its apps. confirm must be the account email.

curl -sS -X DELETE "https://api.atberth.com/v1/account?confirm=you@example.com" \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY"

Operator routes (/v1/admin/accounts, /v1/admin/accounts/{account_id}, /v1/admin/codes) need the platform admin token and are not available to accounts.

Apps and keys

POST/v1/apps

Account key. Body {"name"}. 201 {"app", "keys": {"secret", "publishable"}}. Both keys are shown only here.

CREATED=$(curl -sS -X POST https://api.atberth.com/v1/apps \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"name\":\"$APP\"}")
SECRET_KEY=$(echo "$CREATED" | jq -er .keys.secret)
PUBLISHABLE_KEY=$(echo "$CREATED" | jq -er .keys.publishable)
echo "$CREATED" | jq .app

GET/v1/apps

curl -sS https://api.atberth.com/v1/apps \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY"

GET/v1/apps/{app}

Returns id, name, slug, created_at, cors_origins, api_url.

curl -sS https://api.atberth.com/v1/apps/$APP \
  -H "Authorization: Bearer $SECRET_KEY"

PATCH/v1/apps/{app}

curl -sS -X PATCH https://api.atberth.com/v1/apps/$APP \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"cors_origins":["*"]}'

GET/v1/apps/{app}/keys

Lists id, name, type, prefix, created_at, last_used_at, revoked_at. Never the key itself.

curl -sS https://api.atberth.com/v1/apps/$APP/keys \
  -H "Authorization: Bearer $SECRET_KEY"

POST/v1/apps/{app}/keys

Body {"name", "type": "secret" or "publishable"}. 201 {"key", "secret"}.

KEY_ID=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/keys \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"android build","type":"publishable"}' | jq -er .key.id)

DELETE/v1/apps/{app}/keys/{key_id}

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/keys/$KEY_ID \
  -H "Authorization: Bearer $SECRET_KEY"

GET/v1/apps/{app}/usage

curl -sS https://api.atberth.com/v1/apps/$APP/usage \
  -H "Authorization: Bearer $SECRET_KEY"

GET/v1/apps/{app}/logs?limit=&status=

Recent requests: created_at, method, path, status, duration_ms, key_type, request_id. Kept 7 days.

curl -sS "https://api.atberth.com/v1/apps/$APP/logs?limit=5" \
  -H "Authorization: Bearer $SECRET_KEY"

POST/v1/apps/{app}/sql

Body {"query", "params"?, "read_only"?, "timeout_ms"?}. Returns {"command", "columns", "rows", "row_count", "truncated"}.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/sql \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"select $1::int + 1 as answer","params":[41],"read_only":true}'

POST/v1/apps/{app}/rpc/{function}

Secret key. Calls a Postgres function in the app's public schema with a JSON object of named arguments. Returns the result as JSON: a value, or an array of objects for a function that returns a table.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/sql \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"create function add_nums(a integer, b integer) returns integer language sql as $$ select a + b $$"}'
curl -sS -X POST https://api.atberth.com/v1/apps/$APP/rpc/add_nums \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"a":2,"b":3}'

Schema

Column types: text, integer, bigint, numeric, double, boolean, date, timestamptz, uuid, jsonb, text[], integer[]. A column is {"name", "type", "default"?, "not_null"?, "unique"?, "references"?: {"table", "column"?, "on_delete"?}}. default is a JSON literal or one of "now()", "gen_random_uuid()", "current_date", "auth.uid()".

Every table gets id uuid primary key and created_at. "timestamps": false skips created_at; "updated_at": true adds an auto touched updated_at. Policy is {"read", "write"}, default secret and secret; see Row policies.

POST/v1/apps/{app}/tables

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/tables \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"profiles","columns":[{"name":"display_name","type":"text","not_null":true}],"policy":{"read":"public","write":"owner"}}'
curl -sS -X POST https://api.atberth.com/v1/apps/$APP/tables \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "notes",
    "columns": [
      {"name": "title", "type": "text", "not_null": true},
      {"name": "slug", "type": "text", "unique": true},
      {"name": "done", "type": "boolean", "default": false},
      {"name": "tags", "type": "text[]"},
      {"name": "profile_id", "type": "uuid", "references": {"table": "profiles", "on_delete": "set null"}}
    ],
    "updated_at": true
  }'

GET/v1/apps/{app}/tables

curl -sS https://api.atberth.com/v1/apps/$APP/tables \
  -H "Authorization: Bearer $SECRET_KEY"

GET/v1/apps/{app}/tables/{table}

Returns name, columns, primary_key, indexes, foreign_keys, policy, row_estimate.

curl -sS https://api.atberth.com/v1/apps/$APP/tables/notes \
  -H "Authorization: Bearer $SECRET_KEY"

PATCH/v1/apps/{app}/tables/{table}

Body {"name"?, "policy"?}.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/tables \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"drafts","columns":[{"name":"body","type":"text"}]}' > /dev/null
curl -sS -X PATCH https://api.atberth.com/v1/apps/$APP/tables/drafts \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"archive","policy":{"read":"authenticated","write":"secret"}}'

DELETE/v1/apps/{app}/tables/{table}

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/tables/archive \
  -H "Authorization: Bearer $SECRET_KEY"

POST/v1/apps/{app}/tables/{table}/columns

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/tables/notes/columns \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"priority","type":"integer","default":0,"not_null":true}'

PATCH/v1/apps/{app}/tables/{table}/columns/{column}

Body {"name"?, "type"?, "default"?, "drop_default"?, "not_null"?}.

curl -sS -X PATCH https://api.atberth.com/v1/apps/$APP/tables/notes/columns/priority \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"rank","type":"bigint","drop_default":true,"not_null":false}'

DELETE/v1/apps/{app}/tables/{table}/columns/{column}

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/tables/notes/columns/rank \
  -H "Authorization: Bearer $SECRET_KEY"

POST/v1/apps/{app}/tables/{table}/indexes

Body {"columns", "unique"?, "name"?}.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/tables/notes/indexes \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"columns":["done","created_at"],"name":"notes_done_created"}'

GET/v1/apps/{app}/tables/{table}/indexes

curl -sS https://api.atberth.com/v1/apps/$APP/tables/notes/indexes \
  -H "Authorization: Bearer $SECRET_KEY"

DELETE/v1/apps/{app}/tables/{table}/indexes/{index}

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/tables/notes/indexes/notes_done_created \
  -H "Authorization: Bearer $SECRET_KEY"

Rows

Auth is the table policy (secret key, publishable key, or user token). Query parameters for GET, PATCH, and DELETE on /rows: filters column=op.value (eq, neq, gt, gte, lt, lte, like, ilike, in.(a,b), is.null, is.true, is.false, cs, and not. before any), select, order, limit (1 to 1000, default 100), offset, cursor, count=exact. Details in Queries.

POST/v1/apps/{app}/tables/{table}/rows

An object or an array of up to 1,000. 201 {"rows"}, plus "row" for a single object.

ROW_ID=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/tables/notes/rows \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Buy milk","slug":"milk","tags":["home"]}' | jq -er .row.id)
curl -sS -X POST https://api.atberth.com/v1/apps/$APP/tables/notes/rows \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: bulk-$APP-1" \
  -d '[{"title":"Fix the sink","slug":"sink"},{"title":"Call the bank","slug":"bank","done":true}]'

POST/v1/apps/{app}/tables/{table}/rows?upsert=true&on_conflict=col

Insert or update by a unique column. 200 {"rows"}.

curl -sS -X POST "https://api.atberth.com/v1/apps/$APP/tables/notes/rows?upsert=true&on_conflict=slug" \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug":"milk","title":"Buy oat milk"}'

GET/v1/apps/{app}/tables/{table}/rows

{"rows", "next_cursor", "count"?}. Berth-Next-Cursor and X-Total-Count headers mirror the body.

curl -sS -G https://api.atberth.com/v1/apps/$APP/tables/notes/rows \
  -H "Authorization: Bearer $SECRET_KEY" \
  --data-urlencode "done=eq.false" \
  --data-urlencode "select=id,title" \
  --data-urlencode "order=created_at.desc" \
  --data-urlencode "limit=10" \
  --data-urlencode "count=exact"

GET/v1/apps/{app}/tables/{table}/rows/{id}

curl -sS https://api.atberth.com/v1/apps/$APP/tables/notes/rows/$ROW_ID \
  -H "Authorization: Bearer $SECRET_KEY"

PATCH/v1/apps/{app}/tables/{table}/rows/{id}

curl -sS -X PATCH https://api.atberth.com/v1/apps/$APP/tables/notes/rows/$ROW_ID \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"done":true}'

PATCH/v1/apps/{app}/tables/{table}/rows?filters

At least one filter is required. Returns {"rows"}.

curl -sS -X PATCH "https://api.atberth.com/v1/apps/$APP/tables/notes/rows?slug=eq.sink" \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"done":true}'

DELETE/v1/apps/{app}/tables/{table}/rows/{id}

Returns {"deleted": true, "id"}.

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/tables/notes/rows/$ROW_ID \
  -H "Authorization: Bearer $SECRET_KEY"

DELETE/v1/apps/{app}/tables/{table}/rows?filters

At least one filter is required. Returns {"deleted": n}.

curl -sS -X DELETE "https://api.atberth.com/v1/apps/$APP/tables/notes/rows?done=eq.true" \
  -H "Authorization: Bearer $SECRET_KEY"

POST/v1/apps/{app}/tables/{table}/import

Secret key. text/csv with a header row, or application/x-ndjson. Max 20 MB, all or nothing. Returns {"inserted": n}.

printf 'title,slug\nPlan trip,trip\nPay rent,rent\n' | \
  curl -sS -X POST https://api.atberth.com/v1/apps/$APP/tables/notes/import \
    -H "Authorization: Bearer $SECRET_KEY" \
    -H "Content-Type: text/csv" \
    --data-binary @-

GET/v1/apps/{app}/tables/{table}/stream

text/event-stream with insert, update, and delete events whose data is {"id", "type", "table", "record", "old_record", "at"}. Supports Last-Event-ID, ?events=, and ?apikey= / ?access_token= for browsers. Heartbeat every 15 s. See Realtime.

curl -sN --max-time 3 "https://api.atberth.com/v1/apps/$APP/tables/notes/stream?events=insert,update" \
  -H "Authorization: Bearer $SECRET_KEY" || [ $? -eq 28 ]

End-user auth

Under /v1/apps/{app}/auth. Needs the app's publishable or secret key, or a user token for me and logout. A session is {"user", "access_token", "token_type": "bearer", "expires_in": 3600, "refresh_token"}. See End-user auth.

POST/v1/apps/{app}/auth/signup

Body {"email", "password", "data"?}. 201 session.

SESSION=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/auth/signup \
  -H "apikey: $PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"ada@example.com","password":"correct horse battery","data":{"name":"Ada"}}')
ACCESS_TOKEN=$(echo "$SESSION" | jq -er .access_token)
REFRESH_TOKEN=$(echo "$SESSION" | jq -er .refresh_token)

POST/v1/apps/{app}/auth/login

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/auth/login \
  -H "apikey: $PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"ada@example.com","password":"correct horse battery"}' | jq .user

POST/v1/apps/{app}/auth/code

Body {"email"}. 202, emails a 6 digit code and creates the user if new.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/auth/code \
  -H "apikey: $PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"ada@example.com"}'

POST/v1/apps/{app}/auth/verify

Body {"email", "code"}. Returns a session.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/auth/verify \
  -H "apikey: $PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"ada@example.com","code":"123456"}'

POST/v1/apps/{app}/auth/refresh

Body {"refresh_token"}. Returns a new session and a new refresh token. Reusing an old refresh token revokes the whole chain.

SESSION=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/auth/refresh \
  -H "apikey: $PUBLISHABLE_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"refresh_token\":\"$REFRESH_TOKEN\"}")
ACCESS_TOKEN=$(echo "$SESSION" | jq -er .access_token)
REFRESH_TOKEN=$(echo "$SESSION" | jq -er .refresh_token)

GET/v1/apps/{app}/auth/me

curl -sS https://api.atberth.com/v1/apps/$APP/auth/me \
  -H "Authorization: Bearer $ACCESS_TOKEN"

PATCH/v1/apps/{app}/auth/me

Body {"password"?, "data"?}.

curl -sS -X PATCH https://api.atberth.com/v1/apps/$APP/auth/me \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data":{"name":"Ada Lovelace"}}'

POST/v1/apps/{app}/auth/logout

Body {"all"?: bool}. Returns {"signed_out": true}.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/auth/logout \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"all":true}'

GET/v1/apps/{app}/auth/users

curl -sS https://api.atberth.com/v1/apps/$APP/auth/users \
  -H "Authorization: Bearer $SECRET_KEY"

POST/v1/apps/{app}/auth/users

Secret key. Body {"email", "password"?, "data"?}. 201 {"user"}.

USER_ID=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/auth/users \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"grace@example.com","data":{"name":"Grace"}}' | jq -er .user.id)

GET/v1/apps/{app}/auth/users/{user_id}

curl -sS https://api.atberth.com/v1/apps/$APP/auth/users/$USER_ID \
  -H "Authorization: Bearer $SECRET_KEY"

PATCH/v1/apps/{app}/auth/users/{user_id}

Body {"banned"?, "data"?, "password"?}.

curl -sS -X PATCH https://api.atberth.com/v1/apps/$APP/auth/users/$USER_ID \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"banned":true}'

DELETE/v1/apps/{app}/auth/users/{user_id}

Deletes the user and the rows they own.

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/auth/users/$USER_ID \
  -H "Authorization: Bearer $SECRET_KEY"

Storage

A bucket is {"name", "read", "write", "max_file_size"?, "allowed_types"?}. See Storage.

POST/v1/apps/{app}/storage/buckets

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/storage/buckets \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"files","read":"secret","write":"secret","max_file_size":1000000}'

GET/v1/apps/{app}/storage/buckets

curl -sS https://api.atberth.com/v1/apps/$APP/storage/buckets \
  -H "Authorization: Bearer $SECRET_KEY"

GET/v1/apps/{app}/storage/buckets/{bucket}

curl -sS https://api.atberth.com/v1/apps/$APP/storage/buckets/files \
  -H "Authorization: Bearer $SECRET_KEY"

PATCH/v1/apps/{app}/storage/buckets/{bucket}

curl -sS -X PATCH https://api.atberth.com/v1/apps/$APP/storage/buckets/files \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"read":"authenticated","allowed_types":["text/*"]}'

PUT/v1/apps/{app}/storage/objects/{bucket}/{key}

Raw body. Content-Type is stored. Overwrites.

echo "hello from Berth" > hello.txt
curl -sS -X PUT https://api.atberth.com/v1/apps/$APP/storage/objects/files/docs/hello.txt \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: text/plain" \
  --data-binary @hello.txt

GET/v1/apps/{app}/storage/objects/{bucket}?prefix=&limit=

curl -sS "https://api.atberth.com/v1/apps/$APP/storage/objects/files?prefix=docs/&limit=50" \
  -H "Authorization: Bearer $SECRET_KEY"

GET/v1/apps/{app}/storage/objects/{bucket}/{key}

The raw file. Auth by read policy, or ?expires=&signature= from a signed URL. ?download=1 sends it as an attachment.

curl -sS https://api.atberth.com/v1/apps/$APP/storage/objects/files/docs/hello.txt \
  -H "Authorization: Bearer $SECRET_KEY"

POST/v1/apps/{app}/storage/sign/{bucket}/{key}

Body {"expires_in": seconds}. Returns {"url", "expires_at"}.

SIGNED_URL=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/storage/sign/files/docs/hello.txt \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expires_in":300}' | jq -er .url)
curl -sS "$SIGNED_URL"

DELETE/v1/apps/{app}/storage/objects/{bucket}/{key}

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/storage/objects/files/docs/hello.txt \
  -H "Authorization: Bearer $SECRET_KEY"

DELETE/v1/apps/{app}/storage/buckets/{bucket}

The bucket must be empty, unless ?force=true.

curl -sS -X DELETE "https://api.atberth.com/v1/apps/$APP/storage/buckets/files?force=true" \
  -H "Authorization: Bearer $SECRET_KEY"

Functions

One TypeScript or JavaScript file on Deno. See Functions for the sandbox and injected env.

PUT/v1/apps/{app}/functions/{name}/deployment

Body {"source", "verify"?: "key", "user", or "none", "timeout_ms"?, "memory_mb"?, "schedule"?}. 201 on the first deploy, 200 on a redeploy. Returns {"function"} with name, verify, schedule, timeout_ms, memory_mb, version, and url. schedule is five cron fields in UTC or @hourly, @daily, @weekly, @monthly; leaving it out keeps the current one, and null removes it. See Schedules.

cat > echo.ts <<'EOF'
export default async (req: Request) => Response.json({ method: req.method, body: await req.text() });
EOF
jq -n --rawfile source echo.ts '{source: $source, verify: "key"}' | \
  curl -sS -X PUT https://api.atberth.com/v1/apps/$APP/functions/echo/deployment \
    -H "Authorization: Bearer $SECRET_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @-
jq -n --rawfile source echo.ts '{source: $source, schedule: "@hourly"}' | \
  curl -sS -X PUT https://api.atberth.com/v1/apps/$APP/functions/echo/deployment \
    -H "Authorization: Bearer $SECRET_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @- | jq -e '.function.schedule == "@hourly"'
jq -n --rawfile source echo.ts '{source: $source, schedule: null}' | \
  curl -sS -X PUT https://api.atberth.com/v1/apps/$APP/functions/echo/deployment \
    -H "Authorization: Bearer $SECRET_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @- | jq -e '.function.schedule == null'

GET/v1/apps/{app}/functions

curl -sS https://api.atberth.com/v1/apps/$APP/functions \
  -H "Authorization: Bearer $SECRET_KEY"

GET/v1/apps/{app}/functions/{name}/deployment

curl -sS https://api.atberth.com/v1/apps/$APP/functions/echo/deployment \
  -H "Authorization: Bearer $SECRET_KEY"

ANY/v1/apps/{app}/functions/{name}

Auth per verify. The function's own response.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/functions/echo \
  -H "apikey: $PUBLISHABLE_KEY" \
  -d 'ping'

GET/v1/apps/{app}/functions/{name}/logs?limit=

curl -sS "https://api.atberth.com/v1/apps/$APP/functions/echo/logs?limit=10" \
  -H "Authorization: Bearer $SECRET_KEY"

DELETE/v1/apps/{app}/functions/{name}/deployment

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/functions/echo/deployment \
  -H "Authorization: Bearer $SECRET_KEY"

Env vars

Names match ^[A-Z][A-Z0-9_]{0,63}$ and may not start with BERTH_ or DENO_. Values are never returned.

PUT/v1/apps/{app}/env/{name}

curl -sS -X PUT https://api.atberth.com/v1/apps/$APP/env/MAIL_FROM \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"value":"notes@example.com"}'

GET/v1/apps/{app}/env

curl -sS https://api.atberth.com/v1/apps/$APP/env \
  -H "Authorization: Bearer $SECRET_KEY"

DELETE/v1/apps/{app}/env/{name}

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/env/MAIL_FROM \
  -H "Authorization: Bearer $SECRET_KEY"

Webhooks

See Webhooks for the payload, signature, and retries.

POST/v1/apps/{app}/webhooks

Body {"url", "table"?, "events"?, "description"?}. The signing secret is returned once.

WEBHOOK_ID=$(curl -sS -X POST https://api.atberth.com/v1/apps/$APP/webhooks \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/berth-webhook","table":"notes","events":["insert"]}' | jq -er .webhook.id)

GET/v1/apps/{app}/webhooks

curl -sS https://api.atberth.com/v1/apps/$APP/webhooks \
  -H "Authorization: Bearer $SECRET_KEY"

GET/v1/apps/{app}/webhooks/{webhook_id}

curl -sS https://api.atberth.com/v1/apps/$APP/webhooks/$WEBHOOK_ID \
  -H "Authorization: Bearer $SECRET_KEY"

PATCH/v1/apps/{app}/webhooks/{webhook_id}

Body {"url"?, "events"?, "enabled"?}.

curl -sS -X PATCH https://api.atberth.com/v1/apps/$APP/webhooks/$WEBHOOK_ID \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"events":["insert","update","delete"],"enabled":true}'

POST/v1/apps/{app}/webhooks/{webhook_id}/test

Sends a ping event.

curl -sS -X POST https://api.atberth.com/v1/apps/$APP/webhooks/$WEBHOOK_ID/test \
  -H "Authorization: Bearer $SECRET_KEY"

GET/v1/apps/{app}/webhooks/{webhook_id}/deliveries

curl -sS https://api.atberth.com/v1/apps/$APP/webhooks/$WEBHOOK_ID/deliveries \
  -H "Authorization: Bearer $SECRET_KEY"

DELETE/v1/apps/{app}/webhooks/{webhook_id}

curl -sS -X DELETE https://api.atberth.com/v1/apps/$APP/webhooks/$WEBHOOK_ID \
  -H "Authorization: Bearer $SECRET_KEY"

Export, restore, delete

GET/v1/apps/{app}/export

Secret key. A binary pg_dump custom format file (application/octet-stream).

curl -sS -o app.dump https://api.atberth.com/v1/apps/$APP/export \
  -H "Authorization: Bearer $SECRET_KEY"

POST/v1/apps/{app}/restore

Account key. The binary dump as the body. 201, creates a new app named {app}, answered like POST /v1/apps.

curl -sS -X POST https://api.atberth.com/v1/apps/${APP}_copy/restore \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @app.dump | jq .app

DELETE/v1/apps/{app}

Account key. Drops the app's database, role, keys, users, files, functions, and webhooks.

curl -sS -X DELETE https://api.atberth.com/v1/apps/${APP}_copy \
  -H "Authorization: Bearer $BERTH_ACCOUNT_KEY"