Skip to main content

Introduction

Supabase provides a RESTful API that is automatically generated from your PostgreSQL database schema. The API is powered by PostgREST, which provides instant RESTful APIs for your database.

Base URL

Your API is available at:
https://<PROJECT_REF>.supabase.co/rest/v1/
Replace <PROJECT_REF> with your project reference ID found in your project settings.

Auto-Generated API

Every time you create or modify a table, view, or function in your database, the REST API is automatically updated to reflect those changes. No additional configuration is required.

Example

If you create a table named countries with the following schema:
CREATE TABLE countries (
  id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
  name TEXT NOT NULL,
  code TEXT NOT NULL,
  capital TEXT
);
The following endpoints are automatically available:
  • GET /rest/v1/countries - List all countries
  • POST /rest/v1/countries - Create a new country
  • PATCH /rest/v1/countries?id=eq.1 - Update a country
  • DELETE /rest/v1/countries?id=eq.1 - Delete a country

API Documentation

You can view the auto-generated API documentation for your project at:
https://<PROJECT_REF>.supabase.co/rest/v1/
This provides an interactive OpenAPI/Swagger documentation interface.

Common Headers

All API requests require specific headers:
apikey
string
required
Your Supabase API key (anon key for client requests, service role key for server requests).
Authorization
string
Bearer token for authenticated requests: Bearer <JWT_TOKEN>
Content-Type
string
Set to application/json for POST/PATCH requests.
Prefer
string
Control the response format:
  • return=representation - Return the full object after insert/update
  • return=minimal - Return no content (204 response)
  • return=headers-only - Return only headers

Example Request

curl 'https://<PROJECT_REF>.supabase.co/rest/v1/countries' \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response Format

Success Responses

Successful responses return JSON data:
[
  {
    "id": 1,
    "name": "United States",
    "code": "US",
    "capital": "Washington, D.C."
  },
  {
    "id": 2,
    "name": "Canada",
    "code": "CA",
    "capital": "Ottawa"
  }
]

Error Responses

Error responses include a message and details:
{
  "code": "PGRST116",
  "details": null,
  "hint": null,
  "message": "JWT expired"
}
code
string
PostgREST error code.
message
string
Human-readable error message.
details
string | null
Additional error details if available.
hint
string | null
Suggested fix for the error.

HTTP Status Codes

Status CodeDescription
200Successful GET request
201Successful POST request (created)
204Successful DELETE or update with no content
400Bad request (invalid parameters)
401Unauthorized (missing or invalid API key)
403Forbidden (insufficient permissions)
404Not found (table or resource doesn’t exist)
406Not acceptable (invalid Accept header)
409Conflict (unique constraint violation)
416Range not satisfiable (invalid pagination)
500Internal server error

Filtering and Querying

The REST API supports powerful filtering using query parameters:

Basic Filters

# Equal to
GET /countries?name=eq.Albania

# Not equal to
GET /countries?name=neq.Albania

# Greater than
GET /countries?population=gt.1000000

# Less than
GET /countries?population=lt.1000000

# Like (case-sensitive)
GET /countries?name=like.*Alba*

# ilike (case-insensitive)
GET /countries?name=ilike.*alba*

# In list
GET /countries?name=in.(Albania,Algeria)

# Is null
GET /countries?capital=is.null

Combining Filters

Multiple filters are combined with AND logic:
GET /countries?name=like.*A*&population=gt.1000000

Ordering

# Ascending order
GET /countries?order=name.asc

# Descending order
GET /countries?order=population.desc

# Multiple columns
GET /countries?order=name.asc,population.desc

Pagination

# Limit results
GET /countries?limit=10

# Offset results
GET /countries?limit=10&offset=20

# Range (preferred method)
GET /countries
Range: 0-9

Selecting Columns

# Select specific columns
GET /countries?select=name,capital

# Select all columns
GET /countries?select=*

# Select with relationships
GET /countries?select=name,cities(name,population)

Vertical Filtering (Relationships)

Query related data using foreign keys:
# Get countries with their cities
GET /countries?select=name,cities(*)

# Filter nested resources
GET /countries?select=name,cities(name,population)&cities.population=gt.1000000

Stored Procedures

Call PostgreSQL functions via the API:
POST /rpc/function_name
Content-Type: application/json

{
  "param1": "value1",
  "param2": "value2"
}

Performance Tips

Only request the columns you need to reduce payload size:
GET /countries?select=id,name
Create database indexes on columns you frequently filter by:
CREATE INDEX idx_countries_name ON countries(name);
Always use pagination for large datasets:
GET /countries?limit=100&offset=0
Only request total counts when necessary as it can be expensive:
GET /countries?select=*&limit=10
Prefer: count=exact

Rate Limits

API rate limits vary by plan:
  • Free tier: Unlimited requests (with CPU limits)
  • Pro tier: Unlimited requests (higher CPU limits)
  • Enterprise: Custom limits
See Rate Limits for more information.

Next Steps

Authentication

Learn how to authenticate API requests

Database Operations

Explore CRUD operations

Storage API

Work with file storage

Edge Functions

Call serverless functions