Node.js SDK Guide
Official SDK Installation
We provide official SDK packages for Node.js and TypeScript that you can install directly from npm:
Node.js SDK
bash
npm install @keyclaim/sdk
# or
yarn add @keyclaim/sdkTypeScript SDK
bash
npm install @keyclaim/sdk-typescript
# or
yarn add @keyclaim/sdk-typescriptQuick Start with Official SDK
Node.js
javascript
const { KeyClaimClient } = require('@keyclaim/sdk');
// Initialize client (base URL is automatically set to https://keyclaim.org)
const client = new KeyClaimClient({
apiKey: 'kc_your_api_key_here',
secret: 'your-secret-key' // Optional, defaults to API key
});
// Complete validation flow
async function main() {
try {
// Create challenge, generate response, and validate in one call
const result = await client.validate('hmac', 30);
if (result.valid) {
console.log('✓ Validation successful!');
console.log('Signature:', result.signature);
console.log('Quota:', result.quota);
} else {
console.log('✗ Validation failed:', result.error);
}
} catch (error) {
console.error('Error:', error.message);
}
}
main();TypeScript
typescript
import { KeyClaimClient } from '@keyclaim/sdk-typescript';
// Initialize client (base URL is automatically set to https://keyclaim.org)
const client = new KeyClaimClient({
apiKey: 'kc_your_api_key_here',
secret: 'your-secret-key' // Optional, defaults to API key
});
// Complete validation flow
async function main() {
try {
// Create challenge, generate response, and validate in one call
const result = await client.validate('hmac', 30);
if (result.valid) {
console.log('✓ Validation successful!');
console.log('Signature:', result.signature);
console.log('Quota:', result.quota);
} else {
console.log('✗ Validation failed:', result.error);
}
} catch (error) {
console.error('Error:', error.message);
}
}
main();Step-by-Step Usage with Official SDK
javascript
const { KeyClaimClient } = require('@keyclaim/sdk');
const client = new KeyClaimClient({
apiKey: 'kc_your_api_key_here',
secret: 'your-secret-key'
});
// Step 1: Create a challenge
const { challenge, expires_in } = await client.createChallenge({ ttl: 30 });
console.log('Challenge:', challenge);
// Step 2: Generate response (using HMAC)
const response = client.generateResponse(challenge, 'hmac');
console.log('Response:', response);
// Step 3: Validate the challenge-response pair
const result = await client.validateChallenge({
challenge: challenge,
response: response
});
if (result.valid) {
console.log('✓ Challenge validated successfully!');
if (result.signature) {
console.log('Signature:', result.signature);
}
if (result.quota) {
console.log('Quota:', result.quota.used, '/', result.quota.quota);
}
} else {
console.log('✗ Validation failed:', result.error);
}Response Methods
The official SDK supports multiple response generation methods:
javascript
// Echo (testing only)
const echoResponse = client.generateResponse(challenge, 'echo');
// HMAC-SHA256 (recommended for production)
const hmacResponse = client.generateResponse(challenge, 'hmac');
// SHA256 Hash
const hashResponse = client.generateResponse(challenge, 'hash');
// Custom (with custom data)
const customResponse = client.generateResponse(challenge, 'custom', {
userId: '123',
timestamp: Date.now()
});Error Handling
javascript
const { KeyClaimClient, KeyClaimError } = require('@keyclaim/sdk');
try {
const result = await client.validate();
} catch (error) {
if (error instanceof KeyClaimError) {
console.error('KeyClaim Error:', error.message);
console.error('Code:', error.code);
console.error('Status:', error.statusCode);
} else {
console.error('Unknown error:', error);
}
}Package Links
- •Node.js SDK: [@keyclaim/sdk on npm](https://www.npmjs.com/package/@keyclaim/sdk)
- •TypeScript SDK: [@keyclaim/sdk-typescript on npm](https://www.npmjs.com/package/@keyclaim/sdk-typescript)
---
Manual Implementation (Alternative)
If you prefer to implement the API calls manually without the official SDK, you can use the following examples:
Installation
bash
npm install axios
# or
yarn add axiosBasic Usage
javascript
const axios = require('axios');
const API_BASE_URL = 'https://keyclaim.org/api';
const API_KEY = 'kc_your_api_key_here';
// Step 1: Create a challenge
async function createChallenge() {
try {
const response = await axios.post(`${API_BASE_URL}/challenge/create`, {
key: API_KEY,
ttl: 30 // Challenge expires in 30 seconds
});
return response.data.challenge;
} catch (error) {
console.error('Failed to create challenge:', error.response?.data || error.message);
throw error;
}
}
// Step 2: Generate response from challenge
// Option A: Simple echo (for testing)
function generateResponseSimple(challenge) {
return challenge; // Echo the challenge back
}
// Option B: HMAC-based response (recommended for production)
const crypto = require('crypto');
function generateResponseHMAC(challenge, secret) {
// Generate HMAC-SHA256 hash of the challenge
const hmac = crypto.createHmac('sha256', secret);
hmac.update(challenge);
return hmac.digest('hex');
}
// Option C: Custom response generation
function generateResponseCustom(challenge, userData) {
// Your custom logic here
// Example: Combine challenge with user data
const data = `${challenge}:${userData.userId}:${userData.timestamp}`;
return crypto.createHash('sha256').update(data).digest('hex');
}
// Step 3: Validate the response
async function validateChallenge(challenge, response) {
try {
const result = await axios.post(`${API_BASE_URL}/challenge/validate`, {
key: API_KEY,
challenge: challenge,
response: response
});
return result.data;
} catch (error) {
console.error('Validation failed:', error.response?.data || error.message);
return { valid: false, error: error.response?.data?.error };
}
}
// Complete example
async function main() {
try {
// Create challenge
const challenge = await createChallenge();
console.log('Challenge:', challenge);
// Generate response (choose one method)
const secret = 'your-secret-key'; // Use your own secret
const response = generateResponseHMAC(challenge, secret);
// Or use simple echo for testing:
// const response = generateResponseSimple(challenge);
console.log('Response:', response);
// Validate
const result = await validateChallenge(challenge, response);
console.log('Validation result:', result);
if (result.valid) {
console.log('✓ Challenge validated successfully!');
if (result.signature) {
console.log('Signature:', result.signature);
}
} else {
console.log('✗ Validation failed:', result.error);
}
} catch (error) {
console.error('Error:', error);
}
}
main();Error Handling
javascript
async function createChallengeWithRetry(maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await createChallenge();
} catch (error) {
if (error.response?.status === 401) {
throw new Error('Invalid API key');
}
if (error.response?.status === 403) {
throw new Error('Rate limited or security check failed');
}
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}Response Generation Methods
Method 1: Echo (Testing Only)
javascript
function generateResponseEcho(challenge) {
return challenge;
}Method 2: HMAC-SHA256 (Recommended)
javascript
const crypto = require('crypto');
function generateResponseHMAC(challenge, secret) {
return crypto.createHmac('sha256', secret)
.update(challenge)
.digest('hex');
}Method 3: SHA256 Hash
javascript
const crypto = require('crypto');
function generateResponseHash(challenge, salt) {
return crypto.createHash('sha256')
.update(challenge + salt)
.digest('hex');
}Method 4: Custom Algorithm
javascript
function generateResponseCustom(challenge, userId, timestamp) {
const data = `${challenge}:${userId}:${timestamp}`;
return crypto.createHash('sha256').update(data).digest('hex');
}Complete SDK Class
javascript
const axios = require('axios');
const crypto = require('crypto');
class KeyClaimClient {
constructor(apiKey, baseUrl = 'https://keyclaim.org/api', secret = null) {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
this.secret = secret || apiKey; // Use API key as default secret
}
async createChallenge(ttl = 30) {
const response = await axios.post(`${this.baseUrl}/challenge/create`, {
key: this.apiKey,
ttl: ttl
});
return response.data;
}
generateResponse(challenge, method = 'hmac') {
switch (method) {
case 'echo':
return challenge;
case 'hmac':
return crypto.createHmac('sha256', this.secret)
.update(challenge)
.digest('hex');
case 'hash':
return crypto.createHash('sha256')
.update(challenge + this.secret)
.digest('hex');
default:
throw new Error(`Unknown method: ${method}`);
}
}
async validate(challenge, response) {
try {
const result = await axios.post(`${this.baseUrl}/challenge/validate`, {
key: this.apiKey,
challenge: challenge,
response: response
});
return result.data;
} catch (error) {
return {
valid: false,
error: error.response?.data?.error || error.message
};
}
}
async validateChallenge(challenge, method = 'hmac') {
const response = this.generateResponse(challenge, method);
return await this.validate(challenge, response);
}
}
// Usage
const client = new KeyClaimClient('kc_your_api_key', 'https://keyclaim.org/api', 'your-secret');
async function example() {
const { challenge } = await client.createChallenge();
const result = await client.validateChallenge(challenge, 'hmac');
console.log(result);
}Explore Other Documentation
Choose your preferred programming language

Python Documentation
Python 3.7+ integration guide
View Guide→

PHP Documentation
PHP 7.4+ integration guide
View Guide→

Java Documentation
Java 8+ integration guide
View Guide→

Kotlin Documentation
Kotlin/JVM integration guide
View Guide→
C# Documentation
.NET/C# integration guide
View Guide→

Go Documentation
Go 1.18+ integration guide
View Guide→
