Auto-Generated APIs
How Supabase creates instant REST and GraphQL endpoints from your tables
Last updated: 8/15/2025
The moment you create a table in Supabase, it becomes a fully functional REST API. No backend code required.
Instant API Creation
Create a table called products:
CREATE TABLE products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
price DECIMAL(10,2),
category TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
You immediately get these endpoints:
GET /rest/v1/products(List all products)POST /rest/v1/products(Create a new product)PATCH /rest/v1/products?id=eq.{id}(Update a product)DELETE /rest/v1/products?id=eq.{id}(Delete a product)
Basic REST Operations
Reading Data
# Get all products
curl "https://your-project.supabase.co/rest/v1/products" \
-H "apikey: your-anon-key"
# Get specific columns
curl "https://your-project.supabase.co/rest/v1/products?select=name,price" \
-H "apikey: your-anon-key"
# Get one product by ID
curl "https://your-project.supabase.co/rest/v1/products?id=eq.123&select=*" \
-H "apikey: your-anon-key"
Filtering with Query Parameters
Supabase uses PostgREST operators for filtering:
# Equal to
?name=eq.iPhone
# Not equal
?price=neq.0
# Greater than
?price=gt.100
# Less than or equal
?price=lte.500
# Pattern matching
?name=like.*Phone*
?email=ilike.*@gmail.com
# In a list
?category=in.(electronics,books)
# Date ranges
?created_at=gte.2025-01-01&created_at=lt.2025-02-01
Real-World Examples
# Products under $100 in electronics category
curl "https://your-project.supabase.co/rest/v1/products?category=eq.electronics&price=lt.100&select=name,price" \
-H "apikey: your-anon-key"
# Recent orders with customer info
curl "https://your-project.supabase.co/rest/v1/orders?created_at=gte.2025-01-01&select=id,total,created_at,customers(name,email)" \
-H "apikey: your-anon-key"
Sorting and Pagination
# Sort by price (ascending)
?order=price.asc
# Sort by multiple columns
?order=category.asc,price.desc
# Limit results
?limit=10
# Pagination (skip first 20, get next 10)
?limit=10&offset=20
# Range-based pagination
Range: 20-29
Nested Relationships
Query related data in a single request:
# Get customers with their orders
curl "https://your-project.supabase.co/rest/v1/customers?select=name,email,orders(id,total,created_at)" \
-H "apikey: your-anon-key"
# Get orders with customer and order items
curl "https://your-project.supabase.co/rest/v1/orders?select=id,total,customers(name),order_items(quantity,products(name,price))" \
-H "apikey: your-anon-key"
Writing Data
Creating Records
# Create a new product
curl -X POST "https://your-project.supabase.co/rest/v1/products" \
-H "apikey: your-service-role-key" \
-H "Content-Type: application/json" \
-d '{
"name": "New Product",
"price": 29.99,
"category": "electronics"
}'
Updating Records
# Update product price
curl -X PATCH "https://your-project.supabase.co/rest/v1/products?id=eq.123" \
-H "apikey: your-service-role-key" \
-H "Content-Type: application/json" \
-d '{"price": 19.99}'
Deleting Records
# Delete a product
curl -X DELETE "https://your-project.supabase.co/rest/v1/products?id=eq.123" \
-H "apikey: your-service-role-key"
Using from JavaScript
Basic Queries
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
'https://your-project.supabase.co',
'your-anon-key'
);
// Get all products
const { data: products } = await supabase
.from('products')
.select('*');
// Filter and sort
const { data: expensiveProducts } = await supabase
.from('products')
.select('name, price')
.gt('price', 100)
.order('price', { ascending: false })
.limit(10);
Relationships
// Get customers with their recent orders
const { data: customers } = await supabase
.from('customers')
.select(`
name,
email,
orders (
id,
total,
created_at
)
`)
.order('created_at', {
foreignTable: 'orders',
ascending: false
});
Insert and Update
// Create new product
const { data: newProduct, error } = await supabase
.from('products')
.insert({
name: 'New Product',
price: 29.99,
category: 'electronics'
})
.select();
// Update existing product
const { data: updatedProduct, error } = await supabase
.from('products')
.update({ price: 19.99 })
.eq('id', productId)
.select();
// Delete product
const { error } = await supabase
.from('products')
.delete()
.eq('id', productId);
Database Functions as API Endpoints
Create custom logic as PostgreSQL functions:
-- Create a function to get sales summary
CREATE OR REPLACE FUNCTION get_sales_summary(start_date DATE, end_date DATE)
RETURNS TABLE(
total_orders INTEGER,
total_revenue DECIMAL,
average_order DECIMAL
) AS $$
BEGIN
RETURN QUERY
SELECT
COUNT(*)::INTEGER,
SUM(total),
AVG(total)
FROM orders
WHERE created_at BETWEEN start_date AND end_date;
END;
$$ LANGUAGE plpgsql;
Call it as an API:
// Call the function
const { data: summary } = await supabase
.rpc('get_sales_summary', {
start_date: '2025-01-01',
end_date: '2025-01-31'
});
GraphQL Alternative
Enable GraphQL in your project settings for more flexible queries:
query GetCustomersWithOrders {
customersCollection {
edges {
node {
id
name
email
ordersCollection {
edges {
node {
id
total
created_at
}
}
}
}
}
}
}
API Performance Tips
Use select to limit columns:
// Good: only get what you need
.select('id, name, price')
// Avoid: unnecessary data transfer
.select('*')
Use count for pagination:
const { count } = await supabase
.from('products')
.select('*', { count: 'exact' })
.range(0, 9);
Index frequently filtered columns:
-- Speed up category filters
CREATE INDEX idx_products_category ON products(category);
-- Speed up price range queries
CREATE INDEX idx_products_price ON products(price);
Error Handling
const { data, error } = await supabase
.from('products')
.select('*')
.eq('id', productId);
if (error) {
console.error('Database error:', error.message);
return;
}
// Use the data
console.log('Product:', data);
Auto-generated APIs turn your database into a backend service instantly. Focus on your data model and let Supabase handle the API layer.
Related Topics
Continue building your Supabase knowledge:
- Row Level Security (RLS) Fundamentals - Database-level security
- Supabase Client Patterns - Common usage patterns
- Multi-tenant Security Patterns - Team and organisation data isolation
- API Keys and Environment Setup - Safe handling of credentials