Like many others, Databuddy took advantage of Neon's Free Plan - and started building an open-source, privacy-first analytics platform for devs
/Data API

Getting started with Neon Data API

beta

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.

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.

  1. Enabling 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.

    Data API page with enable button

    By default, we install Neon Auth as your Authentication provider. We recommend using Neon Auth for a seamless experience, but you can also select Other provider if you manage your own JWTs, or skip this step to configure authentication later.

    Once enabled, you'll see your REST API Endpoint — this is your base URL for API requests, with a copy-to-clipboard control.

    Data API enabled view with REST API Endpoint

    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'
  2. Authentication

    Once enabled, the Working with the Data API section shows your current security status and next steps. If you skipped the auth provider selection, you'll also see an option to add an authentication provider.

    configuration section of Data API

    The security model consists of two parts:

    Neon Auth (default)

    Neon Auth manages user authentication, generating JWT tokens for secure API requests. If you accepted the default during setup, Neon Auth is already configured and you'll see the JWKS URL in the Authentication providers section.

    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.

  3. 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.

  4. Try the demo app

    To see a complete, working example of an application built with the Data API, Neon Auth, and RLS, check out our demo note-taking app.

What's Next?

  • Faster cold starts (we're working on it)

Last updated on

Was this page helpful?