SDK Connection Guide

This guide shows how to connect to your self-hosted WoWSQL instance from JavaScript, Python, and other languages using the WoWSQL SDK or raw HTTP.

Getting Your Credentials

You need two values to connect:

  1. API URL — The Kong gateway address (default: http://localhost:8080)
  2. Anon Key — The public API key with the anon role

Both are available in the dashboard under Settings. The anon key is a JWT that looks like:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbi...

JavaScript / TypeScript

Install

npm install @wowsql/sdk-js

Initialize

import { createClient } from '@wowsql/sdk-js'

const wowsql = createClient(
  'http://localhost:8080',  // Your API URL
  'YOUR_ANON_KEY'           // From Settings page
)

Query data

// Select all rows
const { data, error } = await wowsql
  .from('todos')
  .select('*')

// Insert a row
const { data, error } = await wowsql
  .from('todos')
  .insert({ title: 'Buy groceries', completed: false })

// Update
const { data, error } = await wowsql
  .from('todos')
  .update({ completed: true })
  .eq('id', 1)

// Delete
const { error } = await wowsql
  .from('todos')
  .delete()
  .eq('id', 1)

Authentication

// Sign up a new user
const { data, error } = await wowsql.auth.signUp({
  email: 'user@example.com',
  password: 'secure-password'
})

// Sign in
const { data, error } = await wowsql.auth.signInWithPassword({
  email: 'user@example.com',
  password: 'secure-password'
})

// Get current user
const { data: { user } } = await wowsql.auth.getUser()

// Sign out
await wowsql.auth.signOut()

Realtime subscriptions

const channel = wowsql
  .channel('todos-changes')
  .on('postgres_changes',
    { event: '*', schema: 'public', table: 'todos' },
    (payload) => {
      console.log('Change:', payload)
    }
  )
  .subscribe()

Storage

// Upload a file
const { data, error } = await wowsql.storage
  .from('avatars')
  .upload('user1.png', file)

// Get public URL
const { data } = wowsql.storage
  .from('avatars')
  .getPublicUrl('user1.png')

Python

Install

pip install wowsql

Initialize

from wowsql import create_client

client = create_client(
    "http://localhost:8080",  # Your API URL
    "YOUR_ANON_KEY"           # From Settings page
)

Query data

# Select
response = client.table("todos").select("*").execute()
print(response.data)

# Insert
response = client.table("todos").insert({
    "title": "Buy groceries",
    "completed": False
}).execute()

# Update
response = client.table("todos").update({
    "completed": True
}).eq("id", 1).execute()

# Delete
response = client.table("todos").delete().eq("id", 1).execute()

Authentication

# Sign up
response = client.auth.sign_up({
    "email": "user@example.com",
    "password": "secure-password"
})

# Sign in
response = client.auth.sign_in_with_password({
    "email": "user@example.com",
    "password": "secure-password"
})

Raw HTTP (cURL)

You can use any HTTP client. Pass the anon key in both headers:

Read data

curl 'http://localhost:8080/rest/v1/todos?select=*' \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer YOUR_ANON_KEY"

Insert data

curl 'http://localhost:8080/rest/v1/todos' \
  -X POST \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: return=representation" \
  -d '{"title": "Buy groceries", "completed": false}'

Filter and paginate

# Filter: completed = true
curl 'http://localhost:8080/rest/v1/todos?completed=eq.true' \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer YOUR_ANON_KEY"

# Paginate: 10 items starting from offset 20
curl 'http://localhost:8080/rest/v1/todos?select=*&limit=10&offset=20' \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer YOUR_ANON_KEY"

# Order by created_at descending
curl 'http://localhost:8080/rest/v1/todos?order=created_at.desc' \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer YOUR_ANON_KEY"

Authenticate a user

# Sign up
curl 'http://localhost:8080/auth/v1/signup' \
  -X POST \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "password": "securepass"}'

# Sign in (returns access_token)
curl 'http://localhost:8080/auth/v1/token?grant_type=password' \
  -X POST \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "password": "securepass"}'

Use authenticated token

After signing in, use the returned access_token in subsequent requests:

curl 'http://localhost:8080/rest/v1/todos' \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer USER_ACCESS_TOKEN"
Note: The apikey header always uses the anon key. The Authorization header uses the user's access token after login. This tells PostgREST to execute queries as the authenticated role.

Using the Service Role Key

The service role key bypasses Row Level Security. Use it only in server-side code (backend APIs, scripts, admin tools).

// Server-side only
const admin = createClient(
  'http://localhost:8080',
  'YOUR_SERVICE_ROLE_KEY'
)

// This bypasses all RLS policies
const { data } = await admin
  .from('todos')
  .select('*')
Never expose the service role key in client-side code. It grants unrestricted access to all data in your database.

Row Level Security Basics

After creating a table, enable RLS and write policies to control access:

-- Enable RLS on the table
ALTER TABLE public.todos ENABLE ROW LEVEL SECURITY;

-- Allow anyone to read all todos
CREATE POLICY "Public read access"
  ON public.todos FOR SELECT
  USING (true);

-- Only the owner can insert
CREATE POLICY "Users insert own todos"
  ON public.todos FOR INSERT
  WITH CHECK (auth.uid() = user_id);

-- Only the owner can update
CREATE POLICY "Users update own todos"
  ON public.todos FOR UPDATE
  USING (auth.uid() = user_id);

-- Only the owner can delete
CREATE POLICY "Users delete own todos"
  ON public.todos FOR DELETE
  USING (auth.uid() = user_id);
Tip: Without RLS policies, a table with RLS enabled returns empty results for the anon and authenticated roles. Always create at least a SELECT policy.