C# SDK
C# / .NET Quick Start
WowSQL · WOWSQL.SDK · PostgreSQL REST API
API keys: Copy Anonymous or Service role keys from the WowSQL project dashboard. Use the service role key only on servers (full DB, storage, schema). App data lives in the public schema via the REST API.
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;
var client = new WOWSQLClient(
projectUrl: "myproject", // slug or full URL
apiKey: "wowsql_anon_... or wowsql_service_...",
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", apiKey))
{
var r = await c.Table("users").Select("*").GetAsync();
}
Authentication — ProjectAuthClient
using (var auth = new ProjectAuthClient(
projectUrl: "myproject",
apiKey: "wowsql_anon_...",
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/api/auth/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_..."))
{
// ── 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/api/auth/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)
using (var storage = new WOWSQLStorage(
projectUrl: "myproject",
apiKey: "wowsql_service_...",
baseDomain: "wowsqlconnect.com",
timeout: 60))
{
var bucket = await storage.CreateBucketAsync("uploads", isPublic: false);
var file = await storage.UploadFromPathAsync(@".\doc.pdf", "uploads", path: "docs/doc.pdf");
var files = await storage.ListFilesAsync("uploads", prefix: "docs/", limit: 100, offset: 0);
var url = storage.GetPublicUrl("uploads", "docs/doc.pdf");
var quota = await storage.GetQuotaAsync();
}
Schema — WOWSQLSchema (service key only)
UUID primary 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_...",
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.
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.