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:
npm install @medusajs/js-sdk
Basic Initialization
Storefront Usage
For customer-facing applications, initialize the SDK with your backend URL and publishable API key:
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:
import Medusa from "@medusajs/js-sdk"
const sdk = new Medusa ({
baseUrl: "http://localhost:9000" ,
apiKey: "sk_01234567890abcdef" // Your secret API key
})
export default sdk
Never expose admin API keys in client-side code. Use environment variables and keep them server-side only.
Configuration Options
The SDK accepts a Config object with the following options:
Required Options
The base URL of your Medusa backend API. In browser environments, you can use / or an empty string to use the current origin. baseUrl : "https://api.example.com"
Authentication Options
The publishable API key for storefront requests. Required for store API access. publishableKey : "pk_01234567890abcdef"
The secret API key for admin requests. Use only in server-side environments. apiKey : "sk_01234567890abcdef"
Advanced authentication configuration. auth.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
auth.jwtTokenStorageKey
string
default: "medusa_auth_token"
The storage key for JWT tokens.
auth.jwtTokenStorageMethod
'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
auth.fetchCredentials
'include' | 'omit' | 'same-origin'
default: "include"
Credentials mode for session-based auth. Controls cookie sending behavior.
Custom storage implementation. Required when jwtTokenStorageMethod is custom. storage : {
getItem : async ( key : string ) => string | null ,
setItem : async ( key : string , value : string ) => void ,
removeItem : async ( key : string ) => void
}
Request Options
Headers to include in all requests. globalHeaders : {
"x-custom-header" : "value" ,
"cache-control" : {
tags: [ "all-requests" ] // Next.js cache tags
}
}
Debugging Options
Enable debug logging to console. debug : process . env . NODE_ENV === "development"
Custom logger implementation. logger : {
error : ( ... messages : string []) => void ,
warn : ( ... messages : string []) => void ,
info : ( ... messages : string []) => void ,
debug : ( ... messages : string []) => void
}
Common Setup Examples
React Application
Create a dedicated SDK instance file:
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:
src/components/ProductList.tsx
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
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
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:
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:
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:
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:
<! 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:
# 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
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.
Verify Installation
Test your SDK setup:
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
SDK Methods Learn about available methods and how to use the client
API Authentication Implement user authentication and session management