Skip to main content

Overview

The KillB JavaScript SDK provides a type-safe, easy-to-use interface for integrating KillB’s crypto on/off-ramp API into your Node.js or TypeScript applications.

Installation

npm install @killb/sdk

Quick Start

Initialize the SDK

import { KillB } from '@killb/sdk';

const killb = new KillB({
  email: process.env.KILLB_EMAIL,
  password: process.env.KILLB_PASSWORD,
  environment: 'sandbox' // or 'production'
});

// SDK handles authentication automatically
await killb.initialize();

Configuration Options

interface KillBConfig {
  email: string;              // Your KillB email
  password: string;           // Your KillB password
  apiKey?: string;           // Optional API key
  environment?: 'sandbox' | 'production'; // Default: 'sandbox'
  timeout?: number;          // Request timeout (ms)
  retries?: number;          // Max retry attempts
  debug?: boolean;           // Enable debug logging
}

Core Features

Users Management

const user = await killb.users.create({
  type: 'PERSON',
  externalId: 'user-12345',
  data: {
    firstName: 'Juan',
    lastName: 'García',
    email: '[email protected]',
    phone: '+573001234567',
    dateOfBirth: '1990-01-01',
    address: {
      street1: 'Calle 123',
      city: 'Bogotá',
      state: 'Cundinamarca',
      zipCode: '110111',
      countryCode: 'CO'
    },
    document: {
      type: 'PASSPORT',
      number: 'AB123456',
      issuedCountryCode: 'CO'
    }
  }
});

console.log('User created:', user.id);
console.log('KYC Level:', user.accessLevel);

Accounts Management

const wallet = await killb.accounts.create({
  type: 'WALLET',
  userId: user.id,
  externalId: 'wallet-polygon-usdc',
  data: {
    firstName: 'Juan',
    lastName: 'García',
    email: '[email protected]',
    phone: '+573001234567',
    currency: 'USDC',
    network: 'POLYGON',
    address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
    countryCode: 'CO',
    document: {
      type: 'PASSPORT',
      number: 'AB123456',
      issuedCountryCode: 'CO'
    }
  }
});

console.log('Wallet created:', wallet.id);

Quotations

const quote = await killb.quotations.create({
  fromCurrency: 'COP',
  toCurrency: 'USDC',
  amount: 100000,
  amountIsToCurrency: false,
  cashInMethod: 'PSE',
  cashOutMethod: 'POLYGON'
});

console.log('Rate:', quote.rate);
console.log('You will receive:', quote.toAmount, 'USDC');
console.log('Expires at:', new Date(quote.expiresAt));

// Check if expired
if (quote.isExpired()) {
  const newQuote = await killb.quotations.create(/* same params */);
}

Ramps

// Complete on-ramp flow
const ramp = await killb.ramps.create({
  quotationId: quote.id,
  userId: user.id,
  accountId: wallet.id,
  externalId: 'onramp-123'
});

console.log('Ramp ID:', ramp.id);
console.log('Status:', ramp.status);
console.log('Payment URL:', ramp.paymentInfo[0].url);

// Redirect user to payment
// window.location.href = ramp.paymentInfo[0].url;

Webhooks

const webhook = await killb.webhooks.create({
  url: 'https://api.yourapp.com/webhooks/killb',
  secret: process.env.WEBHOOK_SECRET,
  events: ['RAMP', 'USER', 'ACCOUNT']
});

console.log('Webhook configured:', webhook.id);

Savings Accounts

const savings = await killb.savings.create({
  userId: user.id,
  acceptedTermsAndConditions: true
});

console.log('Savings account:', savings.id);

Advanced Features

Pagination

// Automatic pagination helper
const allUsers = await killb.users.listAll({
  type: 'PERSON'
});

// Or manual pagination
let page = 1;
let hasMore = true;

while (hasMore) {
  const result = await killb.users.list({ page, limit: 50 });
  processUsers(result.users);
  
  hasMore = page < result.totalPage;
  page++;
}

Error Handling

import { KillBError, QuotationExpiredError, InsufficientBalanceError } from '@killb/sdk';

try {
  const ramp = await killb.ramps.create(rampData);
} catch (error) {
  if (error instanceof QuotationExpiredError) {
    console.log('Quote expired, creating new one...');
    const newQuote = await killb.quotations.create(quoteParams);
    return await killb.ramps.create({ ...rampData, quotationId: newQuote.id });
  }
  
  if (error instanceof InsufficientBalanceError) {
    console.log('Insufficient pre-fund balance');
    await notifyAdminToTopUp();
  }
  
  if (error instanceof KillBError) {
    console.error('KillB API Error:', error.code, error.message);
  }
  
  throw error;
}

Retry Configuration

const killb = new KillB({
  email: process.env.KILLB_EMAIL,
  password: process.env.KILLB_PASSWORD,
  retryConfig: {
    maxRetries: 3,
    retryDelay: 1000,
    retryableStatuses: [500, 502, 503, 504]
  }
});

Custom Headers

// Add custom headers to requests
killb.setHeaders({
  'X-Custom-Header': 'value',
  'X-Request-ID': requestId
});

// Remove custom headers
killb.removeHeaders(['X-Custom-Header']);

Request Logging

const killb = new KillB({
  email: process.env.KILLB_EMAIL,
  password: process.env.KILLB_PASSWORD,
  debug: true,
  logger: {
    log: (message) => console.log('[KillB]', message),
    error: (message) => console.error('[KillB ERROR]', message)
  }
});

Complete Example

import { KillB } from '@killb/sdk';

async function executeOnRamp(
  walletAddress: string,
  amount: number
) {
  // Initialize SDK
  const killb = new KillB({
    email: process.env.KILLB_EMAIL!,
    password: process.env.KILLB_PASSWORD!,
    environment: 'sandbox'
  });

  await killb.initialize();

  try {
    // 1. Create user
    const user = await killb.users.create({
      type: 'PERSON',
      externalId: `user-${Date.now()}`,
      data: {
        firstName: 'Test',
        lastName: 'User',
        email: '[email protected]',
        phone: '+573001234567',
        dateOfBirth: '1990-01-01',
        address: {
          street1: 'Test Street 123',
          city: 'Bogotá',
          state: 'Cundinamarca',
          zipCode: '110111',
          countryCode: 'CO'
        },
        document: {
          type: 'PASSPORT',
          number: 'TEST123',
          issuedCountryCode: 'CO'
        }
      }
    });

    console.log('✅ User created:', user.id);

    // 2. Create wallet account
    const wallet = await killb.accounts.create({
      type: 'WALLET',
      userId: user.id,
      externalId: `wallet-${Date.now()}`,
      data: {
        firstName: 'Test',
        lastName: 'User',
        email: '[email protected]',
        phone: '+573001234567',
        currency: 'USDC',
        network: 'POLYGON',
        address: walletAddress,
        countryCode: 'CO',
        document: {
          type: 'PASSPORT',
          number: 'TEST123',
          issuedCountryCode: 'CO'
        }
      }
    });

    console.log('✅ Wallet created:', wallet.id);

    // 3. Get quotation
    const quote = await killb.quotations.create({
      fromCurrency: 'COP',
      toCurrency: 'USDC',
      amount: amount,
      amountIsToCurrency: false,
      cashInMethod: 'PSE',
      cashOutMethod: 'POLYGON'
    });

    console.log('✅ Quote created:', quote.id);
    console.log('   Rate:', quote.rate);
    console.log('   You will receive:', quote.toAmount, 'USDC');

    // 4. Create ramp
    const ramp = await killb.ramps.create({
      quotationId: quote.id,
      userId: user.id,
      accountId: wallet.id,
      externalId: `onramp-${Date.now()}`
    });

    console.log('✅ Ramp created:', ramp.id);
    console.log('   Payment URL:', ramp.paymentInfo[0].url);

    // 5. In sandbox, simulate payment
    if (killb.environment === 'sandbox') {
      await killb.faker.cashIn(ramp.id);
      console.log('✅ Payment simulated');
    }

    // 6. Wait for completion
    const completed = await ramp.waitForCompletion({
      pollInterval: 5000,
      timeout: 300000
    });

    console.log('✅ Ramp completed!');
    console.log('   Transfer proof:', completed.transferProof);
    
    return completed;

  } catch (error) {
    console.error('❌ Error:', error);
    throw error;
  }
}

// Usage
executeOnRamp('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 100000)
  .then(() => console.log('✅ All done!'))
  .catch(console.error);

TypeScript Support

Full TypeScript definitions included:
import type {
  User,
  CreateUserRequest,
  Account,
  CreateAccountRequest,
  Ramp,
  CreateRampRequest,
  Quotation,
  WebhookEvent
} from '@killb/sdk';

// Type-safe operations
const createUser = async (data: CreateUserRequest): Promise<User> => {
  return await killb.users.create(data);
};

Utilities

Helper Functions

// Validate addresses
import { validateAddress } from '@killb/sdk/utils';

const isValid = validateAddress('0x742d35...', 'POLYGON');
console.log('Valid address:', isValid);

// Format currencies
import { formatCurrency } from '@killb/sdk/utils';

const formatted = formatCurrency(1234.56, 'COP');
console.log(formatted); // "$ 1,234.56 COP"

// Calculate fees
import { calculateFees } from '@killb/sdk/utils';

const fees = calculateFees(quote);
console.log('Platform fee:', fees.platform);
console.log('Network fee:', fees.network);
console.log('Total fee:', fees.total);

Webhook Verification

import { verifyWebhookSignature } from '@killb/sdk';

// Express middleware
const webhookMiddleware = (req, res, next) => {
  const signature = req.headers['x-signature-sha256'];
  const isValid = verifyWebhookSignature(
    JSON.stringify(req.body),
    signature,
    process.env.WEBHOOK_SECRET
  );
  
  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  next();
};

app.post('/webhooks/killb', webhookMiddleware, handleWebhook);

Testing Helpers (Sandbox Only)

// Available in sandbox environment only
if (killb.environment === 'sandbox') {
  // Simulate cash-in
  await killb.faker.cashIn(rampId);
  
  // Simulate cash-out
  await killb.faker.cashOut(rampId);
  
  // Create test user
  const testUser = await killb.faker.createUser();
  
  // Create test wallet
  const testWallet = await killb.faker.createWallet(userId);
}

Best Practices

// Use environment variables for credentials
const killb = new KillB({
  email: process.env.KILLB_EMAIL!,
  password: process.env.KILLB_PASSWORD!,
  apiKey: process.env.KILLB_API_KEY,
  environment: process.env.NODE_ENV === 'production' 
    ? 'production' 
    : 'sandbox'
});
// Always wrap SDK calls in try-catch
try {
  const result = await killb.ramps.create(data);
  return result;
} catch (error) {
  if (error instanceof KillBError) {
    // Handle KillB-specific errors
    logError(error.code, error.message);
  }
  throw error;
}
// Create once, reuse throughout app
export const killb = new KillB(config);

// In other files
import { killb } from './killb-client';
const user = await killb.users.create(data);
// Always provide external IDs for idempotency
const ramp = await killb.ramps.create({
  quotationId: quote.id,
  userId: user.id,
  accountId: wallet.id,
  externalId: `order-${orderId}` // Your system ID
});

API Reference

KillB Client

class KillB {
  constructor(config: KillBConfig)
  
  // Initialize (must be called before using)
  async initialize(): Promise<void>
  
  // Resource managers
  users: UsersManager
  accounts: AccountsManager
  ramps: RampsManager
  quotations: QuotationsManager
  webhooks: WebhooksManager
  savings: SavingsManager
  customers: CustomersManager
  banks: BanksManager
  
  // Sandbox helpers
  faker: FakerManager
  
  // Static utilities
  static verifyWebhookSignature(
    payload: any,
    signature: string,
    secret: string
  ): boolean
}

Resource Managers

Each resource has consistent methods:
interface ResourceManager<T> {
  create(data: CreateRequest): Promise<T>
  get(id: string): Promise<T>
  list(params?: ListParams): Promise<ListResponse<T>>
  update(id: string, data: UpdateRequest): Promise<T>
  delete(id: string): Promise<void>
}

Migration from REST API

Before (REST API)

const response = await fetch('/api/v2/users', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(userData)
});

const user = await response.json();

After (SDK)

const user = await killb.users.create(userData);
Benefits:
  • ✅ No manual auth headers
  • ✅ Automatic token refresh
  • ✅ Type safety
  • ✅ Better error handling
  • ✅ Less boilerplate

Resources

Next Steps