--- title: JavaScript SDK (Auth & Data API) subtitle: Reference documentation for building applications with Neon Auth and Data API enableTableOfContents: true layout: wide updatedOn: '2025-12-11T19:49:37.742Z' --- The Neon JavaScript SDK (`@neondatabase/neon-js`) provides authentication and database operations for your applications. Authentication is provided through an adapter-based architecture, letting you work more easily with your existing code or preferred framework. Available adapters: - **BetterAuthVanillaAdapter** (default) — Promise-based authentication methods like `client.auth.signIn.email()`. Used in all examples on this page. - **BetterAuthReactAdapter** — Similar API but with React hooks like `useSession()`. See the [React quickstart](/docs/auth/quick-start/react). - **SupabaseAuthAdapter** — Supabase-compatible API for easy migration. See the [migration guide](/docs/auth/migrate/from-supabase). Database query methods (`client.from()`, `.select()`, etc.) work the same regardless of which adapter you use. Install the JavaScript SDK in your project using npm, yarn, pnpm, or bun. ```bash npm install @neondatabase/neon-js ``` **Full client (`createClient`)** Use this when you need both authentication and database queries. You get: - Auth methods like `client.auth.signIn.email()` and `client.auth.signUp.email()`. - Database queries like `client.from('todos').select()` and `client.from('users').insert()`. **Auth-only client (`createAuthClient`)** Use this when you only need authentication (no database queries). You get: - Auth methods like `auth.signIn.email()` and `auth.signUp.email()` - No database query methods The auth methods are identical—only the access path differs. `client.auth.signIn.email()` and `auth.signIn.email()` do the same thing. ```typescript import { createClient } from '@neondatabase/neon-js'; const client = createClient({ auth: { url: import.meta.env.VITE_NEON_AUTH_URL, }, dataApi: { url: import.meta.env.VITE_NEON_DATA_API_URL, }, }); ``` ```typescript import { createAuthClient } from '@neondatabase/neon-js'; const auth = createAuthClient(import.meta.env.VITE_NEON_AUTH_URL); ``` ```typescript import { createClient } from '@neondatabase/neon-js'; import type { Database } from './types/database.types'; const client = createClient({ auth: { url: import.meta.env.VITE_NEON_AUTH_URL, }, dataApi: { url: import.meta.env.VITE_NEON_DATA_API_URL, }, }); ``` ```typescript import { createClient, BetterAuthReactAdapter } from '@neondatabase/neon-js'; const client = createClient({ auth: { adapter: BetterAuthReactAdapter(), url: import.meta.env.VITE_NEON_AUTH_URL, }, dataApi: { url: import.meta.env.VITE_NEON_DATA_API_URL, }, }); ``` - Returns user and session data on success - User data is stored in your database - Sessions are managed automatically ### Parameters
View parameters | Parameter | Type | Required | | -------------------- | --------------------------- | -------- | | email | string | ✓ | | name | string | ✓ | | password | string | ✓ | | image | string \| undefined | | | phoneNumber | string \| null \| undefined | | | callbackURL | string \| undefined | |
```typescript const result = await client.auth.signUp.email({ email: 'user@example.com', password: 'password123', name: 'John Doe' }) if (result.error) { console.error('Sign up error:', result.error.message) } else { console.log('User created:', result.data.user) } ````
- Returns user and session on success - Session tokens are cached automatically - Authentication state syncs across browser tabs ### Parameters
View parameters | Parameter | Type | Required | | -------------------- | -------------------- | -------- | | email | string | ✓ | | password | string | ✓ | | rememberMe | boolean \| undefined | | | callbackURL | string \| undefined | |
```typescript const result = await client.auth.signIn.email({ email: 'user@example.com', password: 'password123' }) if (result.error) { console.error('Sign in error:', result.error.message) } else { console.log('Signed in:', result.data.user.email) } ````
Sign in with an OAuth provider like Google, GitHub, etc. - Redirects user to provider's authorization page - User is redirected back after authorization - Session is created automatically ### Parameters
View parameters | Parameter | Type | Required | | --------------------------- | --------------------- | -------- | | provider | object | ✓ | | callbackURL | string \| undefined | | | newUserCallbackURL | string \| undefined | | | errorCallbackURL | string \| undefined | | | disableRedirect | boolean \| undefined | | | idToken | object | | | scopes | string[] \| undefined | | | requestSignUp | boolean \| undefined | | | loginHint | string \| undefined | | | additionalData | object | |
```typescript await client.auth.signIn.social({ provider: 'github', callbackURL: 'https://yourapp.com/auth/callback', }); ``` ```typescript await client.auth.signIn.social({ provider: 'google', callbackURL: 'https://yourapp.com/auth/callback', }); ```
- Clears local session cache - Notifies other browser tabs (cross-tab sync) - Removes authentication tokens ```typescript const { error } = await client.auth.signOut() if (error) { console.error('Sign out error:', error.message) } ```` - Returns cached session if available (fast) - Automatically refreshes expired tokens - Returns null if no active session ```typescript const { data, error } = await client.auth.getSession() if (data.session) { console.log('User is logged in:', data.session.user.email) } else { console.log('No active session') } ```` Note: Password updates require password reset flow for security. ### Parameters
View parameters | Parameter | Type | Required | | -------------------- | --------------------------- | -------- | | name | string \| undefined | | | image | string \| null \| undefined | | | phoneNumber | string \| null \| undefined | |
```typescript const { data, error } = await client.auth.updateUser({ email: 'newemail@example.com' }) ```
Sends an OTP (one-time password) code to the user's email for sign-in. The user must then call `signIn.emailOtp()` with the received code. ### Parameters
View parameters | Parameter | Type | Required | | -------------- | ------ | -------- | | email | string | ✓ | | type | object | ✓ |
```typescript const { error } = await client.auth.emailOtp.sendVerificationOtp({ email: 'user@example.com', type: 'sign-in' }) if (error) { console.error('Failed to send OTP:', error.message) } ````
Signs in a user using an OTP code received via email. First call `emailOtp.sendVerificationOtp()` to send the code. ### Parameters
View parameters | Parameter | Type | Required | | -------------- | ------ | -------- | | email | string | ✓ | | otp | string | ✓ |
```typescript const { data, error } = await client.auth.signIn.emailOtp({ email: 'user@example.com', otp: '123456' }) if (error) { console.error('OTP verification failed:', error.message) } else { console.log('Signed in:', data.user.email) } ````
Verifies a user's email address using an OTP code sent during signup. This is typically used after `signUp.email()` when email verification is required. ### Parameters
View parameters | Parameter | Type | Required | | -------------- | ------ | -------- | | email | string | ✓ | | otp | string | ✓ |
```typescript const { data, error } = await client.auth.emailOtp.verifyEmail({ email: 'user@example.com', otp: '123456' }) if (error) { console.error('Email verification failed:', error.message) } else { console.log('Email verified successfully') } ````
Checks if an OTP code is valid without completing the verification flow. Useful for password reset flows where you need to verify the code before allowing password change. ### Parameters
View parameters | Parameter | Type | Required | | -------------- | ------ | -------- | | email | string | ✓ | | type | object | ✓ | | otp | string | ✓ |
```typescript const { data, error } = await client.auth.emailOtp.checkVerificationOtp({ email: 'user@example.com', otp: '123456', type: 'forget-password' }) if (error || !data.success) { console.error('Invalid OTP code') } ````
Sends a verification email to the user. Used for email verification after signup or email change. ### Parameters
View parameters | Parameter | Type | Required | | -------------------- | ------------------- | -------- | | email | string | ✓ | | callbackURL | string \| undefined | |
```typescript const { error } = await client.auth.sendVerificationEmail({ email: 'user@example.com', callbackURL: 'https://yourapp.com/verify-email' }) if (error) { console.error('Failed to send verification email:', error.message) } ````
Verifies an email address using a token from a verification email link. Used for email change verification. ### Parameters
View parameters | Parameter | Type | Required | | -------------- | ------ | -------- | | query | object | ✓ |
```typescript const { data, error } = await client.auth.verifyEmail({ query: { token: 'verification-token-from-email', callbackURL: 'https://yourapp.com/email-verified' } }) if (error) { console.error('Email verification failed:', error.message) } ````
Sends a password reset email to the user. The email contains a link to reset the password. ### Parameters
View parameters | Parameter | Type | Required | | ------------------- | ------------------- | -------- | | email | string | ✓ | | redirectTo | string \| undefined | |
```typescript const { error } = await client.auth.requestPasswordReset({ email: 'user@example.com', redirectTo: 'https://yourapp.com/reset-password' }) if (error) { console.error('Failed to send password reset email:', error.message) } ````
- Authentication token is included automatically if user is signed in - Returns typed data based on your database schema - Row-level security policies determine what data is returned ```typescript const { data, error } = await client.from('todos').select('*'); ```` ```typescript const { data, error } = await client.from('todos').select('id, title, completed'); ``` ```typescript const { data, error } = await client.from('todos').select('*').eq('completed', false); ``` ```typescript const { data, error } = await client.from('todos').select('*, owner:users(*)'); ``` - Authentication token is included automatically - Can insert single or multiple rows - Returns inserted data by default ```typescript const { data, error } = await client .from('todos') .insert({ title: 'Buy groceries', completed: false }) .select(); ``` ```typescript const { data, error } = await client .from('todos') .insert([ { title: 'Task 1', completed: false }, { title: 'Task 2', completed: false }, ]) .select(); ``` - Requires filter to specify which rows to update - Authentication token is included automatically ```typescript const { data, error } = await client .from('todos') .update({ completed: true }) .eq('id', 1) .select() ``` - Requires filter to specify which rows to delete - Authentication token is included automatically ### Parameters
View parameters | Parameter | Type | Required | | -------------- | ------------------------------------------------ | -------- | | count | "exact" \| "planned" \| "estimated" \| undefined | |
```typescript const { error } = await client .from('todos') .delete() .eq('id', 1) ```
- Authentication token is included automatically - Pass parameters as object - Returns function result ```typescript const { data, error } = await client.rpc('get_user_stats', { user_id: 123, start_date: '2024-01-01' }) if (error) { console.error('RPC error:', error.message) } else { console.log('Stats:', data) } ```` Filters rows where the specified column equals the given value. Can be chained with other filters to create complex queries. ```typescript const { data, error } = await client .from('todos') .select('*') .eq('completed', true) ```` Filters rows where the specified column does not equal the given value. Useful for excluding specific values from results. ```typescript const { data, error } = await client .from('todos') .select('*') .neq('status', 'archived') ``` Filters rows where the specified column is greater than the given value. Works with numeric values, dates, and other comparable types. ```typescript const { data, error } = await client .from('todos') .select('*') .gt('priority', 5) ``` Filters rows where the specified column is less than the given value. Works with numeric values, dates, and other comparable types. ```typescript const { data, error } = await client .from('todos') .select('*') .lt('priority', 10) ``` Sorts query results by the specified column. Use `{ ascending: true }` for ascending order or `{ ascending: false }` for descending order. ```typescript const { data, error } = await client .from('todos') .select('*') .order('created_at', { ascending: true }); ``` ```typescript const { data, error } = await client .from('todos') .select('*') .order('created_at', { ascending: false }); ```
Limits the number of rows returned by the query. Useful for pagination and preventing large result sets. ```typescript const { data, error } = await client .from('todos') .select('*') .limit(10) ``` Filters rows where the specified column is greater than or equal to the given value. The comparison is inclusive (includes rows where column equals the value). ```typescript const { data, error } = await client .from('todos') .select('*') .gte('priority', 5) ``` Filters rows where the specified column is less than or equal to the given value. The comparison is inclusive (includes rows where column equals the value). ```typescript const { data, error } = await client .from('todos') .select('*') .lte('priority', 10) ``` Filter rows where column matches pattern (case-sensitive). Use % as wildcard: '%pattern%' matches any string containing 'pattern' ```typescript const { data, error } = await client .from('todos') .select('*') .like('title', '%groceries%') ``` Use % as wildcard: '%pattern%' matches any string containing 'pattern' ```typescript const { data, error } = await client .from('todos') .select('*') .ilike('title', '%groceries%') ``` Filters rows based on whether a column is null or not null. Use `null` to find rows where the column is null, or `'not.null'` to find rows where it's not null. ```typescript const { data, error } = await client.from('todos').select('*').is('deleted_at', null); ``` ```typescript const { data, error } = await client.from('todos').select('*').is('completed_at', 'not.null'); ``` Filters rows where the column value matches any value in the provided array. Useful for filtering by multiple possible values (e.g., status in ['pending', 'active']). ```typescript const { data, error } = await client .from('todos') .select('*') .in('status', ['pending', 'in-progress']) ``` Filters rows where an array or JSONB column contains the specified value. For arrays, checks if the value exists in the array. For JSONB, checks if the value is contained in the JSON object. ```typescript const { data, error } = await client .from('todos') .select('*') .contains('tags', ['urgent']) ``` Range is inclusive (includes both start and end values). ```typescript const { data, error } = await client .from('todos') .select('*') .range('priority', 5, 10) ```