> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/medusajs/medusa/llms.txt
> Use this file to discover all available pages before exploring further.

# Install JavaScript SDK

> Learn how to install and initialize the Medusa JavaScript SDK

# Installation

This guide covers installing and configuring the Medusa JavaScript SDK in your application.

## Prerequisites

* Node.js 20 or higher
* A Medusa backend instance running (local or hosted)
* Package manager: npm, yarn, or pnpm

## Install the SDK

Install the `@medusajs/js-sdk` package using your preferred package manager:

<CodeGroup>
  ```bash npm theme={null}
  npm install @medusajs/js-sdk
  ```

  ```bash yarn theme={null}
  yarn add @medusajs/js-sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @medusajs/js-sdk
  ```
</CodeGroup>

## Basic Initialization

### Storefront Usage

For customer-facing applications, initialize the SDK with your backend URL and publishable API key:

```tsx theme={null}
import Medusa from "@medusajs/js-sdk"

const sdk = new Medusa({
  baseUrl: "http://localhost:9000", // Your Medusa backend URL
  publishableKey: "pk_01234567890abcdef" // Your publishable API key
})

export default sdk
```

### Admin Usage

For administrative applications, use an API key for authentication:

```tsx theme={null}
import Medusa from "@medusajs/js-sdk"

const sdk = new Medusa({
  baseUrl: "http://localhost:9000",
  apiKey: "sk_01234567890abcdef" // Your secret API key
})

export default sdk
```

<Note>
  Never expose admin API keys in client-side code. Use environment variables and keep them server-side only.
</Note>

## Configuration Options

The SDK accepts a `Config` object with the following options:

### Required Options

<ParamField path="baseUrl" type="string" required>
  The base URL of your Medusa backend API. In browser environments, you can use `/` or an empty string to use the current origin.

  ```tsx theme={null}
  baseUrl: "https://api.example.com"
  ```
</ParamField>

### Authentication Options

<ParamField path="publishableKey" type="string">
  The publishable API key for storefront requests. Required for store API access.

  ```tsx theme={null}
  publishableKey: "pk_01234567890abcdef"
  ```
</ParamField>

<ParamField path="apiKey" type="string">
  The secret API key for admin requests. Use only in server-side environments.

  ```tsx theme={null}
  apiKey: "sk_01234567890abcdef"
  ```
</ParamField>

<ParamField path="auth" type="object">
  Advanced authentication configuration.

  <Expandable title="Auth Configuration">
    <ParamField path="auth.type" type="'jwt' | 'session'" default="jwt">
      The authentication method to use:

      * `jwt`: Store tokens in browser/custom storage (default)
      * `session`: Use HTTP-only cookies for authentication
    </ParamField>

    <ParamField path="auth.jwtTokenStorageKey" type="string" default="medusa_auth_token">
      The storage key for JWT tokens.
    </ParamField>

    <ParamField path="auth.jwtTokenStorageMethod" type="'local' | 'session' | 'memory' | 'custom' | 'nostore'" default="local">
      Where to store JWT tokens:

      * `local`: localStorage (persistent)
      * `session`: sessionStorage (tab-scoped)
      * `memory`: In-memory (lost on refresh)
      * `custom`: Custom storage implementation
      * `nostore`: Don't store tokens
    </ParamField>

    <ParamField path="auth.fetchCredentials" type="'include' | 'omit' | 'same-origin'" default="include">
      Credentials mode for session-based auth. Controls cookie sending behavior.
    </ParamField>

    <ParamField path="auth.storage" type="CustomStorage">
      Custom storage implementation. Required when `jwtTokenStorageMethod` is `custom`.

      ```tsx theme={null}
      storage: {
        getItem: async (key: string) => string | null,
        setItem: async (key: string, value: string) => void,
        removeItem: async (key: string) => void
      }
      ```
    </ParamField>
  </Expandable>
</ParamField>

### Request Options

<ParamField path="globalHeaders" type="ClientHeaders">
  Headers to include in all requests.

  ```tsx theme={null}
  globalHeaders: {
    "x-custom-header": "value",
    "cache-control": {
      tags: ["all-requests"] // Next.js cache tags
    }
  }
  ```
</ParamField>

### Debugging Options

<ParamField path="debug" type="boolean" default="false">
  Enable debug logging to console.

  ```tsx theme={null}
  debug: process.env.NODE_ENV === "development"
  ```
</ParamField>

<ParamField path="logger" type="Logger">
  Custom logger implementation.

  ```tsx theme={null}
  logger: {
    error: (...messages: string[]) => void,
    warn: (...messages: string[]) => void,
    info: (...messages: string[]) => void,
    debug: (...messages: string[]) => void
  }
  ```
</ParamField>

## Common Setup Examples

### React Application

Create a dedicated SDK instance file:

```tsx title="src/lib/medusa.ts" theme={null}
import Medusa from "@medusajs/js-sdk"

const sdk = new Medusa({
  baseUrl: process.env.NEXT_PUBLIC_MEDUSA_API_URL || "http://localhost:9000",
  publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
  debug: process.env.NODE_ENV === "development"
})

export default sdk
```

Use in components:

```tsx title="src/components/ProductList.tsx" theme={null}
import { useEffect, useState } from "react"
import sdk from "@/lib/medusa"
import type { HttpTypes } from "@medusajs/types"

export function ProductList() {
  const [products, setProducts] = useState<HttpTypes.StoreProduct[]>([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    sdk.store.product.list()
      .then(({ products }) => setProducts(products))
      .finally(() => setLoading(false))
  }, [])

  if (loading) return <div>Loading...</div>

  return (
    <div>
      {products.map((product) => (
        <div key={product.id}>{product.title}</div>
      ))}
    </div>
  )
}
```

### Next.js Application

#### Client Components

```tsx title="src/lib/sdk/client.ts" theme={null}
import Medusa from "@medusajs/js-sdk"

export const sdk = new Medusa({
  baseUrl: process.env.NEXT_PUBLIC_MEDUSA_API_URL!,
  publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
  auth: {
    type: "session",
    fetchCredentials: "include"
  }
})
```

#### Server Components

```tsx title="src/lib/sdk/server.ts" theme={null}
import Medusa from "@medusajs/js-sdk"

export async function getServerSDK() {
  return new Medusa({
    baseUrl: process.env.MEDUSA_API_URL!,
    publishableKey: process.env.MEDUSA_PUBLISHABLE_KEY
  })
}
```

Use in server components:

```tsx title="app/products/page.tsx" theme={null}
import { getServerSDK } from "@/lib/sdk/server"

export default async function ProductsPage() {
  const sdk = await getServerSDK()
  const { products } = await sdk.store.product.list({
    fields: "id,title,thumbnail"
  })

  return (
    <div>
      {products.map((product) => (
        <div key={product.id}>{product.title}</div>
      ))}
    </div>
  )
}
```

### React Native Application

Use AsyncStorage for token persistence:

```tsx title="src/lib/medusa.ts" theme={null}
import Medusa from "@medusajs/js-sdk"
import AsyncStorage from '@react-native-async-storage/async-storage'

const sdk = new Medusa({
  baseUrl: "https://api.example.com",
  publishableKey: "pk_...",
  auth: {
    type: "jwt",
    jwtTokenStorageMethod: "custom",
    jwtTokenStorageKey: "medusa_token",
    storage: {
      getItem: async (key) => {
        return await AsyncStorage.getItem(key)
      },
      setItem: async (key, value) => {
        await AsyncStorage.setItem(key, value)
      },
      removeItem: async (key) => {
        await AsyncStorage.removeItem(key)
      }
    }
  }
})

export default sdk
```

### Node.js/Express Backend

Use API key authentication:

```tsx title="src/lib/medusa.ts" theme={null}
import Medusa from "@medusajs/js-sdk"

const sdk = new Medusa({
  baseUrl: process.env.MEDUSA_API_URL || "http://localhost:9000",
  apiKey: process.env.MEDUSA_API_KEY
})

export default sdk
```

### Vanilla JavaScript

Use via CDN or bundler:

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <title>Medusa Store</title>
</head>
<body>
  <div id="products"></div>

  <script type="module">
    import Medusa from "@medusajs/js-sdk"

    const sdk = new Medusa({
      baseUrl: "http://localhost:9000",
      publishableKey: "pk_..."
    })

    async function loadProducts() {
      const { products } = await sdk.store.product.list()
      const container = document.getElementById("products")
      
      products.forEach(product => {
        const div = document.createElement("div")
        div.textContent = product.title
        container.appendChild(div)
      })
    }

    loadProducts()
  </script>
</body>
</html>
```

## Environment Variables

Store your configuration in environment variables:

```bash title=".env.local" theme={null}
# Medusa API Configuration
NEXT_PUBLIC_MEDUSA_API_URL=http://localhost:9000
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_01234567890abcdef

# Admin API Key (server-side only)
MEDUSA_API_KEY=sk_01234567890abcdef
```

<Warning>
  Always prefix client-side environment variables with `NEXT_PUBLIC_` (Next.js) or your framework's convention. Never expose admin API keys in client-side code.
</Warning>

## Verify Installation

Test your SDK setup:

```tsx theme={null}
import sdk from "./lib/medusa"

async function testConnection() {
  try {
    const { regions } = await sdk.store.region.list()
    console.log("Connected! Found", regions.length, "regions")
  } catch (error) {
    console.error("Failed to connect:", error)
  }
}

testConnection()
```

## Next Steps

<CardGroup cols={2}>
  <Card title="SDK Methods" icon="code" href="/sdk/methods">
    Learn about available methods and how to use the client
  </Card>

  <Card title="API Authentication" icon="lock" href="/api/authentication">
    Implement user authentication and session management
  </Card>
</CardGroup>
