Quickstart
Get Impersona running locally in minutes.
Get Impersona running locally in minutes. This guide assumes you already have a working app with authentication and permissions.
1) Create an Impersona project
In the Impersona dashboard:
- Sign up or log in
- Create an organization (or use the auto-created one)
- Create a project — give it a name and slug
- Go to the API Keys tab and generate a publishable key (this is a separate step — project creation does not auto-generate a key)
- Go to Settings and add your frontend's origin to Allowed Origins (e.g.
http://localhost:5173)
You'll need the project ID and publishable key for the next step.
2) Install the SDK
npm install @impersona/sdk3) Add environment variables
Create or update your .env file with the values from the dashboard:
# Must match the project in your Impersona dashboard
VITE_IMPERSONA_PROJECT_ID=proj_abc123
VITE_IMPERSONA_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxx
# Only set if self-hosting; omit to use the hosted default
# VITE_IMPERSONA_API_BASE_URL=http://localhost:3002/api/v1# Must match the project in your Impersona dashboard
NEXT_PUBLIC_IMPERSONA_PROJECT_ID=proj_abc123
NEXT_PUBLIC_IMPERSONA_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxx
# Only set if self-hosting; omit to use the hosted default
# NEXT_PUBLIC_IMPERSONA_API_BASE_URL=http://localhost:3002/api/v1# Must match the project in your Impersona dashboard
REACT_APP_IMPERSONA_PROJECT_ID=proj_abc123
REACT_APP_IMPERSONA_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxx
# Only set if self-hosting; omit to use the hosted default
# REACT_APP_IMPERSONA_API_BASE_URL=http://localhost:3002/api/v14) Initialize the SDK
Add the provider and widget to your app's component tree:
import { ImpersonaProvider } from '@impersona/sdk'
import { ImpersonaWidget } from '@impersona/sdk/widget'
export function App() {
return (
<ImpersonaProvider
projectId={import.meta.env.VITE_IMPERSONA_PROJECT_ID}
publishableKey={import.meta.env.VITE_IMPERSONA_PUBLISHABLE_KEY}
apiBaseUrl={import.meta.env.VITE_IMPERSONA_API_BASE_URL || undefined}
enabled={import.meta.env.DEV}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
<ImpersonaWidget />
</ImpersonaProvider>
)
}import { ImpersonaProvider } from '@impersona/sdk'
import { ImpersonaWidget } from '@impersona/sdk/widget'
export function App() {
return (
<ImpersonaProvider
projectId={process.env.NEXT_PUBLIC_IMPERSONA_PROJECT_ID!}
publishableKey={process.env.NEXT_PUBLIC_IMPERSONA_PUBLISHABLE_KEY!}
apiBaseUrl={process.env.NEXT_PUBLIC_IMPERSONA_API_BASE_URL || undefined}
enabled={process.env.NODE_ENV === 'development'}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
<ImpersonaWidget />
</ImpersonaProvider>
)
}import { ImpersonaProvider } from '@impersona/sdk'
import { ImpersonaWidget } from '@impersona/sdk/widget'
export function App() {
return (
<ImpersonaProvider
projectId={process.env.REACT_APP_IMPERSONA_PROJECT_ID!}
publishableKey={process.env.REACT_APP_IMPERSONA_PUBLISHABLE_KEY!}
apiBaseUrl={process.env.REACT_APP_IMPERSONA_API_BASE_URL || undefined}
enabled={process.env.NODE_ENV === 'development'}
refreshStrategy={{ type: 'reload' }}
>
{/* your app tree */}
<ImpersonaWidget />
</ImpersonaProvider>
)
}When no tokenAdapter is passed, the provider creates a default FetchInterceptorAdapter that:
- Only patches requests to same-origin URLs
- Automatically excludes SDK-internal calls (requests to
apiBaseUrl)
This default is correct for most setups. See Installation for when you need a custom adapter.
5) Decide how to pass identity to your host
Impersona can impersonate by swapping the Authorization header, or by sending a separate Impersona token header that your host reads.
Choose the pattern that matches your app:
- Bearer token (common for APIs): Impersona replaces
Authorization: Bearer <token>with the impersonated user's token - Custom header: Your host reads
X-Impersona-Token(or another header you choose) and resolves the impersonated identity - Cookie session: Your host reads an Impersona token header and creates a session
See Auth Strategies for details.
6) Verify the integration
Start your dev server and load your app in the browser.
What to look for:
- A small widget bubble (56x56px) appears in the corner of your app
- The widget fetches presets from
/api/v1/presets— check the Network tab for a200response - If you've created presets in the dashboard, they appear in the widget's preset list
If something is wrong:
| Symptom | Likely cause |
|---|---|
| Widget doesn't appear | enabled is false, or the SDK isn't mounted |
| 401 Unauthorized (fast, <10ms) | Publishable key doesn't match the dashboard |
| 403 "Origin not allowed" | Your frontend origin isn't in the dashboard's Allowed Origins |
| Network/CORS error | apiBaseUrl is wrong or the backend can't be reached |
See Troubleshooting for more.
7) Move to permissions testing
Use Permissions Testing to verify role-based or attribute-based access control across your app.