--- id: 'using-custom-schemas' title: 'Using Custom Schemas' description: 'You need additional steps to use custom database schemas with data APIs.' --- By default, your database has a `public` schema which is automatically exposed on data APIs. ## Creating custom schemas You can create your own custom schema/s by running the following SQL, substituting `myschema` with the name you want to use for your schema: ```sql CREATE SCHEMA myschema; ``` ## Exposing custom schemas You can expose custom database schemas - to do so you need to follow these steps: 1. Go to [API settings](/dashboard/project/_/settings/api) and add your custom schema to "Exposed schemas". 2. Run the following SQL, substituting `myschema` with your schema name: ```sql GRANT USAGE ON SCHEMA myschema TO anon, authenticated, service_role; GRANT ALL ON ALL TABLES IN SCHEMA myschema TO anon, authenticated, service_role; GRANT ALL ON ALL ROUTINES IN SCHEMA myschema TO anon, authenticated, service_role; GRANT ALL ON ALL SEQUENCES IN SCHEMA myschema TO anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA myschema GRANT ALL ON TABLES TO anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA myschema GRANT ALL ON ROUTINES TO anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA myschema GRANT ALL ON SEQUENCES TO anon, authenticated, service_role; ``` Now you can access these schemas from data APIs: ```js // Initialize the JS client import { createClient } from '@supabase/supabase-js' const supabase = createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, { db: { schema: 'myschema' }, }) // Make a request const { data: todos, error } = await supabase.from('todos').select('*') // You can also change the target schema on a per-query basis const { data: todos, error } = await supabase.schema('myschema').from('todos').select('*') ``` With generated `Database` types that include `public`, `createClient(...)` type-checks `db.schema` against `public` only, unless the schema name is also passed as the second generic: `createClient(...)`. `supabase.schema('myschema').from(...)` infers its schema per call and needs no second generic. In both cases `myschema` has to be present in the generated `Database` type. <$Show if="sdk:dart"> ```dart // Initialize the Flutter client await Supabase.initialize( url: supabaseUrl, publishableKey: publishableKey, postgrestOptions: const PostgrestClientOptions(schema: 'myschema'), ); final supabase = Supabase.instance.client; // Make a request final data = await supabase.from('todos').select(); // You can also change the target schema on a per-query basis final data = await supabase.schema('myschema').from('todos').select(); ```` <$Show if="sdk:csharp"> ```c# // Initialize the client with a custom schema var supabase = new Supabase.Client( SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, new SupabaseOptions { Schema = "myschema" } ); await supabase.InitializeAsync(); // Make a request var todos = await supabase.From().Get(); ``` ```bash # Append /rest/v1/ to your URL, and then use the table name as the route. # for GET or HEAD request use Accept-Profile curl '/rest/v1/todos' \ -H "apikey: " \ -H "Authorization: Bearer " \ -H "Accept-Profile: myschema" # for POST, PATCH, PUT and DELETE Request use Content-Profile curl -X POST '/rest/v1/todos' \ -H "apikey: " \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -H "Content-Profile: myschema" \ -d '{"column_name": "value"}' ````