Skip to main content
This guide walks you through integrating the Devdraft SDK into your application. You’ll learn how to configure the SDK, initiate transfers (both bank and wallet), and set up webhooks to receive real-time transaction updates.

Overview

The Devdraft SDK provides a unified interface to:

Bank Transfers

Initiate fiat-to-crypto transfers from external bank accounts

Wallet Transfers

Create blockchain-to-blockchain transfers from external wallets

Webhooks

Receive real-time notifications for transfer status updates

Multi-Language Support

Available in TypeScript, Python, Go, Java, PHP, Ruby, and C#

Installation

npm install @devdraft/sdk
# or
yarn add @devdraft/sdk

Configuration

Before making API calls, configure the SDK with your API credentials. You can obtain your x-client-key and x-client-secret from the Devdraft Console.
import { Configuration, TransfersApi, WebhooksApi } from 'devdraft';

const configuration = new Configuration({
  basePath: 'https://api.devdraft.ai',
  apiKey: (name: string) => {
    const keys: Record<string, string> = {
      'x-client-key': process.env.DEVDRAFT_CLIENT_KEY || 'your-client-key',
      'x-client-secret': process.env.DEVDRAFT_CLIENT_SECRET || 'your-client-secret'
    };
    return keys[name];
  }
});

const transfersApi = new TransfersApi(configuration);
const webhooksApi = new WebhooksApi(configuration);
Never hardcode your API credentials in production code. Always use environment variables or a secure secrets manager.

Direct Bank Transfer

Create a bank-to-wallet transfer where funds come from an external bank account and are deposited into your Devdraft wallet. This is useful for accepting traditional fiat payments.

Parameters

ParameterTypeRequiredDescription
walletIdstringYesYour Devdraft wallet ID to receive the transfer
paymentRailstringYesPayment method: wire, ach, sepa, spei
sourceCurrencystringYesSource fiat currency: usd, eur, mxn
destinationCurrencystringYesDestination currency in your wallet
amountnumberYesAmount to transfer
import { TransfersApi, CreateDirectBankTransferDto } from 'devdraft';

async function createBankTransfer() {
  const transferData: CreateDirectBankTransferDto = {
    walletId: '550e8400-e29b-41d4-a716-446655440000',
    paymentRail: 'wire',
    sourceCurrency: 'usd',
    destinationCurrency: 'usdc',
    amount: 1000.50
  };

  try {
    await transfersApi.transferControllerCreateDirectBankTransfer({
      createDirectBankTransferDto: transferData
    });
    console.log('Bank transfer initiated successfully');
  } catch (error) {
    console.error('Transfer failed:', error);
  }
}

Direct Wallet Transfer

Create a blockchain-to-blockchain transfer where funds come from an external wallet and are deposited into your Devdraft wallet. This is ideal for accepting cryptocurrency payments.

Parameters

ParameterTypeRequiredDescription
walletIdstringYesYour Devdraft wallet ID to receive the transfer
networkstringYesBlockchain network: solana, ethereum, base, etc.
stableCoinCurrencystringYesStablecoin: usdc, eurc
amountnumberYesAmount to transfer

Supported Networks

  • Solana (solana)
  • Ethereum (ethereum)
  • Base (base)
  • Polygon (polygon)
  • Arbitrum (arbitrum)
  • Optimism (optimism)
  • Avalanche C-Chain (avalanche_c_chain)
import { TransfersApi, CreateDirectWalletTransferDto } from 'devdraft';

async function createWalletTransfer() {
  const transferData: CreateDirectWalletTransferDto = {
    walletId: '550e8400-e29b-41d4-a716-446655440000',
    network: 'solana',
    stableCoinCurrency: 'usdc',
    amount: 500.00
  };

  try {
    await transfersApi.transferControllerCreateDirectWalletTransfer({
      createDirectWalletTransferDto: transferData
    });
    console.log('Wallet transfer initiated successfully');
  } catch (error) {
    console.error('Transfer failed:', error);
  }
}

Webhook Integration

Webhooks allow you to receive real-time notifications when transfer statuses change. This is the recommended approach for tracking transaction progress.

Transfer Events

EventDescription
transfer.initiatedTransfer process has started
transfer.pendingTransfer is being processed
transfer.completedTransfer completed successfully
transfer.failedTransfer processing failed
transfer.refundedFailed transfer was refunded

Create a Webhook

import { WebhooksApi, CreateWebhookDto } from 'devdraft';

async function createTransferWebhook() {
  const webhookData: CreateWebhookDto = {
    url: 'https://your-app.com/webhooks/transfers',
    name: 'Transfer Notifications',
    isActive: true,
    encrypted: false
  };

  try {
    const webhook = await webhooksApi.webhookControllerCreate({
      createWebhookDto: webhookData
    });
    console.log('Webhook created:', webhook.id);
    console.log('Signing secret:', webhook.signingSecret);
    return webhook;
  } catch (error) {
    console.error('Webhook creation failed:', error);
    throw error;
  }
}

List Webhooks

Retrieve all webhooks registered for your application:
async function listWebhooks() {
  try {
    const webhooks = await webhooksApi.webhookControllerFindAll({});
    console.log(`Found ${webhooks.length} webhooks`);
    
    webhooks.forEach(webhook => {
      console.log(`- ${webhook.name}: ${webhook.url} (${webhook.isActive ? 'active' : 'inactive'})`);
    });
    
    return webhooks;
  } catch (error) {
    console.error('Failed to list webhooks:', error);
    throw error;
  }
}

Handling Webhook Events

When your webhook endpoint receives an event, verify the signature and process the event:
import crypto from 'crypto';
import express from 'express';

const app = express();

app.post('/webhooks/transfers', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-webhook-signature'] as string;
  const payload = req.body.toString();
  
  // Verify signature
  const expectedSignature = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET!)
    .update(payload)
    .digest('hex');
  
  if (!crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expectedSignature}`)
  )) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(payload);
  
  // Handle transfer events
  switch (event.type) {
    case 'transfer.completed':
      console.log('Transfer completed:', event.data.object.id);
      // Update your database, notify user, etc.
      break;
    case 'transfer.failed':
      console.log('Transfer failed:', event.data.object.id);
      // Handle failure, notify user, etc.
      break;
    case 'transfer.pending':
      console.log('Transfer pending:', event.data.object.id);
      break;
  }
  
  res.status(200).send('OK');
});

Complete Integration Example

Here’s a real-world example that demonstrates the complete flow:
  1. Configure the SDK with your API URL and credentials
  2. Retrieve your wallets from the API
  3. Use a wallet ID from the response to initiate a transfer
  4. Set up a webhook to receive real-time transfer status updates
This example shows how to use actual data from API responses in subsequent calls:
import { Configuration, TransfersApi, WebhooksApi, WalletsApi } from 'devdraft';

async function realWorldExample() {
  // Step 1: Configure the SDK with API URL and credentials
  const configuration = new Configuration({
    basePath: 'https://api.devdraft.ai', // API base URL
    apiKey: (name: string) => {
      const keys: Record<string, string> = {
        'x-client-key': process.env.DEVDRAFT_CLIENT_KEY!,
        'x-client-secret': process.env.DEVDRAFT_CLIENT_SECRET!
      };
      return keys[name];
    }
  });

  const transfersApi = new TransfersApi(configuration);
  const webhooksApi = new WebhooksApi(configuration);
  const walletsApi = new WalletsApi(configuration);

  try {
    // Step 2: Get your wallets from the API
    console.log('Fetching your wallets...');
    const walletsResponse = await walletsApi.walletControllerGetWallets();
    
    // In a real implementation, the API would return wallet data
    // For this example, we'll use the first wallet from your account
    const firstWalletId = '550e8400-e29b-41d4-a716-446655440000'; // From API response
    console.log(`Using wallet: ${firstWalletId}`);

    // Step 3: Set up webhook to receive transfer events
    console.log('Creating webhook for transfer notifications...');
    const webhook = await webhooksApi.webhookControllerCreate({
      createWebhookDto: {
        url: 'https://your-app.com/webhooks/transfers',
        name: 'Transfer Status Updates',
        isActive: true
      }
    });
    console.log(`✓ Webhook created: ${webhook.id}`);
    console.log(`  Signing secret: ${webhook.signingSecret}`);

    // Step 4: Initiate a direct wallet transfer using the wallet from Step 2
    console.log('Initiating transfer...');
    await transfersApi.transferControllerCreateDirectWalletTransfer({
      createDirectWalletTransferDto: {
        walletId: firstWalletId, // Using the wallet ID from API
        network: 'solana',
        stableCoinCurrency: 'usdc',
        amount: 100.00
      }
    });
    console.log('✓ Transfer initiated successfully!');
    console.log('  Your webhook will receive status updates at:');
    console.log(`  ${webhook.url}`);
    
    // Alternative: Bank transfer example
    // await transfersApi.transferControllerCreateDirectBankTransfer({
    //   createDirectBankTransferDto: {
    //     walletId: firstWalletId,
    //     paymentRail: 'wire',
    //     sourceCurrency: 'usd',
    //     destinationCurrency: 'usdc',
    //     amount: 1000.00
    //   }
    // });

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

realWorldExample().catch(console.error);

Error Handling

All SDK methods may throw exceptions. Here are common error scenarios and how to handle them:
HTTP CodeError TypeDescription
400Bad RequestInvalid request parameters
401UnauthorizedInvalid or missing API credentials
403ForbiddenInsufficient permissions
404Not FoundResource not found
422UnprocessableBusiness logic validation failed
429Rate LimitedToo many requests
import { ResponseError } from 'devdraft';

try {
  await transfersApi.transferControllerCreateDirectBankTransfer({
    createDirectBankTransferDto: transferData
  });
} catch (error) {
  if (error instanceof ResponseError) {
    const status = error.response.status;
    const body = await error.response.json();
    
    switch (status) {
      case 400:
        console.error('Invalid request:', body.message);
        break;
      case 401:
        console.error('Authentication failed - check your API credentials');
        break;
      case 404:
        console.error('Wallet not found:', body.message);
        break;
      case 422:
        console.error('Validation error:', body.message);
        break;
      case 429:
        console.error('Rate limited - retry after:', error.response.headers.get('retry-after'));
        break;
      default:
        console.error('API error:', status, body);
    }
  }
}
from devdraft.rest import ApiException

try:
    transfers_api.transfer_controller_create_direct_bank_transfer(transfer_data)
except ApiException as e:
    if e.status == 400:
        print(f'Invalid request: {e.body}')
    elif e.status == 401:
        print('Authentication failed - check your API credentials')
    elif e.status == 404:
        print(f'Wallet not found: {e.body}')
    elif e.status == 422:
        print(f'Validation error: {e.body}')
    elif e.status == 429:
        print(f'Rate limited - retry after: {e.headers.get("retry-after")}')
    else:
        print(f'API error: {e.status} - {e.body}')
_, httpRes, err := apiClient.TransfersAPI.TransferControllerCreateDirectBankTransfer(ctx).
    CreateDirectBankTransferDto(*transferData).
    Execute()

if err != nil {
    if httpRes != nil {
        switch httpRes.StatusCode {
        case 400:
            fmt.Println("Invalid request")
        case 401:
            fmt.Println("Authentication failed - check your API credentials")
        case 404:
            fmt.Println("Wallet not found")
        case 422:
            fmt.Println("Validation error")
        case 429:
            retryAfter := httpRes.Header.Get("Retry-After")
            fmt.Printf("Rate limited - retry after: %s\n", retryAfter)
        default:
            fmt.Printf("API error: %d\n", httpRes.StatusCode)
        }
    }
}
import org.openapitools.client.ApiException;

try {
    transfersApi.transferControllerCreateDirectBankTransfer(transferData);
} catch (ApiException e) {
    int statusCode = e.getCode();
    String responseBody = e.getResponseBody();
    
    switch (statusCode) {
        case 400:
            System.err.println("Invalid request: " + responseBody);
            break;
        case 401:
            System.err.println("Authentication failed - check your API credentials");
            break;
        case 404:
            System.err.println("Wallet not found: " + responseBody);
            break;
        case 422:
            System.err.println("Validation error: " + responseBody);
            break;
        case 429:
            String retryAfter = e.getResponseHeaders().get("Retry-After").get(0);
            System.err.println("Rate limited - retry after: " + retryAfter);
            break;
        default:
            System.err.println("API error: " + statusCode + " - " + responseBody);
    }
}
use Devdraft\ApiException;

try {
    $transfersApi->transferControllerCreateDirectBankTransfer($transferData);
} catch (ApiException $e) {
    $statusCode = $e->getCode();
    $responseBody = $e->getResponseBody();
    
    switch ($statusCode) {
        case 400:
            echo "Invalid request: " . $responseBody . "\n";
            break;
        case 401:
            echo "Authentication failed - check your API credentials\n";
            break;
        case 404:
            echo "Wallet not found: " . $responseBody . "\n";
            break;
        case 422:
            echo "Validation error: " . $responseBody . "\n";
            break;
        case 429:
            $retryAfter = $e->getResponseHeaders()['Retry-After'][0] ?? 'unknown';
            echo "Rate limited - retry after: " . $retryAfter . "\n";
            break;
        default:
            echo "API error: " . $statusCode . " - " . $responseBody . "\n";
    }
}
begin
  transfers_api.transfer_controller_create_direct_bank_transfer(transfer_data)
rescue Devdraft::ApiError => e
  status_code = e.code
  response_body = e.response_body
  
  case status_code
  when 400
    puts "Invalid request: #{response_body}"
  when 401
    puts 'Authentication failed - check your API credentials'
  when 404
    puts "Wallet not found: #{response_body}"
  when 422
    puts "Validation error: #{response_body}"
  when 429
    retry_after = e.response_headers['Retry-After']
    puts "Rate limited - retry after: #{retry_after}"
  else
    puts "API error: #{status_code} - #{response_body}"
  end
end
using Devdraft.Client;

try
{
    await transfersApi.TransferControllerCreateDirectBankTransferAsync(transferData);
}
catch (ApiException e)
{
    int statusCode = e.ErrorCode;
    string responseBody = e.Message;
    
    switch (statusCode)
    {
        case 400:
            Console.WriteLine($"Invalid request: {responseBody}");
            break;
        case 401:
            Console.WriteLine("Authentication failed - check your API credentials");
            break;
        case 404:
            Console.WriteLine($"Wallet not found: {responseBody}");
            break;
        case 422:
            Console.WriteLine($"Validation error: {responseBody}");
            break;
        case 429:
            var retryAfter = e.Headers.ContainsKey("Retry-After") 
                ? e.Headers["Retry-After"].ToString() 
                : "unknown";
            Console.WriteLine($"Rate limited - retry after: {retryAfter}");
            break;
        default:
            Console.WriteLine($"API error: {statusCode} - {responseBody}");
            break;
    }
}

Best Practices

1

Secure Your Credentials

Always use environment variables or a secrets manager for API credentials. Never commit credentials to version control.
2

Implement Webhook Signature Verification

Always verify webhook signatures to ensure events are legitimately from Devdraft and haven’t been tampered with.
3

Handle Errors Gracefully

Implement proper error handling with retry logic for transient failures (5xx errors, rate limits).
4

Use Idempotency

For critical operations, implement idempotency to prevent duplicate transfers in case of network issues.
5

Process Webhooks Asynchronously

Return HTTP 200 quickly from your webhook endpoint and process events asynchronously to avoid timeouts.

Next Steps

Direct Bank Transfer

Learn more about bank transfer options and configurations

Direct Wallet Transfer

Explore wallet transfer networks and currencies

Webhooks Overview

Deep dive into webhook events and security

API Reference

Complete API documentation for all endpoints