Secret Key vs Publishable Key: Understanding the Difference

Learn the critical differences between Linkbreakers secret keys (full API access, backend-only) and publishable keys (limited scope, frontend-safe) to secure your integration and prevent unauthorized access.

Developer
5 min read
By Laurent Schaffner
Updated March 20, 2025

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

TypeScript
// ✅ 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

TypeScript
// ✅ 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)

JSON
{
  "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)

JSON
{
  "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:

  1. Log in to app.linkbreakers.com
  2. Navigate to Dashboard → API Tokens
  3. Click Create API Token
  4. Choose the key type:
    • Secret Key - For backend use, full API access
    • Publishable Key - For frontend use, limited scope
  5. Give it a descriptive name (e.g., "Production Backend" or "Frontend Tracker")
  6. 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

Bash
# .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:

  1. Immediately create a new secret key
  2. Update your backend environment variables
  3. Delete the compromised key from the dashboard
  4. The old key becomes invalid within seconds

Common mistakes to avoid

❌ Using secret keys in frontend code

TypeScript
// 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

TypeScript
// 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

Bash
# .env (should be in .gitignore!)
LINKBREAKERS_SECRET_KEY=eyJhbGciOiJI...  # ❌ Never commit this

✅ Correct: Use appropriate keys for each environment

TypeScript
// 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

Bash
# 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

Bash
# 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.

Last reviewed

This article was last reviewed on March 20, 2025.

About the Author

LS

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.