APIs
Overview
Supabase generates three types of API directly from your database schema.
- REST - interact with your database through a restful interface.
- Realtime - listen to database changes.
- GraphQL - in beta.
The APIs are:
- Instant and auto-generated.
As you update your database the changes are immediately accessible through your API. - Self documenting.
Supabase generates documentation in the Dashboard which updates as you make database changes. - Secure.
The API is configured to work with PostgreSQL's Row Level Security, provisioned behind an API gateway with key-auth enabled. - Fast.
Our benchmarks for basic reads are more than 300% faster than Firebase. The API is a very thin layer on top of Postgres, which does most of the heavy lifting. - Scalable.
The API can serve thousands of simultaneous requests, and works well for Serverless workloads.
REST API
Supabase provides a RESTful API using PostgREST. This is a very thin API layer on top of Postgres. It provides everything you need from a CRUD API:
- Basic CRUD operations
- Deeply nested joins, allowing you to fetch data from multiple tables in a single fetch
- Works with Postgres Views
- Works with Postgres Functions
- Works with the Postgres security model - including Row Level Security, Roles, and Grants.
GraphQL API
note
GraphQL is in Beta, and may have breaking changes. It is only available on self-hosted setups and Supabase projects created after 28th March 2022.
GraphQL in Supabase works through pg_graphql, an open source PostgreSQL extension for GraphQL.
Realtime API
Supabase provides a Realtime API using Realtime. You can use this to listen to database changes over websockets. Realtime leverages PostgreSQL's built-in logical replication. You can manage your Realtime API simply by managing Postgres publications.
Getting started
All APIs are auto-created from Database tables. After you have added tables or functions to your database, you can use the APIs provided.
Creating API Routes
API routes are automatically created when you create Postgres Tables, Views, or Functions.
Let's create our first
API route by creating a table called todos
to store tasks.
This creates a corresponding route todos
which can accept GET
, POST
, PATCH
, & DELETE
requests.
- Dashboard
- SQL
- Go to the Table editor page in the Dashboard.
- Click New Table and create a table with the name
todos
. - Click Save.
- Click New Column and create a column with the name
task
and typetext
. - Click Save.
-- Create a table called "todos" with a column to store tasks.
create table todos (
id bigint generated by default as identity primary key,
task text check (char_length(task) > 3)
);
API URL and Keys
Every Supabase project has a unique API URL. Your API is secured behind an API gateway which requires an API Key for every request.
- Go to the Settings page in the Dashboard.
- Click API in the sidebar.
- Find your API
URL
,anon
, andservice_role
keys on this page.
The REST API and the GraphQL API are both accessible through this URL:
- REST:
https://<project_ref>.supabase.co/rest/v1
- GraphQL:
https://<project_ref>.supabase.co/graphql/v1
Both of these routes require the anon
key to be passed through an apikey
header.
API Keys
You are provided with two keys:
- an
anon
key, which is safe to be used in a browser context. - a
service_role
key, which should only be used on a server. This key can bypass Row Level Security. NEVER use this key in a browser.
Accessing the docs in the Dashboard
REST API
Supabase generates documentation in the Dashboard which updates as you make database changes.
Let's view the documentation for a countries
table which we created in our database.
- Go to the API page in the Dashboard.
- Find the
countries
table under Tables and Views in the sidebar. - Switch between the JavaScript and the cURL docs using the tabs.
GraphQL
The GraphQL Endpoint that we provide (https://<project_ref>.supabase.co/graphql/v1
) is compatible with any GraphiQL implementation that can pass an apikey
header.
Some suggested applications:
- paw.cloud
- insomnia.rest
- postman.com/graphql
- Self-hosted GraphiQL: GraphiQL can be served through a simple HTML file. See this discussion for more details.
Using the API
REST API
You can interact with your API directly via HTTP requests, or you can use the client libraries which we provide.
Let's see how to make a request to the todos
table which we created in the first step,
using the API URL (SUPABASE_URL
) and Key (SUPABASE_ANON_KEY
) we provided:
- JavaScript
- cURL
// Initialize the JS client
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
// Make a request
const { data: todos, error } = await supabase
.from('todos')
.select('*')
# Append /rest/v1/ to your URL, and then use the table name as the route
curl '<SUPABASE_URL>/rest/v1/todos' \
-H "apikey: <SUPABASE_ANON_KEY>" \
-H "Authorization: Bearer <SUPABASE_ANON_KEY>"
JS Reference: select(), insert(), update(), upsert(), delete(), rpc() (call Postgres functions).
GraphQL API
note
To rebuild your GraphQL schema from the SQL schema, call select graphql.rebuild_schema();
.
Be sure to rebuild the GraphQL schema after altering the SQL schema.
You can use any GraphQL client with the Supabase GraphQL API. For our GraphQL example we will use urql.
- JavaScript
- cURL
import { createClient, useQuery } from 'urql'
// Prepare API key and Authorization header
const headers = {
apikey: <SUPABASE_ANON_KEY>,
authorization: `Bearer: ${<SUPABASE_ANON_KEY}`>
}
// Create GraphQL client
// See: https://formidable.com/open-source/urql/docs/basics/react-preact/#setting-up-the-client
const client = createClient({
url: '<SUPABASE_URL>/graphql/v1',
fetchOptions: function createFetchOptions() {
return { headers }
},
})
// Prepare our GraphQL query
const TodosQuery = `
query {
todosCollection {
edges {
node {
id
title
}
}
}
}
`
// Query for the data (React)
const [result, reexecuteQuery] = useQuery({
query: TodosQuery,
})
// Read the result
const { data, fetching, error } = result
# Append /graphql/v1/ to your URL, and then use the table name as the route
curl --request POST '<SUPABASE_URL>/graphql/v1' \
-H 'apikey: <SUPABASE_ANON_KEY>' \
-H 'Authorization: Bearer <SUPABASE_ANON_KEY>' \
-d '{ "query":"{ todos(first: 3) { edges { node { id } } } }" }'
Realtime API
By default Realtime is disabled on your database. Let's turn on Realtime for the todos
table.
- Dashboard
- SQL
- Go to the Database page in the Dashboard.
- Click on Replication in the sidebar.
- Control which database events are sent by toggling Insert, Update, and Delete.
- Control which tables broadcast changes by selecting Source and toggling each table.
alter publication supabase_realtime add table todos;
From the client, we can listen to any new data that is inserted into the todos
table:
// Initialize the JS client
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
// Create a function to handle inserts
const handleInserts = (payload) => {
console.log('Change received!', payload)
}
// Listen to inserts
const { data: todos, error } = await supabase
.from('todos')
.on('INSERT', handleInserts)
.subscribe()
Use subscribe() to listen to database changes.
The Realtime API works through PostgreSQL's replication functionality. Postgres sends database changes to a publication
called supabase_realtime
, and by managing this publication you can control which data is broadcast.
API Security
Securing your Routes
Your API is designed to work with Postgres Row Level Security (RLS). If you use Supabase Auth, you can restrict data based on the logged-in user. To control access to your data, you can use Policies. When you create a table in Postgres, Row Level Security is disabled by default. To enable RLS:
- Dashboard
- SQL
- Go to the Authentication page in the Dashboard.
- Click on Policies in the sidebar.
- Select Enable RLS to enable Row Level Security.
alter table todos enable row level security;
The service_role
key
Never expose the service_role
key in a browser or anywhere where a user can see it. This Key is designed to bypass Row Level Security - so it should only be used on a private server.
We have partnered with GitHub to scan for Supabase service_role
keys pushed to public repositories.
If they detect any keys with service_role privileges being pushed to GitHub, they will forward the API key to us, so that we can automatically revoke the detected secrets and notify you, protecting your data against malicious actors.
Safeguards towards accidental deletes and updates
For all projects, by default, the Postgres extension safeupdate is enabled for all queries coming from the API.
This ensures that any delete()
or update()
would fail if there are no accompanying filters provided.
To confirm that safeupdate is enabled for queries going through the API of your project, the following query could be run:
select usename,useconfig from pg_shadow where usename = 'authenticator' ;
The expected value for useconfig
should be:
["session_preload_libraries=supautils, safeupdate"]