Skip to main content

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.

  1. Go to the Table editor page in the Dashboard.
  2. Click New Table and create a table with the name todos.
  3. Click Save.
  4. Click New Column and create a column with the name task and type text.
  5. Click Save.

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.

  1. Go to the Settings page in the Dashboard.
  2. Click API in the sidebar.
  3. Find your API URL, anon, and service_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.

  1. Go to the API page in the Dashboard.
  2. Find the countries table under Tables and Views in the sidebar.
  3. 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:

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:

// 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('*')

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.

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

Realtime API

By default Realtime is disabled on your database. Let's turn on Realtime for the todos table.

  1. Go to the Database page in the Dashboard.
  2. Click on Replication in the sidebar.
  3. Control which database events are sent by toggling Insert, Update, and Delete.
  4. Control which tables broadcast changes by selecting Source and toggling each table.

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:

  1. Go to the Authentication page in the Dashboard.
  2. Click on Policies in the sidebar.
  3. Select Enable RLS to 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"]