API Documentation Overview
PasskeyMe provides a comprehensive REST API alongside our framework-specific SDKs. This section helps you understand when to use the API directly versus using our SDKs, and provides integration examples for direct API usage.
🔗 Complete API Reference
📖 Full Swagger API Documentation
Our complete API documentation is available as an interactive Swagger interface where you can:
- Browse all available endpoints
- See request/response schemas
- Test API calls directly
- Download OpenAPI specifications
🤔 When to Use API vs SDKs
Use the Direct API When:
- ✅ Building custom integrations for unsupported frameworks
- ✅ Server-side authentication flows
- ✅ Webhook processing and backend integrations
- ✅ Custom token validation logic
- ✅ Building your own SDK for a new platform
Use Framework SDKs When:
- ✅ React applications - use
@passkeyme/react-auth
- ✅ JavaScript/TypeScript apps - use
@passkeyme/auth
- ✅ React Native apps - React Native SDK (coming Q1 2025) - use JavaScript SDK currently
- ✅ Standard authentication flows with built-in UI components
🔐 Authentication Flow via API
1. Configuration Endpoint
GET /api/config?app_id={your_app_id}
Retrieve your application configuration including OAuth providers and settings.
2. OAuth Redirect
GET /oauth/{provider}/authorize?app_id={app_id}&redirect_uri={redirect_uri}
Redirect users to OAuth provider (Google, GitHub, Facebook) for authentication.
3. Token Verification
GET /api/auth/verify-token?token={jwt_token}&app_id={app_id}
Verify JWT tokens received from authentication callbacks.
4. User Information
GET /api/user?token={jwt_token}
Retrieve authenticated user information using a valid JWT token.
🛠️ Integration Examples
Frontend Integration (Vanilla JavaScript)
class PasskeymeApiClient {
constructor(appId, baseUrl = 'https://auth.passkeyme.com') {
this.appId = appId;
this.baseUrl = baseUrl;
}
async getConfig() {
const response = await fetch(
`${this.baseUrl}/api/config?app_id=${this.appId}`
);
return response.json();
}
redirectToOAuth(provider, redirectUri) {
const url = `${this.baseUrl}/oauth/${provider}/authorize?app_id=${this.appId}&redirect_uri=${encodeURIComponent(redirectUri)}`;
window.location.href = url;
}
async verifyToken(token) {
const response = await fetch(
`${this.baseUrl}/api/auth/verify-token?token=${token}&app_id=${this.appId}`
);
return response.json();
}
async getCurrentUser(token) {
const response = await fetch(
`${this.baseUrl}/api/user?token=${token}`
);
return response.json();
}
}
Backend Integration (Node.js)
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
// Middleware to verify PasskeyMe tokens
const verifyPasskeymeToken = async (req, res, next) => {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
try {
// Verify with PasskeyMe API
const response = await fetch(
`https://auth.passkeyme.com/api/auth/verify-token?token=${token}&app_id=${process.env.PASSKEYME_APP_ID}`
);
const result = await response.json();
if (result.valid) {
req.user = result.user;
next();
} else {
res.status(401).json({ error: 'Invalid token' });
}
} catch (error) {
res.status(500).json({ error: 'Token verification failed' });
}
};
// Protected route example
app.get('/api/protected', verifyPasskeymeToken, (req, res) => {
res.json({
message: 'Protected data',
user: req.user
});
});
Python Integration
import requests
import os
from flask import Flask, request, jsonify
app = Flask(__name__)
class PasskeymeClient:
def __init__(self, app_id, base_url="https://auth.passkeyme.com"):
self.app_id = app_id
self.base_url = base_url
def verify_token(self, token):
response = requests.get(
f"{self.base_url}/api/auth/verify-token",
params={"token": token, "app_id": self.app_id}
)
return response.json()
def get_user(self, token):
response = requests.get(
f"{self.base_url}/api/user",
params={"token": token}
)
return response.json()
passkeyme = PasskeymeClient(os.environ['PASSKEYME_APP_ID'])
def require_auth(f):
def decorated_function(*args, **kwargs):
token = request.headers.get('Authorization', '').replace('Bearer ', '')
if not token:
return jsonify({'error': 'No token provided'}), 401
result = passkeyme.verify_token(token)
if not result.get('valid'):
return jsonify({'error': 'Invalid token'}), 401
request.user = result.get('user')
return f(*args, **kwargs)
return decorated_function
@app.route('/api/protected')
@require_auth
def protected():
return jsonify({
'message': 'Protected data',
'user': request.user
})
🔑 Token Management
JWT Token Structure
PasskeyMe returns standard JWT tokens with the following claims:
{
"sub": "user-uuid",
"email": "user@example.com",
"aud": "application-uuid",
"iss": "https://passkeyme.com",
"iat": 1640995200,
"exp": 1640998800,
"user_id": "user-uuid",
"app_id": "application-uuid"
}
Token Verification Best Practices
- Always verify tokens server-side for sensitive operations
- Cache verification results with appropriate TTL
- Handle token expiration gracefully
- Use HTTPS for all API calls
- Store tokens securely in browser (httpOnly cookies recommended)
🔒 Security Considerations
API Key Management
- Store your
app_id
securely - Use environment variables in production
- Rotate credentials regularly
- Monitor API usage for anomalies
Token Handling
- Validate tokens on every protected request
- Implement token refresh logic
- Use short-lived tokens when possible
- Log authentication events for security monitoring
🚀 Next Steps
- Explore the Full API - Browse all endpoints
- Authentication Flows - Complete flow implementations
- Token Management - Security and lifecycle management
- Try our React SDK - For React applications
- Use JavaScript SDK - For other frameworks
💬 Support
- API Questions: GitHub Issues
- Integration Help: Discord Community
- Documentation: docs.passkeyme.com