Documentation
Complete guide to integrating Key-Rex authentication into your website
New to Key-Rex? Sign in with your Lightning wallet and complete the setup wizard to get your integration code and access your personalized dashboard with account-specific examples.
Quick Start Guide
Get Key-Rex working on your website in just a few minutes. This guide covers the essential steps.
Step 1: Get Your Integration Code
- Sign in with your Lightning wallet and complete the setup wizard to access your dashboard (or create an account if you haven't)
- Go to the "My Integration Code" tab in your dashboard
- Copy the integration code provided
Step 2: Add Code to Your Website
Paste the integration code into your HTML, just before the closing </body> tag:
<body> <!-- Your website content --> <!-- Key-Rex Integration Code --> <script src="https://yourdomain.com/embed?siteId=YOUR_SITE_ID"></script> <!-- Note: KeyRex.init() is optional - script auto-initializes when DOM is ready --> <script>KeyRex.init();</script> </body>
Step 3: Add and Verify Your Domain
- Go to the "Domains" tab in your dashboard
- Add your website domain (e.g.,
example.com) - Verify domain ownership by adding the DNS TXT record shown in the dashboard (production domains require verification)
- Click "Verify" after adding the DNS record (wait 5-10 minutes for DNS propagation)
- Add both www and non-www versions if you use both (each requires separate verification)
Note: Test domains like localhost and 127.0.0.1 are automatically allowed for development and don't require verification.
Step 4: Set Up Backend Integration
When a user authenticates, Key-Rex will call your onSuccess callback with their xpub (extended public key). You need to:
- Receive the xpub in your backend
- Create a session for the user
- Store the xpub as their user identifier
See the Backend Integration section for detailed examples.
✓ That's It!
Your Key-Rex button should now appear on your website. Visitors can click it to sign in with their Lightning wallets. Continue reading for framework-specific examples and advanced configuration.
Prerequisites
What you need before integrating Key-Rex into your website.
1. Key-Rex Account
You need a Key-Rex account to get your integration code. Sign up for free - no credit card required.
- Sign in with a compatible Lightning wallet
- Complete the onboarding wizard
- Get your unique Site ID from the dashboard
2. Backend Server
Key-Rex requires a backend server to receive authentication data. You need:
- A server that can receive HTTP POST requests
- Ability to create and manage user sessions
- Database or storage for user records
- CORS configured on your backend to allow requests from your frontend domain (Key-Rex handles its own CORS automatically)
Options: Node.js/Express, Python/Flask, PHP, Ruby on Rails, serverless functions (Vercel, AWS Lambda, etc.), or any backend that can handle HTTP requests.
Note: Key-Rex handles CORS for its own API endpoints automatically. The CORS requirement above is for your own backend endpoint that receives the xpub from your frontend.
3. Website Domain
You need to know the domain(s) where you'll use Key-Rex:
- Production domain (e.g.,
example.com) - Both www and non-www versions if you use both
- Any staging or test domains (or use auto-allowed test domains)
Note: Test domains like localhost and 127.0.0.1 are automatically allowed for development - no need to add them or verify them.
4. Lightning Wallet (For Testing)
To test your integration, you'll need a Lightning wallet:
- Desktop: A browser extension wallet (recommended for WebLN testing)
- Mobile: A mobile Lightning wallet app
- Wallet must support LNURL-auth protocol
Featured Wallets — Coming Soon
Partner wallets will be showcased here
⚠️ Important Requirements
- Your website must have HTTPS in production (required for secure authentication)
- Your backend must be able to handle CORS requests from your frontend domain
- You must be able to modify your website's HTML to add the integration code
Integration Checklist
Use this checklist to ensure your integration is complete and working correctly.
Integration Guide
Detailed step-by-step guide for integrating Key-Rex into your website.
1. Basic HTML Integration
The simplest way to add Key-Rex is to include the script tags in your HTML:
<!DOCTYPE html> <html> <head> <title>My Website</title> </head> <body> <h1>Welcome to My Website</h1> <!-- Your website content --> <!-- Key-Rex Integration --> <script src="https://yourdomain.com/embed?siteId=YOUR_SITE_ID"></script> <!-- Note: KeyRex.init() is optional - script auto-initializes when DOM is ready --> <script>KeyRex.init();</script> </body> </html>
Important: Replace YOUR_SITE_ID with your actual Site ID from your dashboard. The script automatically initializes when the DOM is ready, but including Key-Rex.init() is recommended for explicit control.
2. Set Up Success and Error Callbacks
You need to handle authentication success and errors. Set up callbacks before the script loads:
<!-- Set up callbacks BEFORE loading the script -->
<script>
window.KeyRex = window.KeyRex || {};
window.KeyRex.onSuccess = function(xpub) {
console.log('User authenticated:', xpub);
// Send xpub to your backend
fetch('/api/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ xpub: xpub })
})
.then(response => response.json())
.then(data => {
// Redirect to dashboard or update UI
window.location.href = '/dashboard';
})
.catch(error => {
console.error('Auth error:', error);
});
};
window.KeyRex.onError = function(error) {
console.error('Key-Rex error:', error);
alert('Authentication failed: ' + error.message);
};
</script>
<!-- Then load the Key-Rex script -->
<script src="https://yourdomain.com/embed?siteId=YOUR_SITE_ID"></script>
<script>KeyRex.init();</script>3. Custom Container Placement
By default, the Key-Rex button is appended to the <body>. To place it in a specific location, add an element with id="keyrex-container":
<div id="login-section"> <h2>Sign In</h2> <div id="keyrex-container"></div> <!-- Key-Rex button will appear here --> </div> <script src="https://yourdomain.com/embed?siteId=YOUR_SITE_ID"></script> <script>KeyRex.init();</script>
Framework Examples
Choose your framework below to see a complete integration example. All examples follow the same pattern: set up callbacks, load the script, and handle the xpub in your backend.
React Integration
Example of integrating Key-Rex into a React application.
import { useEffect } from 'react';
function LoginPage() {
useEffect(() => {
// Set up callbacks
window.KeyRex = window.KeyRex || {};
window.KeyRex.onSuccess = function(xpub) {
console.log('User authenticated:', xpub);
// Handle authentication
fetch('/api/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ xpub: xpub })
})
.then(response => response.json())
.then(data => {
window.location.href = '/dashboard';
});
};
window.KeyRex.onError = function(error) {
console.error('Auth error:', error);
};
// Load Key-Rex script
const script = document.createElement('script');
script.src = 'https://yourdomain.com/embed?siteId=YOUR_SITE_ID';
script.async = true;
// Script auto-initializes when loaded
document.body.appendChild(script);
return () => {
// Cleanup
if (document.body.contains(script)) {
document.body.removeChild(script);
}
};
}, []);
return (
<div>
<h1>Login Page</h1>
<div id="keyrex-container"></div>
</div>
);
}
export default LoginPage;Vue Integration
Example of integrating Key-Rex into a Vue application.
<template>
<div>
<h1>Login Page</h1>
<div id="keyrex-container"></div>
</div>
</template>
<script setup>
import { onMounted, onUnmounted } from 'vue';
onMounted(() => {
// Set up callbacks
window.KeyRex = window.KeyRex || {};
window.KeyRex.onSuccess = function(xpub) {
console.log('User authenticated:', xpub);
// Handle authentication
fetch('/api/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ xpub: xpub })
})
.then(response => response.json())
.then(data => {
window.location.href = '/dashboard';
});
};
window.KeyRex.onError = function(error) {
console.error('Auth error:', error);
};
// Load Key-Rex script
const script = document.createElement('script');
script.src = 'https://yourdomain.com/embed?siteId=YOUR_SITE_ID';
script.async = true;
// Script auto-initializes when loaded
document.body.appendChild(script);
});
onUnmounted(() => {
// Cleanup
const scripts = document.querySelectorAll('script[src*="embed"]');
scripts.forEach(script => script.remove());
});
</script>Next.js Integration
Example of integrating Key-Rex into a Next.js application (App Router).
'use client';
import { useEffect } from 'react';
export default function LoginPage() {
useEffect(() => {
// Set up callbacks
window.KeyRex = window.KeyRex || {};
window.KeyRex.onSuccess = function(xpub) {
console.log('User authenticated:', xpub);
// Handle authentication
fetch('/api/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ xpub: xpub })
})
.then(response => response.json())
.then(data => {
window.location.href = '/dashboard';
});
};
window.KeyRex.onError = function(error) {
console.error('Auth error:', error);
};
// Load Key-Rex script
const script = document.createElement('script');
script.src = 'https://yourdomain.com/embed?siteId=YOUR_SITE_ID';
script.async = true;
// Script auto-initializes when loaded
document.body.appendChild(script);
return () => {
// Cleanup
if (document.body.contains(script)) {
document.body.removeChild(script);
}
};
}, []);
return (
<div>
<h1>Login Page</h1>
<div id="keyrex-container"></div>
</div>
);
}Plain HTML Integration
Simple HTML example for static websites or basic integrations.
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Welcome</h1>
<!-- Set up callbacks BEFORE loading script -->
<script>
window.KeyRex = window.KeyRex || {};
window.KeyRex.onSuccess = function(xpub) {
console.log('User authenticated:', xpub);
// Send to your backend
fetch('/api/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ xpub: xpub })
})
.then(response => response.json())
.then(data => {
window.location.href = '/dashboard';
});
};
window.KeyRex.onError = function(error) {
console.error('Auth error:', error);
alert('Authentication failed');
};
</script>
<!-- Load Key-Rex script -->
<script src="https://yourdomain.com/embed?siteId=YOUR_SITE_ID"></script>
<!-- Note: KeyRex.init() is optional - script auto-initializes when DOM is ready -->
<script>KeyRex.init();</script>
<!-- Optional: Place button in specific location -->
<div id="keyrex-container"></div>
</body>
</html>Backend Integration
Your backend needs to receive the xpub and create a user session. Here are examples for common backend frameworks.
Node.js/Express Example
const express = require('express');
const session = require('express-session');
const app = express();
app.use(express.json());
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: false,
cookie: { secure: true, httpOnly: true }
}));
// Handle Key-Rex authentication callback
app.post('/api/auth/callback', (req, res) => {
const { xpub } = req.body;
if (!xpub) {
return res.status(400).json({ error: 'Missing xpub' });
}
// Find or create user by xpub
// In a real app, you'd query your database
let user = findUserByXpub(xpub);
if (!user) {
// Create new user
user = createUser(xpub);
}
// Create session
req.session.userId = user.id;
req.session.xpub = xpub;
res.json({
success: true,
user: { id: user.id, xpub: xpub }
});
});
function findUserByXpub(xpub) {
// Query your database
// Return user object or null
}
function createUser(xpub) {
// Create new user in database
// Return user object
}Python/Flask Example
from flask import Flask, request, jsonify, session
from flask_session import Session
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SESSION_TYPE'] = 'filesystem'
Session(app)
@app.route('/api/auth/callback', methods=['POST'])
def auth_callback():
data = request.json
xpub = data.get('xpub')
if not xpub:
return jsonify({'error': 'Missing xpub'}), 400
# Find or create user by xpub
user = find_user_by_xpub(xpub)
if not user:
user = create_user(xpub)
# Create session
session['user_id'] = user['id']
session['xpub'] = xpub
return jsonify({
'success': True,
'user': {'id': user['id'], 'xpub': xpub}
})
def find_user_by_xpub(xpub):
# Query your database
# Return user dict or None
pass
def create_user(xpub):
# Create new user in database
# Return user dict
passDatabase Schema Example
Here's a simple database schema for storing users:
-- Users table CREATE TABLE users ( id SERIAL PRIMARY KEY, xpub VARCHAR(255) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP ); -- Sessions table (if using database sessions) CREATE TABLE sessions ( id VARCHAR(255) PRIMARY KEY, user_id INTEGER REFERENCES users(id), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP );
How Authentication Works
Understanding how Key-Rex authentication works helps you integrate it correctly. This section explains the technical flow - you can skip it if you just want to get started.
WebLN (Browser Extension) Flow
- User clicks Key-Rex button on your website
- Script detects WebLN extension in browser
- Extension prompts user to approve sign-in request
- User approves in extension
- Extension returns signature directly to script
- Script calls your
Key-Rex.onSuccess(xpub)callback - Your code receives xpub and creates user session
Best UX: This is the fastest flow - one click, instant authentication. Works on desktop browsers with WebLN extensions.
QR Code Flow (Desktop Popup)
- User clicks Key-Rex button on your website
- No WebLN detected - script opens popup window with QR code
- User scans QR code with mobile Lightning wallet
- Wallet authenticates and calls Key-Rex callback server
- Popup detects authentication via polling
- Popup sends xpub to main window via postMessage
- Script calls your
Key-Rex.onSuccess(xpub)callback - Your code receives xpub and creates user session
Note: If popup is blocked, script automatically falls back to full-page redirect (same as mobile flow).
QR Code Flow (Mobile Redirect)
- User clicks Key-Rex button on mobile device
- Script detects mobile device and uses full-page redirect
- Page redirects to Key-Rex QR code page
- User scans QR code with another device or switches to wallet app
- Wallet authenticates and calls Key-Rex callback server
- QR page detects authentication and redirects back to your site
- Redirect includes xpub in URL parameter:
?xpub=... - Script detects xpub in URL and calls your
Key-Rex.onSuccess(xpub)callback - URL parameter is automatically cleaned up
- Your code receives xpub and creates user session
API Reference
Complete reference for the Key-Rex JavaScript API.
Key-Rex.init()
Description: Initializes the Key-Rex button. The script automatically calls this when the DOM is ready, but you can call it manually if needed.
Note: This is optional - the script auto-initializes when the DOM is ready. Including it explicitly doesn't hurt and can be useful for explicit control.
// Auto-initialization (recommended) <script src="https://yourdomain.com/embed?siteId=YOUR_SITE_ID"></script> // Script auto-initializes when DOM is ready // Manual initialization (optional) KeyRex.init();
Key-Rex.onSuccess(xpub)
Description: Callback function called when authentication succeeds. Receives the user's xpub (extended public key) as a parameter.
window.KeyRex.onSuccess = function(xpub) {
console.log('User authenticated:', xpub);
// Send xpub to your backend
fetch('/api/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ xpub: xpub })
})
.then(response => response.json())
.then(data => {
// Handle successful authentication
window.location.href = '/dashboard';
});
};Key-Rex.onError(error)
Description: Callback function called when authentication fails or an error occurs.
window.KeyRex.onError = function(error) {
console.error('Key-Rex error:', error);
// Handle error (show message to user, etc.)
alert('Authentication failed: ' + error.message);
};Configuration
Key-Rex configuration is managed server-side through your dashboard. Most settings are standardized for consistency.
Server-Managed Configuration
The following settings are managed in your dashboard and fetched automatically:
- Button Text: Standardized to "Sign in with Key-Rex"
- Footer Text: Standardized branding
- Featured Wallets: Partner wallet list (managed by admin)
- Integration Toggle: Enable/disable authentication across all domains
Note: These settings are standardized to ensure consistent user experience. If you need custom branding, contact support for enterprise options.
Container Placement
Control where the Key-Rex button appears by using a container element:
<!-- Button will appear in this container --> <div id="keyrex-container"></div> <!-- If no container found, button is appended to <body> --> <script src="https://yourdomain.com/embed?siteId=YOUR_SITE_ID"></script> <script>KeyRex.init();</script>
Best Practices
Follow these best practices for a secure and reliable integration.
Security
- Always validate xpub on your backend - never trust client-side data alone
- Use HTTPS for all authentication requests
- Implement proper session management with secure, HTTP-only cookies
- Never store sensitive data using only xpub as identifier - use proper user IDs
User Experience
- Set up callbacks before loading the script to avoid race conditions
- Provide clear error messages if authentication fails
- Test on both desktop and mobile devices
- Handle both WebLN and QR code flows gracefully
Performance
- Load the script asynchronously to avoid blocking page render
- Only include the script on pages that need authentication
- Use container placement for better control over button location
Testing & Debugging
Tips for testing your Key-Rex integration and debugging common issues.
Browser Console Commands
Open browser Developer Tools (F12) and use these commands:
// Check if KeyRex is loaded
KeyRex
// Check if button exists
document.getElementById('keyrex-button')
// Check for xpub in URL
new URLSearchParams(window.location.search).get('xpub')
// Check for cookies (Note: Key-Rex cookies are httpOnly and won't appear here)
// Use DevTools → Application → Cookies to view httpOnly cookies
document.cookie.split(';').filter(c => c.includes('keyrex'))
// Test popup blocking
window.open('about:blank', 'test', 'width=100,height=100')Common Issues
- Button doesn't appear: Check browser console for errors, verify script loads in Network tab
- Domain not authorized: Add your domain in the dashboard Domains tab and verify it via DNS TXT record
- onSuccess not called: Verify callback is set before script loads
- CORS errors: Configure your backend to allow requests from your frontend domain
Testing Checklist
- Test on desktop browser with a WebLN extension
- Test on desktop browser without WebLN (should show QR popup)
- Test on mobile device (should redirect to QR page)
- Test with popup blocker enabled (should fallback to redirect)
- Verify xpub is received in onSuccess callback
- Verify backend receives xpub and creates session
- Test session persistence across page reloads
Error Handling
How to handle errors and provide good user experience when authentication fails.
Setting Up Error Callbacks
Always set up an error callback to handle authentication failures gracefully:
window.KeyRex.onError = function(error) {
console.error('Key-Rex error:', error);
// Handle specific error types
if (error.message.includes('Invalid siteId')) {
// Site ID is wrong - show message to developer
console.error('Check your siteId in the integration code');
} else if (error.message.includes('domain is not authorized') || error.message.includes('not authorized — add it')) {
// Domain not added - show user-friendly message
alert('This website is not configured for authentication. Please contact the website owner.');
} else if (error.message.includes('disabled')) {
// Integration disabled
alert('Authentication is currently disabled. Please try again later.');
} else if (error.message.includes('timed out')) {
// Authentication timeout
alert('Authentication timed out. Please try again.');
} else {
// Generic error
alert('Authentication failed. Please try again or contact support.');
}
};Common Error Messages
"Invalid siteId"
Cause: Site ID in integration code is incorrect
Fix: Copy the exact code from your dashboard
"This domain is not authorized — add it in your dashboard"
Cause: Domain not added to dashboard or not verified
Fix: Add your domain in the Domains tab and verify it via DNS TXT record
"Integration is disabled"
Cause: Integration toggle is off
Fix: Enable integration in dashboard
"Failed to load configuration"
Cause: Config API request failed
Fix: Check network connection and try again
"Authentication timed out"
Cause: User took too long or wallet didn't respond
Fix: Try authenticating again
"Invalid signature"
Cause: Wallet signature verification failed
Fix: Try a different wallet or restart current wallet
User-Friendly Error Messages
Show user-friendly messages instead of technical errors:
window.KeyRex.onError = function(error) {
// Map technical errors to user-friendly messages
const userMessages = {
'Invalid siteId': 'This website is not properly configured. Please contact support.',
'domain is not authorized': 'This website is not authorized for authentication. Please contact the website owner.',
'not authorized — add it': 'This website is not authorized for authentication. Please contact the website owner.',
'disabled': 'Authentication is temporarily unavailable. Please try again later.',
'timed out': 'Authentication took too long. Please try again.',
'Invalid signature': 'Authentication failed. Please try again with your wallet.',
};
// Find matching message or use generic
let message = 'Authentication failed. Please try again.';
for (const [key, value] of Object.entries(userMessages)) {
if (error.message.includes(key)) {
message = value;
break;
}
}
// Show to user (customize based on your UI)
showNotification(message, 'error');
};Advanced Features
Advanced features and customization options.
postMessage API
On desktop, the popup window communicates with the main window using postMessage. You can listen for these messages:
window.addEventListener('message', function(event) {
if (event.data && event.data.type === 'keyrex-auth-success') {
const xpub = event.data.xpub;
// Handle authentication
} else if (event.data && event.data.type === 'keyrex-auth-error') {
const error = event.data.error;
// Handle error
} else if (event.data && event.data.type === 'keyrex-popup-closed') {
// User closed the popup without completing authentication
}
});xpub Retrieval Methods
The xpub can be delivered in multiple ways:
- URL Parameters: Mobile/redirect flow includes
?xpub=...in URL - postMessage: Desktop popup sends xpub via postMessage
- Cookies: Fallback method using cookies (automatically cleaned up)
The Key-Rex script handles all these methods automatically and calls your onSuccess callback with the xpub.
Account Linking & User Management
How to link Key-Rex authentication to existing user accounts.
Linking to Existing Accounts
If you already have user accounts, you can link Key-Rex authentication to them:
- User signs in with existing method (email/password, etc.)
- User clicks "Link Lightning Wallet" button
- User authenticates with Key-Rex
- Store xpub in user's account record
- Future sign-ins can use either method
Creating New Accounts
For new users signing in with Key-Rex:
- User clicks Key-Rex button and authenticates
- Your backend receives xpub
- Check if user exists by xpub
- If not, create new user account with xpub
- Create session and redirect to dashboard
Common Use Cases
Examples of how Key-Rex can be used in different scenarios.
Standalone Authentication
Use Key-Rex as the only authentication method. Users sign in exclusively with Lightning wallets.
Alternative Authentication
Offer Key-Rex alongside traditional authentication (email/password). Users can choose their preferred method.
Account Linking
Allow existing users to link their Lightning wallet to their account for faster future sign-ins.
Frequently Asked Questions
Common questions about Key-Rex integration.
Do I need to call Key-Rex.init()?
No, it's optional. The script automatically initializes when the DOM is ready. However, including it explicitly is recommended for better control and compatibility with some frameworks.
Can I customize the button appearance?
The button appearance is standardized for consistency. If you need custom branding, contact support for enterprise options.
What if a user doesn't have a Lightning wallet?
Users need a Lightning wallet to use Key-Rex. You can provide links to download compatible wallets or offer alternative authentication methods alongside Key-Rex.
Is the xpub unique per user?
Yes, each Lightning wallet has a unique xpub. You can use it as a user identifier, but it's recommended to create your own user IDs and store the xpub as a linked identifier.
Quick Reference
Quick reference guide for common tasks.
Basic Integration
<script src="https://yourdomain.com/embed?siteId=YOUR_SITE_ID"></script> <script>KeyRex.init();</script>
With Callbacks
window.KeyRex.onSuccess = (xpub) => {
// Handle success
};
window.KeyRex.onError = (error) => {
// Handle error
};Container Placement
<div id="keyrex-container"></div>
Backend Endpoint
POST /api/auth/callback
Body: { xpub: "xpub_..." }Ready to Get Started?
Sign in with your Lightning wallet and complete the setup wizard to get your integration code and access your personalized dashboard.
Get Your Integration Code