---
id: api
title: APIs
description: Auto-generating and Realtime APIs.
sidebar_label: Overview
---

import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import useBaseUrl from '@docusaurus/useBaseUrl'

## 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](https://supabase.com/blog/pg-graphql).

The APIs are:

- **Instant and auto-generated.** <br />As you update your database the changes are immediately accessible through your API.
- **Self documenting.** <br />Supabase generates documentation in the Dashboard which updates as you make database changes.
- **Secure.** <br />The API is configured to work with PostgreSQL's Row Level Security, provisioned behind an API gateway with key-auth enabled.
- **Fast.** <br />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.** <br />The API can serve thousands of simultaneous requests, and works well for Serverless workloads.

### REST API {#rest-api-overview}

Supabase provides a RESTful API using [PostgREST](https://postgrest.org/). 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.

<div class="video-container">
  <iframe
    src="https://www.youtube-nocookie.com/embed/rPAJJFdtPw0"
    frameBorder="1"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
    allowFullScreen
  ></iframe>
</div>

### GraphQL API {#graphql-api-overview}

:::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](https://supabase.com/blog/pg-graphql), an open source PostgreSQL extension for GraphQL.

### Realtime API {#realtime-api-overview}

Supabase provides a Realtime API using [Realtime](https://github.com/supabase/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.

<Tabs
  groupId="dashboard-or-sql"
  defaultValue="dashboard"
  values={[
    {label: 'Dashboard', value: 'dashboard'},
    {label: 'SQL', value: 'sql'},
  ]}>

<TabItem value="dashboard">

1. Go to the [Table editor](https://app.supabase.com/project/_/editor) page in the Dashboard.
1. Click **New Table** and create a table with the name `todos`.
1. Click **Save**.
1. Click **New Column** and create a column with the name `task` and type `text`.
1. Click **Save**.

<video width="99%" muted playsInline controls="true">
  <source
    src={useBaseUrl('/videos/api/api-create-table-sm.mp4')}
    type="video/mp4"
    muted
    playsInline
  />
</video>

</TabItem>
<TabItem value="sql">

```sql
-- 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)
);
```

</TabItem>
</Tabs>

### 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](https://app.supabase.com/project/_/settings/general) page in the Dashboard.
2. Click **API** in the sidebar.
3. Find your API `URL`, `anon`, and `service_role` keys on this page.

<video width="99%" muted playsInline controls="true">
  <source
    src={useBaseUrl('/videos/api/api-url-and-key.mp4')}
    type="video/mp4"
    muted
    playsInline
  />
</video>

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 {#rest-api-dashboard-docs}

Supabase generates documentation in the [Dashboard](https://app.supabase.com) 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](https://app.supabase.com/project/_/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.

<video width="99%" muted playsInline controls="true">
  <source
    src={useBaseUrl('/videos/api/api-docs.mp4')}
    type="video/mp4"
    muted
    playsInline
  />
</video>

#### 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](https://paw.cloud)
- [insomnia.rest](https://insomnia.rest)
- [postman.com/graphql](https://www.postman.com/graphql/)
- Self-hosted GraphiQL: GraphiQL can be served through a simple HTML file. See [this discussion](https://github.com/supabase/supabase/discussions/6144) 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:

<Tabs
  groupId="language"
  defaultValue="javascript"
  values={[
    {label: 'JavaScript', value: 'javascript'},
    {label: 'cURL', value: 'curl'},
  ]}>

<TabItem value="javascript">

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

</TabItem>
<TabItem value="curl">

```bash
# 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>"
```

</TabItem>
</Tabs>

JS Reference: [select()](../reference/javascript/select),
[insert()](../reference/javascript/insert),
[update()](../reference/javascript/update),
[upsert()](../reference/javascript/upsert),
[delete()](../reference/javascript/delete),
[rpc()](../reference/javascript/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](https://formidable.com/open-source/urql/docs/).

<Tabs
  groupId="language"
  defaultValue="javascript"
  values={[
    {label: 'JavaScript', value: 'javascript'},
    {label: 'cURL', value: 'curl'},
  ]}>

<TabItem value="javascript">

```javascript
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
```

</TabItem>
<TabItem value="curl">

```bash
# 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 } } } }" }'
```

</TabItem>
</Tabs>

### Realtime API

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

<Tabs
  groupId="dashboard-or-sql"
  defaultValue="dashboard"
  values={[
    {label: 'Dashboard', value: 'dashboard'},
    {label: 'SQL', value: 'sql'},
  ]}>

<TabItem value="dashboard">

1. Go to the [Database](https://app.supabase.com/project/_/database/tables) 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.

<video width="99%" muted playsInline controls="true">
  <source
    src={useBaseUrl('/videos/api/api-realtime.mp4')}
    type="video/mp4"
    muted
    playsInline
  />
</video>

</TabItem>
<TabItem value="sql">

```sql
alter publication supabase_realtime add table todos;
```

</TabItem>
</Tabs>

From the client, we can listen to any new data that is inserted into the `todos` table:

```javascript
// 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()](/docs/reference/javascript/subscribe) to listen to database changes.
The Realtime API works through PostgreSQL's replication functionality. Postgres sends database changes to a [publication](/docs/guides/database/replication#publications)
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](/guides/auth), you can restrict data based on the logged-in user.
To control access to your data, you can use [Policies](/guides/auth#policies).
When you create a table in Postgres, Row Level Security is disabled by default. To enable RLS:

<Tabs
  groupId="dashboard-or-sql"
  defaultValue="dashboard"
  values={[
    {label: 'Dashboard', value: 'dashboard'},
    {label: 'SQL', value: 'sql'},
  ]}>

<TabItem value="dashboard">

1. Go to the [Authentication](https://app.supabase.com/project/_/auth/users) page in the Dashboard.
2. Click on **Policies** in the sidebar.
3. Select **Enable RLS** to enable Row Level Security.

</TabItem>
<TabItem value="sql">

```sql
alter table todos enable row level security;
```

</TabItem>
</Tabs>

### 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](https://github.blog/changelog/2022-03-28-supabase-is-now-a-github-secret-scanning-partner/) 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](https://github.com/eradman/pg-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:

```sql
select usename,useconfig from pg_shadow where usename = 'authenticator' ;
```

The expected value for `useconfig` should be:

```
["session_preload_libraries=supautils, safeupdate"]
```
