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('posts').select('*');
About RLS and Neon RLS
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.
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. We recommend using the Data API for client-side querying as it provides a more secure and controlled way to access your data through predefined REST endpoints.
Enable the Data API
Enable the Data API at the branch level for a single database.
To get started, open the Data API page from the project sidebar and click Enable.
Enabling the Data API on your branch gives you:
- A REST API endpoint for your branch (your base URL for API requests) with a copy-to-clipboard control
- Neon Auth as your default authentication provider (if you accept the default)
- Two Postgres roles:
authenticated
– used when a request includes a valid JWTanonymous
– will be used for unauthenticated requests (coming soon)
You can change the provider to Other provider if you want to manage your own JWTs, or skip authentication setup and add it later. But if you accept the default, Neon Auth is ready to use immediately. If you select Other provider, you'll need to provide your provider's JWKS (JSON Web Key Set) URL to validate JWT tokens.
Always secure your data before using the Data API in production.
Secure your Data API
To secure your Data API you must configure both of the following:
- GRANT statements that define which operations (
SELECT
,INSERT
,UPDATE
,DELETE
) each role can attempt - Row-Level Security (RLS) policies that control which specific rows each role can see or modify
GRANT permissions
-- For existing tables GRANT SELECT, UPDATE, INSERT, DELETE ON ALL TABLES IN SCHEMA public TO authenticated; -- For future tables ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, UPDATE, INSERT, DELETE ON TABLES TO authenticated; -- For sequences (for identity columns) GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO authenticated; -- Schema usage GRANT USAGE ON SCHEMA public TO authenticated;
Authentication required
All requests to the Data API currently require authentication with a valid JWT token. Anonymous access is not supported yet, but is coming soon. In the near future, we'll provide public/long-lived tokens for anonymous users.
Create a table with RLS
Here's a sample
posts
table secured with RLS. The GRANT statements above give authenticated users access to all tables, which allows the Data API to work. RLS policies then control which specific rows each user can see and modify.For guidance on writing RLS policies, see our PostgreSQL RLS tutorial for the basics, or our recommended Drizzle RLS guide for a simpler approach.
CREATE TABLE "posts" ( "id" bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, "userId" text DEFAULT (auth.user_id()) NOT NULL, "content" text NOT NULL, "published" boolean DEFAULT false NOT NULL ); -- Enable RLS and create policies ALTER TABLE "posts" ENABLE ROW LEVEL SECURITY; -- When RLS is enabled, all operations are denied by default unless explicitly allowed by policies. CREATE POLICY "Allow authenticated users to read any post" ON "posts" AS PERMISSIVE FOR SELECT TO "authenticated" USING (true); CREATE POLICY "Allow authenticated users to insert their own posts" ON "posts" AS PERMISSIVE FOR INSERT TO "authenticated" WITH CHECK ((select auth.user_id() = "userId")); CREATE POLICY "Allow authenticated users to update their own posts" ON "posts" AS PERMISSIVE FOR UPDATE TO "authenticated" USING ((select auth.user_id() = "userId")) WITH CHECK ((select auth.user_id() = "userId")); CREATE POLICY "Allow authenticated users to delete their own posts" ON "posts" AS PERMISSIVE FOR DELETE TO "authenticated" USING ((select auth.user_id() = "userId"));
The
auth.user_id()
function is provided by the Data API and extracts the user ID from JWT tokens, making it available to your RLS policies for enforcing per-user access control.With the
posts
table and its RLS policies in place, you can now securely query and modify posts using the Data API.- GRANT statements that define which operations (
Query from your app
The Neon Auth SDK (Stack Auth) manages JWT tokens automatically. Here's an example showing how to use it with
postgrest-js
:import { PostgrestClient } from '@supabase/postgrest-js'; import { useUser } from '@stackframe/stack'; // Example: fetch notes for the current user async function fetchUserNotes() { const user = useUser(); if (!user) return null; const { accessToken } = await user.getAuthJson(); const pg = new PostgrestClient(import.meta.env.VITE_DATA_API_URL, { headers: { Authorization: `Bearer ${accessToken}` }, }); const { data, error } = await pg .from('notes') .select('id, title, created_at, owner_id, shared') .eq('owner_id', user.id) .order('created_at', { ascending: false }); return { data, error }; }
This example shows the key steps:
- Get the current user with
useUser()
- Extract their JWT token with
user.getAuthJson()
- Create a PostgrestClient with proper authentication headers
- Query the Data API with filtering (
.eq('owner_id', user.id)
) and ordering (.order('created_at', { ascending: false })
)
To see a complete, working example of an application built with the Data API, Neon Auth, and Postgres RLS, check out our demo note-taking app:
- Full tutorial - Step-by-step guide to building the app
- GitHub Repository
- Live Demo
- Get the current user with