--- title: 'Build an API route in less than 2 minutes.' subtitle: 'Create your first API route by creating a table called `todos` to store tasks.' breadcrumb: 'API Quickstart' hideToc: true --- Let's create our first REST route which we can query using `cURL` or the browser. We'll create a database table called `todos` for storing tasks. This creates a corresponding API route `/rest/v1/todos` which can accept `GET`, `POST`, `PATCH`, & `DELETE` requests. [Create a new project](/dashboard) in the Supabase Dashboard. After your project is ready, create a table in your Supabase database. You can do this with either the Table interface or the [SQL Editor](/dashboard/project/_/sql). ```sql -- Create a table called "todos" -- with a column to store tasks. create table todos ( id serial primary key, task text ); ``` 1. Go to the [**Table editor**](/dashboard/project/_/editor) section 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**. Expose the `todos` table through the Data API so it can be queried over HTTP. For more control over which tables and functions are exposed, see [Expose specific tables and functions](/docs/guides/database/data-api#expose-specific-tables-and-functions-recommended). ```sql -- Allow read-only access for anonymous clients grant select on public.todos to anon; ``` Go to [**Integrations > Data API > Settings**](/dashboard/project/_/integrations/data_api/settings). Under **Exposed schemas**, make sure `public` is included, then under **Exposed tables**, toggle on access for the `todos` table. Turn on Row Level Security for this table and create the policies that control who can read and write rows. ```sql -- Turn on RLS alter table "todos" enable row level security; -- Allow anonymous access create policy "Allow public access" on todos for select to anon using (true); -- Allow authenticated users to read and modify todos create policy "Allow authenticated users to manage todos" on todos for all to authenticated using (true) with check (true); ``` Now that RLS is in place, grant write access to the `authenticated` and `service_role` roles. ```sql -- Grant write access only after RLS and policies are in place grant select, insert, update, delete on public.todos to authenticated; grant select, insert, update, delete on public.todos to service_role; ``` Now we can add some data to our table which we can access through our API. ```sql insert into todos (task) values ('Create tables'), ('Enable security'), ('Add data'), ('Fetch data from the API'); ``` Find your API URL and Keys in your Dashboard [API Settings](/dashboard/project/_/settings/api). You can now query your "todos" table by appending `/rest/v1/todos` to the API URL. Copy this block of code, substitute `` and ``, then run it from a terminal. ```bash Terminal curl 'https://.supabase.co/rest/v1/todos' \ -H "apikey: " ``` ## Bonus There are several options for accessing your data: ### Browser You can query the route in your browser, by appending the `publishable` key as a query parameter: `https://.supabase.co/rest/v1/todos?apikey=` ### Curl ``` curl 'https://.supabase.co/rest/v1/todos?select=*' \ -H "apikey: " \ -H "Authorization: Bearer " ``` ### Client libraries We provide a number of [Client Libraries](https://github.com/supabase/supabase#client-libraries). ```js const { data, error } = await supabase.from('todos').select() ``` <$Show if="sdk:dart"> ```dart final data = await supabase.from('todos').select('*'); ``` <$Show if="sdk:python"> ```python response = supabase.table('todos').select("*").execute() ``` <$Show if="sdk:swift"> ```swift let response = try await supabase.from("todos").select() ```