C# SDK
C# / .NET Quick Start
WowSQL · WOWSQL.SDK · PostgreSQL REST API
Get your API keys: In your WowSQL project dashboard, go to Settings → API to find your anon key (wowsql_anon_...) and service role key (wowsql_service_...). The anon key is safe for client-side use (respects Row Level Security). The service role key bypasses RLS and should only be used server-side.
Installation
NuGet: WOWSQL.SDK on nuget.org →
.NET CLI:
dotnet add package WOWSQL.SDK
Package Manager:
Install-Package WOWSQL.SDK
PackageReference:
<PackageReference Include="WOWSQL.SDK" Version="2.0.0" />
Targets .NET Standard 2.0 (works with .NET Framework 4.6.1+ and .NET Core / 5+).
Namespace
All types are in using WOWSQL; — class names are WOWSQLClient, ProjectAuthClient, WOWSQLStorage, WOWSQLSchema.
Initialize database client
using WOWSQL;
using System.Collections.Generic;
using System.Threading.Tasks;
// URL resolves to: https://myproject.wowsqlconnect.com
// SDK talks to PostgREST at /rest/v1/
var client = new WOWSQLClient(
projectUrl: "myproject", // slug or full URL
apiKey: "wowsql_anon_your_key_here",
baseDomain: "wowsqlconnect.com",
secure: true,
timeout: 30,
verifySsl: true
);
// Query: always Select() before GetAsync() on the builder
var users = await client.Table("users").Select("*").GetAsync();
Query data
Basic
var all = await client.Table("users").Select("*").GetAsync();
var adults = await client.Table("users").Select("*").Gte("age", 18).GetAsync();
var names = await client.Table("users").Select("id", "name").GetAsync();
Chained filters & paging
var active = await client.Table("users")
.Select("*")
.Eq("status", "active")
.Gt("age", 18)
.Order("created_at", "desc")
.Limit(20)
.Offset(0)
.GetAsync();
System.Console.WriteLine($"Count: {active.Count}");
foreach (var row in active.Data)
System.Console.WriteLine(row["name"]);
GROUP BY / HAVING (POST when needed)
var stats = await client.Table("products")
.Select("category", "COUNT(*) as count", "AVG(price) as avg_price")
.GroupBy("category")
.Having("COUNT(*)", "gt", 10)
.GetAsync();
CRUD
var created = await client.Table("users").CreateAsync(new Dictionary<string, object> {
["name"] = "Jane",
["email"] = "jane@example.com"
});
// created.Id, created.Message
await client.Table("users").UpdateAsync(created.Id, new Dictionary<string, object> {
["email"] = "new@example.com"
});
await client.Table("users").DeleteAsync(created.Id);
var one = await client.Table("users").GetByIdAsync(123);
var first = await client.Table("users").Eq("status", "active").FirstAsync();
Error handling
try
{
var res = await client.Table("users").Select("*").GetAsync();
}
catch (WOWSQLException ex)
{
if (ex.StatusCode == 401) { /* bad API key */ }
}
finally { client.Dispose(); }
// or
using (var c = new WOWSQLClient("myproject", "wowsql_anon_your_key_here"))
{
var r = await c.Table("users").Select("*").GetAsync();
}
Authentication — ProjectAuthClient
Authentication endpoints are served at /auth/v1/. Use your anon key for client-side auth operations.
// Auth endpoints: POST /auth/v1/signup, POST /auth/v1/login
// Header: apikey: wowsql_anon_your_key_here
using (var auth = new ProjectAuthClient(
projectUrl: "myproject",
apiKey: "wowsql_anon_your_key_here",
baseDomain: "wowsqlconnect.com"))
{
var session = await auth.SignUpAsync(
"user@example.com",
"SecurePassword123!",
"Full Name",
new Dictionary<string, object> { ["k"] = "v" });
auth.SetSession(session.Session.AccessToken, session.Session.RefreshToken);
var login = await auth.SignInAsync("user@example.com", "SecurePassword123!");
await auth.ForgotPasswordAsync("user@example.com");
}
OAuth Authentication
Setup checklist — do this once per provider, per project:
1. Dashboard → Project → Auth → Providers: enable the provider, paste Client ID and Client Secret (no leading/trailing spaces).
2. Copy the Redirect URI shown: https://<slug>.wowsqlconnect.com/auth/v1/oauth/<provider>/callback and register it in your provider's developer console.
3. The callback URL is handled entirely by WowSQL — your app does not send an API key on it. WowSQL exchanges the code and redirects to your frontend_redirect_uri with ?access_token=&refresh_token=.
using (var auth = new ProjectAuthClient(projectUrl: "myproject", apiKey: "wowsql_anon_your_key_here"))
{
// ── Step 1: Get the authorization URL ────────────────────────────────────
var oauth = await auth.GetOAuthAuthorizationUrlAsync(
"google",
"https://yourapp.com/auth/callback"
);
// Redirect the browser to oauth.AuthorizationUrl
// Google calls: https://<slug>.wowsqlconnect.com/auth/v1/oauth/google/callback
// WowSQL exchanges the code and redirects to your frontend_redirect_uri.
// ── Step 2: Read tokens from the redirect ────────────────────────────────
// WowSQL redirects to: https://yourapp.com/auth/callback?access_token=...&refresh_token=...
// ── (Advanced) Manual code exchange — only if you handle the callback yourself
var result = await auth.ExchangeOAuthCallbackAsync(
"google",
"authorization_code_from_callback",
"https://yourapp.com/auth/callback" // must match step 1
);
Console.WriteLine($"OAuth login successful: {result.User.Id}");
}
Storage — WOWSQLStorage (buckets)
Storage endpoints are served at /storage/v1/.
using (var storage = new WOWSQLStorage(
projectUrl: "myproject",
apiKey: "wowsql_service_your_key_here",
baseDomain: "wowsqlconnect.com",
timeout: 60))
{
// Upload — POST /storage/v1/object/{bucket}/{path}
var bucket = await storage.CreateBucketAsync("uploads", isPublic: false);
var file = await storage.UploadFromPathAsync(@".\doc.pdf", "uploads", path: "docs/doc.pdf");
// List — POST /storage/v1/object/list/{bucket}
var files = await storage.ListFilesAsync("uploads", prefix: "docs/", limit: 100, offset: 0);
// Public URL — GET /storage/v1/object/public/{bucket}/{path}
var url = storage.GetPublicUrl("uploads", "docs/doc.pdf");
// Download — GET /storage/v1/object/{bucket}/{path}
var quota = await storage.GetQuotaAsync();
}
Schema — WOWSQLSchema (service key only)
Requires service role key. The API requires the primaryKey column to be type UUID (not SERIAL). Use ["type"] = "UUID" with ["auto_increment"] = true for DEFAULT gen_random_uuid(). Raw CREATE TABLE via ExecuteSQL must not use integer/SERIAL primary keys.
using (var schema = new WOWSQLSchema(
projectUrl: "myproject",
serviceKey: "wowsql_service_your_key_here",
baseDomain: "wowsqlconnect.com"))
{
await schema.CreateTableAsync("items", new List<Dictionary<string, object>> {
new Dictionary<string, object> { ["name"] = "id", ["type"] = "UUID", ["auto_increment"] = true },
new Dictionary<string, object> { ["name"] = "title", ["type"] = "TEXT" }
}, primaryKey: "id");
var tables = await schema.ListTablesAsync();
}
Catch SchemaPermissionException if a non-service key is used.
Example API Call (REST)
The SDK wraps PostgREST. Here's what the underlying HTTP calls look like:
Query (GET)
GET https://myproject.wowsqlconnect.com/rest/v1/users?select=id,email,name&status=eq.active&order=created_at.desc&limit=10
Headers:
apikey: wowsql_anon_your_key_here
Content-Type: application/json
Insert (POST)
POST https://myproject.wowsqlconnect.com/rest/v1/users
Headers:
apikey: wowsql_anon_your_key_here
Content-Type: application/json
Prefer: return=representation
Body:
{
"name": "John Doe",
"email": "john@example.com",
"age": 30
}
Update (PATCH)
PATCH https://myproject.wowsqlconnect.com/rest/v1/users?id=eq.123
Headers:
apikey: wowsql_anon_your_key_here
Content-Type: application/json
Prefer: return=representation
Body:
{
"email": "newemail@example.com"
}
Delete (DELETE)
DELETE https://myproject.wowsqlconnect.com/rest/v1/users?id=eq.123
Headers:
apikey: wowsql_anon_your_key_here
NuGet package readme
Recent packages embed README.md so the gallery shows documentation. Unsigned packages show NU3004 under dotnet nuget verify — that is normal; publishing still works.