Short answer
Linkbreakers provides two types of API keys: secret keys for backend environments with full API access, and publishable keys for frontend applications with read-only, limited permissions. Secret keys can create links, access analytics, and modify workspace data. Publishable keys can only identify visitors and read limited visitor data. Never expose secret keys in client-side code.
Key differences at a glance
| Feature | Secret Key | Publishable Key |
|---|---|---|
| Environment | Backend only | Frontend safe |
| Permissions | Full API access | Read-only, limited scope |
| Create links | ✅ Yes | ❌ No |
| Delete links | ✅ Yes | ❌ No |
| View analytics | ✅ Yes | ❌ No |
| Identify visitors | ✅ Yes | ✅ Yes |
| Update visitor profiles | ✅ Yes | ✅ Yes (own data only) |
| Access workspace data | ✅ Yes | ❌ No |
| Can be exposed publicly | ❌ Never | ✅ Yes |
Secret keys: Full API access
What they do
Secret keys are JWT tokens that grant complete access to your Linkbreakers workspace. They can:
- Create, update, and delete links
- Generate QR codes
- Identify and update visitors
- Access analytics and event data
- Retrieve workspace metrics
- Manage workspace resources
- Full CRUD operations on all resources
Where to use them
Backend environments only:
- Node.js / Express servers
- Python Django / Flask / FastAPI applications
- Next.js API routes (server-side)
- Serverless functions (AWS Lambda, Vercel, Netlify)
- CI/CD pipelines
- Background jobs and cron tasks
- Server-to-server integrations
Security requirements
Critical: Secret keys must NEVER be exposed in:
- ❌ Client-side JavaScript code
- ❌ Mobile apps (iOS, Android)
- ❌ Browser extensions
- ❌ Public GitHub repositories
- ❌ Frontend environment variables (e.g.,
NEXT_PUBLIC_*) - ❌ Error messages or logs
Always:
- ✅ Store in backend environment variables
- ✅ Use secret management systems (AWS Secrets Manager, Vault)
- ✅ Rotate immediately if accidentally exposed
- ✅ Restrict access to production keys
Example usage
// ✅ BACKEND ONLY - Next.js API route
import { Configuration, LinksApi } from 'linkbreakers';
export async function POST(request: Request) {
const config = new Configuration({
accessToken: process.env.LINKBREAKERS_SECRET_KEY, // Secret JWT
basePath: 'https://api.linkbreakers.com',
});
const linksApi = new LinksApi(config);
const { destination, name } = await request.json();
const response = await linksApi.linksServiceCreate({
createLinkRequest: { destination, name }
});
return Response.json({ shortlink: response.link?.shortlink });
}
Publishable keys: Frontend-safe, limited scope
What they do
Publishable keys are JWT tokens with restricted permissions specifically designed for client-side use. They can:
- Identify visitors (associate user data with sessions)
- Update visitor attributes (email, name, custom fields)
- Read visitor profiles (limited to current visitor only)
What they CANNOT do
Publishable keys have no access to:
- ❌ Link creation, modification, or deletion
- ❌ Workspace analytics or metrics
- ❌ Other visitors' data
- ❌ Workspace settings or configuration
- ❌ Any write operations except visitor identification
Where to use them
Frontend environments:
- React / Vue / Angular applications
- Static websites
- Single-page applications (SPAs)
- Mobile apps (iOS, Android, React Native)
- Browser extensions
- Client-side tracking scripts
Why they're safe for frontends
Even if a publishable key is extracted from your frontend code:
- Attackers cannot create or delete links
- They cannot access your analytics or workspace data
- They can only identify visitors (which requires an LBID from your links anyway)
- The scope is limited by JWT claims enforced server-side
Example usage
// ✅ FRONTEND SAFE - React component
import { Configuration, VisitorsApi } from 'linkbreakers';
import { useEffect } from 'react';
export function VisitorTracker({ userEmail }: { userEmail: string }) {
useEffect(() => {
const config = new Configuration({
accessToken: process.env.NEXT_PUBLIC_LINKBREAKERS_PK, // Publishable JWT
basePath: 'https://api.linkbreakers.com',
});
const visitorsApi = new VisitorsApi(config);
const lbid = new URLSearchParams(window.location.search).get('lbid');
if (lbid && userEmail) {
visitorsApi.visitorsServiceIdentify({
identifyRequest: {
lbid,
visitor: {
data: {
'$email': userEmail,
'$firstName': 'John'
}
}
}
});
}
}, [userEmail]);
return null;
}
How JWT claims enforce permissions
Both key types are JWT tokens, but they contain different scopes in their payload:
Secret key JWT claims (example)
{
"workspace_id": "1234",
"type": "secret",
"scopes": [
"links:read",
"links:write",
"links:delete",
"visitors:read",
"visitors:write",
"analytics:read",
"workspace:read"
],
"env": "production",
"iat": 1710936000,
"exp": null
}
Publishable key JWT claims (example)
{
"workspace_id": "1234",
"type": "publishable",
"scopes": [
"visitors:identify",
"visitors:read_self"
],
"env": "production",
"iat": 1710936000,
"exp": null
}
The API server validates these scopes on every request, ensuring publishable keys cannot perform privileged operations even if someone tries to craft malicious requests.
Creating API keys
To create either key type:
- Log in to app.linkbreakers.com
- Navigate to Dashboard → API Tokens
- Click Create API Token
- Choose the key type:
- Secret Key - For backend use, full API access
- Publishable Key - For frontend use, limited scope
- Give it a descriptive name (e.g., "Production Backend" or "Frontend Tracker")
- Copy the JWT token immediately (you won't see it again)
Best practices
Use both key types strategically
Typical architecture:
- Frontend: Use publishable key to identify visitors when they sign up, log in, or submit forms
- Backend: Use secret key to create links, generate QR codes, and access analytics
- Result: Secure integration with minimal exposure
Environment variable naming
# .env file
LINKBREAKERS_SECRET_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... # Backend only
NEXT_PUBLIC_LINKBREAKERS_PK=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... # Frontend safe
Next.js convention: Prefix publishable keys with NEXT_PUBLIC_ to expose them to the browser, while keeping secret keys private.
Rotate keys if compromised
If you accidentally expose a secret key:
- Immediately create a new secret key
- Update your backend environment variables
- Delete the compromised key from the dashboard
- The old key becomes invalid within seconds
Common mistakes to avoid
❌ Using secret keys in frontend code
// WRONG - Secret key exposed in browser
const config = new Configuration({
accessToken: 'eyJhbGciOiJI...secret_key', // ❌ DO NOT DO THIS
});
❌ Trying to create links with publishable keys
// WRONG - Publishable key doesn't have this permission
const linksApi = new LinksApi(config); // config has publishable key
await linksApi.linksServiceCreate(...); // ❌ 403 Forbidden
❌ Committing keys to version control
# .env (should be in .gitignore!)
LINKBREAKERS_SECRET_KEY=eyJhbGciOiJI... # ❌ Never commit this
✅ Correct: Use appropriate keys for each environment
// Frontend - publishable key
const frontendConfig = new Configuration({
accessToken: process.env.NEXT_PUBLIC_LINKBREAKERS_PK,
});
// Backend - secret key
const backendConfig = new Configuration({
accessToken: process.env.LINKBREAKERS_SECRET_KEY,
});
Testing with both key types
Test your integration security:
Test publishable key restrictions
# This should FAIL with 403 Forbidden
curl -X POST https://api.linkbreakers.com/v1/links \
-H "Authorization: Bearer your_publishable_jwt" \
-H "Content-Type: application/json" \
-d '{"destination":"https://example.com"}'
# Response: {"error": "insufficient_permissions", "message": "Publishable keys cannot create links"}
Test secret key access
# This should SUCCEED with 200 OK
curl -X POST https://api.linkbreakers.com/v1/links \
-H "Authorization: Bearer your_secret_jwt" \
-H "Content-Type: application/json" \
-d '{"destination":"https://example.com"}'
# Response: {"link": {"id": "...", "shortlink": "https://lbr.ai/abc123"}}
Frequently asked questions
Can I use the same key for frontend and backend?
No. Use publishable keys for frontend (limited permissions) and secret keys for backend (full access). This separation ensures your backend remains secure even if frontend code is exposed.
What happens if someone steals my publishable key?
They can only identify visitors who clicked your Linkbreakers links (requires LBID). They cannot create links, access analytics, or view your workspace data. The damage is minimal compared to secret key exposure.
Can I revoke a key without creating a new one?
Yes, delete the key from your dashboard. All requests using that JWT will immediately fail with 401 Unauthorized. However, you'll need to create a new key to restore functionality.
How do I know which type of key I have?
Decode the JWT at jwt.io and check the type claim: "type": "secret" or "type": "publishable". You can also check the scopes array to see what permissions it has.
Do publishable keys expire?
Both key types can optionally have expiration timestamps (exp claim). Check your JWT payload or dashboard settings for expiration details.
Related documentation
- TypeScript SDK Quick Start - Learn how to use both key types in TypeScript applications
- Python SDK Quick Start - Backend integration with secret keys
- Why accessToken vs apiKey - Understanding JWT authentication
- What is LBID? - How visitor identification works with publishable keys
Last reviewed
This article was last reviewed on March 20, 2025.
About the Author
Laurent Schaffner
Founder & Engineer at Linkbreakers
Passionate about building tools that help businesses track and optimize their digital marketing efforts. Laurent founded Linkbreakers to make QR code analytics accessible and actionable for companies of all sizes.
Related Articles
How to use the Linkbreakers API
Complete guide to integrating with the Linkbreakers API - create QR codes, manage links, customize designs, track analytics, and automate workflows programmatically.
Analytics API
Access comprehensive QR code and visitor analytics through the Linkbreakers API. Learn how to retrieve campaign performance data, visitor insights, and engagement metrics programmatically for business intelligence integration.
How to integrate Linkbreakers with existing tech stack
Integrate Linkbreakers with your CRM, marketing automation, analytics platforms, and business systems through APIs, webhooks, and direct integrations. Learn best practices for seamless tech stack integration.
On this page
Need more help?
Can't find what you're looking for? Get in touch with our support team.
Contact Support