Complete reference for the BetterBase REST API.
http://localhost:3000/api
POST /auth/signup
Content-Type: application/json
{
"email": "user@example.com",
"password": "secure-password",
"name": "John Doe"
}Response:
{
"user": {
"id": "user-123",
"email": "user@example.com",
"name": "John Doe"
},
"session": {
"token": "...",
"expiresAt": "2024-01-15T10:30:00Z"
}
}POST /auth/signin
Content-Type: application/json
{
"email": "user@example.com",
"password": "secure-password"
}POST /auth/signout
Authorization: Bearer <token>GET /auth/session
Authorization: Bearer <token>POST /auth/refresh
Authorization: Bearer <token>BetterBase automatically generates CRUD endpoints for each table.
GET /:table
GET /users
GET /posts?limit=10&offset=0&sort=createdAt.descQuery Parameters:
| Parameter | Type | Description |
|---|---|---|
limit |
number | Number of records (default: 20, max: 1000) |
offset |
number | Offset for pagination |
sort |
string | Sort field and direction (e.g., createdAt.desc) |
filter |
string | Filter expression |
Filter Syntax:
GET /users?filter=active.eq.true
GET /posts?filter=published.eq.true&userId.eq.user-123
GET /users?filter=role.in.admin,moderator
GET /:table/:id
GET /users/user-123POST /:table
POST /users
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com"
}Response:
{
"id": "user-123",
"name": "John Doe",
"email": "john@example.com",
"createdAt": "2024-01-15T10:30:00Z"
}PATCH /:table/:id
PATCH /users/user-123
Content-Type: application/json
{
"name": "Jane Doe"
}DELETE /:table/:id
DELETE /users/user-123POST /storage/:bucket
Content-Type: multipart/form-data
--boundary
Content-Disposition: form-data; name="file"; filename="image.jpg"
<file content>
--boundaryGET /storage/:bucket/:pathGET /storage/:bucketDELETE /storage/:bucket/:pathFor realtime subscriptions:
const ws = new WebSocket('ws://localhost:3000/realtime/v1')
// Authenticate
ws.send(JSON.stringify({
type: 'auth',
payload: { token: '...' }
}))
// Subscribe
ws.send(JSON.stringify({
type: 'subscribe',
payload: {
event: 'postgres_changes',
table: 'posts',
filter: '*'
}
}))All errors follow this format:
{
"error": {
"code": "PGRST116",
"message": "The requested resource was not found",
"details": "...",
"hint": "..."
}
}| Code | HTTP Status | Description |
|---|---|---|
PGRST116 |
404 | Resource not found |
23505 |
409 | Unique constraint violation |
42501 |
403 | Permission denied |
AUTH_REQUIRED |
401 | Authentication required |
INVALID_TOKEN |
401 | Invalid or expired token |
API requests are rate limited:
- Authenticated: 1000 requests/minute
- Unauthenticated: 100 requests/minute
Rate limit headers are included in responses:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1705315800
Cross-origin requests are supported via CORS headers:
Access-Control-Allow-Origin: https://your-domain.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
| Operator | Example | Description |
|---|---|---|
eq |
id.eq.user-123 |
Equals |
neq |
id.neq.user-123 |
Not equals |
gt |
age.gt.18 |
Greater than |
gte |
age.gte.18 |
Greater or equal |
lt |
age.lt.18 |
Less than |
lte |
age.lte.18 |
Less or equal |
like |
name.like.%John% |
Pattern match |
ilike |
name.ilike.%john% |
Case-insensitive |
in |
role.in.admin,user |
In array |
is |
deleted.is.null |
Is null |
?sort=createdAt.desc
?sort=title.asc,createdAt.desc
?page=1&limit=20
Response includes pagination metadata:
{
"data": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 100,
"pages": 5
}
}- Client SDK - Using REST API from client
- Database - Database operations
- GraphQL API - GraphQL reference