Publishable Keys
API keys come in two types: publishable keys for client-side code and secret keys for server-side code.
Key formats
| Prefix | Type | Safe to expose |
|--------|------|---------------|
| pk_live_ | Live publishable key | Yes |
| pk_test_ | Test publishable key | Yes |
| sk_live_ | Live secret key | No |
| sk_test_ | Test secret key | No |
Live keys operate against your production data. Test keys operate against isolated test data and are rate-limited differently.
Which key goes where
Frontend code (React, Next.js, browser JS):
Use pk_live_ or pk_test_ keys. These are safe to expose in client-side bundles, HTML, and mobile apps.
// next.config or environment variable
NEXT_PUBLIC_BULWARK_PUBLISHABLE_KEY=pk_live_abc123...
// In your React app
<BulwarkProvider publishableKey={process.env.NEXT_PUBLIC_BULWARK_PUBLISHABLE_KEY}>
Backend code (Node.js, NestJS, API routes):
Use sk_live_ or sk_test_ keys. Never expose these in client-side code. Store them in environment variables, secrets managers, or .env files (not committed to git).
# .env (server-side only, never committed)
BULWARK_SECRET_KEY=sk_live_xyz789...
Quick rule: If the prefix starts with pk_ it can go in the browser. If it starts with sk_ it stays on the server.
Publishable keys
Publishable keys (pk_live_, pk_test_) are designed to be embedded in client-side JavaScript, mobile apps, and any other context where code is visible to end users.
What they can do:
- Identify the application to the Bulwark API
- Load your app's configuration (auth methods, branding, tenant settings)
- Initiate authentication flows on behalf of users
What they cannot do:
- Access or modify user data without a valid user session
- Perform admin operations
- Issue tokens outside of normal authentication flows
- Read secret credentials or API keys
A publishable key on its own is useless to an attacker. It is analogous to a public client ID in OAuth 2.0.
Secret keys
Secret keys (sk_live_, sk_test_) have full API access including admin operations. Treat them like passwords.
- Store them only in environment variables or secrets managers
- Never include them in client-side code, Git repositories, or build artifacts
- Use them only from server-side code (Node.js, Go, etc.)
- Rotate them if you suspect they have been exposed
Secret keys are shown once at creation time and then hashed for storage. If you lose a secret key, rotate it to generate a new one.
How publishable keys resolve app config
When the SDK initializes with a publishable key, it calls:
POST /api/v1/auth/identify
Content-Type: application/json
{
"publishable_key": "pk_live_..."
}
Response
{
"tenant_id": "tenant_01j...",
"app_name": "Acme Corp",
"auth_methods": ["password", "magic_link", "google"],
"branding": {
"logo_url": "https://cdn.example.com/logo.png",
"primary_color": "#6366f1",
"background_color": "#ffffff"
},
"mfa_required": false,
"allowed_origins": ["https://myapp.com", "http://localhost:3000"]
}
The resolved config is cached in the SDK and used to render pre-built components with the correct options. If allowed_origins does not include the current page origin, requests are rejected.
Key rotation
Rotating secret keys
POST /api/v1/settings/applications/{id}/rotate-secret
Authorization: Bearer <admin-token>
X-Bulwark-Tenant: <tenant-id>
This invalidates the current secret key immediately and returns a new one. Update your environment variables before rotating in production.
Response
{
"secret_key": "sk_live_...",
"created_at": "2026-03-20T10:00:00Z"
}
Publishable key stability
Publishable keys do not need to be rotated as part of normal security hygiene — their limited capabilities make rotation low-priority. If you do need to change a publishable key (e.g., application restructuring), create a new application in the dashboard.
Obtaining keys
Publishable and secret keys are per-application. Each application in your workspace has its own key pair, so make sure you are looking at the correct app before copying keys.
- Go to app.bulwarkauth.com
- Use the app switcher in the top navigation to select the application you need keys for
- Navigate to Configure > API Keys
Both the publishable key and the option to generate a new secret key are available on that page.