Beta
Neon Data API is in beta and ready to use. We're actively improving it based on feedback from developers like you. Share your experience in our Discord or via the Neon Console.
Related docs
The Neon Data API, powered by PostgREST, offers a ready-to-use REST API for your Neon database. You can interact with any table, view, or function using standard HTTP verbs (GET
, POST
, PATCH
, DELETE
). To simplify querying, use client libraries like postgrest-js
, postgrest-py
, or postgrest-go
:
const { data } = await client.from('playing_with_neon').select('*').gte('value', 0.5);
When using the Data API, it is essential to set up RLS policies so that you can safely expose your databases to clients such as web apps. Make sure that all of your tables have RLS policies, and that you have carefully reviewed each policy.
A note on Neon RLS
You might notice another feature in Neon called Neon RLS. Please be aware that it's a different method for client-side querying and is not compatible with the Data API.
Enabling the Data API
Enable the Data API at the branch level for a single database.
To get started, navigate to the Data API tab in the Neon Console for your branch and click Enable.
Once enabled, you'll see your Data API Project URL here — this is your endpoint for API requests.
Always secure your data before using the Data API in production.
About activation times and schema changes
-
After enabling the Data API, it may take a minute for your endpoints to become available. Be aware of that.
-
If you change your database schema, you'll need to tell the Data API to refresh its cache. You can do this by reloading the schema from the SQL Editor:
NOTIFY pgrst, 'reload schema'
-
Authentication
Once enabled, the Working with the Data API section shows your current security status.
The security model consists of two parts:
Neon Auth (automatically configured)
Neon Auth manages user authentication, generating JWT tokens for secure API requests.
What you need to do:
- Add Neon Auth keys to your app's environment variables. See Get your Neon Auth keys.
- Include JWT tokens in Data API requests.
- Recommended: Use the Neon Auth SDK for user sign-in/sign-up. See Neon Auth SDKs. There are SDKs for Next.js and React.
You can start using the Data API immediately without authentication, but make sure you set up auth and RLS before going to production.
Row-Level Security (RLS)
RLS controls row access in tables. Neon does not auto-enable RLS; enable it manually per table.
-- Enable RLS on your table ALTER TABLE your_table ENABLE ROW LEVEL SECURITY; -- Create a policy (example: users can only access their own data) CREATE POLICY "user_can_access_own_data" ON your_table FOR ALL USING (auth.user_id() = user_id);
We recommend using Drizzle ORM to help simplify writing RLS policies for the Data API.
About auth.user_id()
The
auth.user_id()
function extracts the user's ID from the JSON Web Token (JWT) issued by Neon Auth. The Data API validates this token, making the user's ID available to your RLS policies for enforcing per-user access.For guidance on writing RLS policies, see our PostgreSQL RLS tutorial for the basics, or our recommended Drizzle RLS guide for a simpler approach.
Using the Data API
By default, all tables in your database are accessible via the API with
SELECT
permissions granted to unauthenticated requests. This lets you directly interact with the API without requiring additional authorization headers.Warning: This means your data is publicly accessible until you enable Row-Level Security (RLS). Again, enable RLS on all your tables before using the Data API in production.
Example of creating a table and querying it via the Data API
First, create a table and enable RLS (as shown in Secure your tables with RLS above):
CREATE TABLE IF NOT EXISTS playing_with_neon( id SERIAL PRIMARY KEY, name TEXT NOT NULL, value REAL ); -- Enable RLS and create policy (see section 3 for details) ALTER TABLE playing_with_neon ENABLE ROW LEVEL SECURITY; CREATE POLICY "user_can_access_own_data" ON playing_with_neon FOR ALL USING (auth.user_id() = user_id); INSERT INTO playing_with_neon(name, value) SELECT LEFT(md5(i::TEXT), 10), random() FROM generate_series(1, 10) s(i); SELECT * FROM playing_with_neon;
Querying with Curl
-
Without JWT (unauthenticated request):
curl --location --request GET 'https://app-restless-salad-23184734.dpl.myneon.app/playing_with_neon' --header 'Accept: application/json'
Response:
[]
No data returned because RLS denies access without authentication.
-
With JWT (authenticated request):
curl --location --request GET 'https://app-restless-salad-23184734.dpl.myneon.app/playing_with_neon' --header 'Accept: application/json' --header 'Authorization: Bearer <jwt>'
Response:
HTTP/1.1 200 OK Content-Type: application/json [ { "id": 1, "name": "c4ca4238a0", "value": 0.36675808 }, ... (shortened) { "id": 10, "name": "6512bd43d9", "value": 0.72407603 } ]
You get expected data since the token is included in the request.
As the Data API is built on PostgREST, it follows PostgREST query and data manipulation formats. You can use also wrapper libraries like postgrest-js for a more ORM-like interface.
import { PostgrestClient } from '@supabase/postgrest-js'; // https://github.com/supabase/postgrest-js/blob/master/src/PostgrestClient.ts#L41 const client = new PostgrestClient('https://app-restless-salad-23184734.dpl.myneon.app', { Authorization: 'Bearer <jwt>', }); const { data } = await client.from('playing_with_neon').select('*').gte('value', 0.5); console.table(data);
For a complete example of how to configure the Bearer token with Neon Auth, see the postgrest.ts file from our demo app.
-
What's Next?
- Faster cold starts (we're working on it)