Short answer
Linkbreakers uses accessToken (not apiKey) for SDK authentication because the API keys are JWT tokens containing encoded access information, scopes, and permissions. Using apiKey won't send proper authentication headers, causing 401 Unauthorized errors.
The difference: accessToken vs apiKey
When configuring the Linkbreakers SDK, you must use the accessToken parameter:
// ✅ CORRECT - Sends authentication headers
const config = new Configuration({
accessToken: 'pk_live_your_key_here',
basePath: 'https://api.linkbreakers.com',
});
// ❌ WRONG - Does NOT authenticate
const config = new Configuration({
apiKey: 'pk_live_your_key_here', // This parameter is ignored!
});
Why this matters: The underlying OpenAPI-generated SDK code uses accessToken to populate the Authorization: Bearer {token} header. The apiKey parameter is designed for a different authentication scheme (API key headers like X-API-Key) which Linkbreakers doesn't use.
Why JWT tokens?
Linkbreakers API keys are JSON Web Tokens (JWT), not simple API keys. This design provides several advantages:
What's inside the JWT
When you create an API key, Linkbreakers generates a JWT containing:
- Workspace ID: Which workspace the key belongs to
- Key type: Publishable (
pk_live_) or secret (sk_live_) - Scopes/permissions: What operations the key can perform
- Expiration: Optional expiration timestamp
- Issued at: When the key was created
- Key metadata: Environment (live/test) and usage context
Benefits of JWT tokens
Server-side validation without database lookups: The API can verify and decode the JWT to extract workspace ID and permissions without querying the database for every request, improving performance.
Built-in permissions: The token itself contains scope information, allowing the API to enforce publishable vs secret key restrictions at the token level.
Revocation tracking: While JWTs are stateless, Linkbreakers maintains a revocation list for invalidated tokens, providing the best of both worlds.
Tamper-proof: JWTs are cryptographically signed, making them impossible to forge or modify without detection.
TypeScript SDK: Correct usage
import { Configuration, LinksApi } from 'linkbreakers';
// ✅ CORRECT
const config = new Configuration({
accessToken: process.env.LINKBREAKERS_SECRET_KEY, // Use accessToken
basePath: 'https://api.linkbreakers.com',
});
const linksApi = new LinksApi(config);
const response = await linksApi.linksServiceCreate({
createLinkRequest: {
destination: 'https://example.com',
name: 'My Link'
}
});
What happens under the hood
When you use accessToken, the SDK sends:
POST /v1/links HTTP/1.1
Host: api.linkbreakers.com
Authorization: Bearer pk_live_your_key_here
Content-Type: application/json
{"destination":"https://example.com","name":"My Link"}
Python SDK: Correct usage
from linkbreakers import Configuration, ApiClient, LinksApi
# ✅ CORRECT
configuration = Configuration(
access_token=os.getenv('LINKBREAKERS_SECRET_KEY'), # Use access_token
host='https://api.linkbreakers.com'
)
with ApiClient(configuration) as api_client:
links_api = LinksApi(api_client)
response = links_api.links_service_create({
'destination': 'https://example.com',
'name': 'My Link'
})
Raw HTTP: Using the API directly
If you're not using the SDK and making direct HTTP requests, include the API key in the Authorization header with the Bearer scheme:
# ✅ CORRECT - Using Bearer token
curl -X POST https://api.linkbreakers.com/v1/links \
-H "Authorization: Bearer pk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"destination": "https://example.com",
"name": "My Link"
}'
// ✅ CORRECT - Fetch API
const response = await fetch('https://api.linkbreakers.com/v1/links', {
method: 'POST',
headers: {
'Authorization': 'Bearer pk_live_your_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
destination: 'https://example.com',
name: 'My Link'
})
});
# ✅ CORRECT - requests library
import requests
response = requests.post(
'https://api.linkbreakers.com/v1/links',
headers={
'Authorization': 'Bearer pk_live_your_key_here',
'Content-Type': 'application/json'
},
json={
'destination': 'https://example.com',
'name': 'My Link'
}
)
Wrong approaches (don't use these)
# ❌ WRONG - Custom API key header (not supported)
curl -X POST https://api.linkbreakers.com/v1/links \
-H "X-API-Key: pk_live_your_key_here" \
-d '{"destination":"https://example.com"}'
# ❌ WRONG - Query parameter (not supported)
curl -X POST "https://api.linkbreakers.com/v1/links?api_key=pk_live_your_key_here" \
-d '{"destination":"https://example.com"}'
# ❌ WRONG - Basic auth (not supported)
curl -X POST https://api.linkbreakers.com/v1/links \
-u "pk_live_your_key_here:" \
-d '{"destination":"https://example.com"}'
Common authentication errors
Error: "401 Unauthorized"
Cause: You used apiKey instead of accessToken in the SDK configuration, or didn't include the Authorization header in raw HTTP requests.
Fix:
// Change this:
const config = new Configuration({
apiKey: 'pk_live_...', // ❌ Wrong
});
// To this:
const config = new Configuration({
accessToken: 'pk_live_...', // ✅ Correct
});
Error: "Missing or invalid authorization header"
Cause: The Authorization header is missing or doesn't use the Bearer scheme.
Fix: Ensure the header format is exactly Authorization: Bearer {your_token}
Error: "Invalid token signature"
Cause: The JWT token is malformed, expired, or has been tampered with.
Fix: Generate a new API key from your dashboard and replace the old one.
Testing your authentication
Verify your authentication is working correctly:
# Test with curl
curl -X GET https://api.linkbreakers.com/v1/links \
-H "Authorization: Bearer pk_live_your_key_here" \
-w "\nHTTP Status: %{http_code}\n"
# Should return HTTP Status: 200 with your links list
# If you get HTTP Status: 401, check your token and header format
Frequently asked questions
Why doesn't Linkbreakers use traditional API keys?
Traditional API keys are just random strings that require database lookups on every request. JWTs encode access information directly in the token, enabling faster authentication and permission checks.
Can I decode my API key to see what's inside?
Yes! JWTs are base64-encoded and can be decoded (but not modified without invalidation). You can paste your token into jwt.io to inspect the payload. However, never share your tokens publicly.
What if I accidentally used apiKey instead of accessToken?
Your requests will fail with 401 Unauthorized errors because no authentication headers are sent. Simply change apiKey to accessToken in your configuration.
Does the JWT contain my secret data?
No. The JWT only contains metadata about the key itself (workspace ID, permissions, key type). It doesn't contain sensitive workspace data.
Why Bearer authentication instead of X-API-Key headers?
Bearer tokens are the industry standard for OAuth 2.0 and JWT-based authentication. They're well-supported by HTTP clients, API gateways, and have better tooling support than custom header schemes.
Sources
- JSON Web Tokens (JWT) Introduction
- RFC 6750: Bearer Token Usage
- Linkbreakers TypeScript SDK Quick Start
- Linkbreakers Python SDK Quick Start
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