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
- TypeScript
- Python
- Go
- Java
- PHP
- Ruby
- C#
npm install @devdraft/sdk
# or
yarn add @devdraft/sdk
pip install devdraft
go get github.com/devdraftengineer/go
MavenGradle
<dependency>
<groupId>com.devdraft</groupId>
<artifactId>devdraft-sdk</artifactId>
<version>1.0.0</version>
</dependency>
implementation 'com.devdraft:devdraft-sdk:1.0.0'
composer require devdraft/devdraft
gem install devdraft
dotnet add package Devdraft
Configuration
Before making API calls, configure the SDK with your API credentials. You can obtain yourx-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);
import devdraft
import os
configuration = devdraft.Configuration(
host="https://api.devdraft.ai"
)
configuration.api_key['x-client-key'] = os.environ.get('DEVDRAFT_CLIENT_KEY', 'your-client-key')
configuration.api_key['x-client-secret'] = os.environ.get('DEVDRAFT_CLIENT_SECRET', 'your-client-secret')
with devdraft.ApiClient(configuration) as api_client:
transfers_api = devdraft.TransfersApi(api_client)
webhooks_api = devdraft.WebhooksApi(api_client)
package main
import (
"context"
"os"
devdraft "github.com/devdraftengineer/go"
)
func main() {
configuration := devdraft.NewConfiguration()
apiClient := devdraft.NewAPIClient(configuration)
ctx := context.Background()
clientKey := os.Getenv("DEVDRAFT_CLIENT_KEY")
if clientKey == "" {
clientKey = "your-client-key"
}
clientSecret := os.Getenv("DEVDRAFT_CLIENT_SECRET")
if clientSecret == "" {
clientSecret = "your-client-secret"
}
ctx = context.WithValue(ctx, devdraft.ContextAPIKeys, map[string]devdraft.APIKey{
"x-client-key": {
Key: clientKey,
},
"x-client-secret": {
Key: clientSecret,
},
})
// Use apiClient.TransfersAPI and apiClient.WebhooksAPI
}
import org.openapitools.client.ApiClient;
import org.openapitools.client.Configuration;
import org.openapitools.client.api.TransfersApi;
import org.openapitools.client.api.WebhooksApi;
public class DevdraftExample {
public static void main(String[] args) {
ApiClient apiClient = Configuration.getDefaultApiClient();
apiClient.setBasePath("https://api.devdraft.ai");
String clientKey = System.getenv("DEVDRAFT_CLIENT_KEY");
String clientSecret = System.getenv("DEVDRAFT_CLIENT_SECRET");
if (clientKey == null) clientKey = "your-client-key";
if (clientSecret == null) clientSecret = "your-client-secret";
apiClient.addDefaultHeader("x-client-key", clientKey);
apiClient.addDefaultHeader("x-client-secret", clientSecret);
TransfersApi transfersApi = new TransfersApi(apiClient);
WebhooksApi webhooksApi = new WebhooksApi(apiClient);
}
}
<?php
require_once(__DIR__ . '/vendor/autoload.php');
use Devdraft\Configuration;
use Devdraft\Api\TransfersApi;
use Devdraft\Api\WebhooksApi;
$config = Configuration::getDefaultConfiguration();
$config->setHost('https://api.devdraft.ai');
$config->setApiKey('x-client-key', getenv('DEVDRAFT_CLIENT_KEY') ?: 'your-client-key');
$config->setApiKey('x-client-secret', getenv('DEVDRAFT_CLIENT_SECRET') ?: 'your-client-secret');
$transfersApi = new TransfersApi(null, $config);
$webhooksApi = new WebhooksApi(null, $config);
require 'devdraft'
Devdraft.configure do |config|
config.host = 'https://api.devdraft.ai'
config.api_key['x-client-key'] = ENV['DEVDRAFT_CLIENT_KEY'] || 'your-client-key'
config.api_key['x-client-secret'] = ENV['DEVDRAFT_CLIENT_SECRET'] || 'your-client-secret'
end
transfers_api = Devdraft::TransfersApi.new
webhooks_api = Devdraft::WebhooksApi.new
using Microsoft.Extensions.DependencyInjection;
using Devdraft.Api;
using Devdraft.Client;
// Using dependency injection
var services = new ServiceCollection();
services.AddDevdraft(options =>
{
options.BasePath = "https://api.devdraft.ai";
options.ApiKey["x-client-key"] = Environment.GetEnvironmentVariable("DEVDRAFT_CLIENT_KEY") ?? "your-client-key";
options.ApiKey["x-client-secret"] = Environment.GetEnvironmentVariable("DEVDRAFT_CLIENT_SECRET") ?? "your-client-secret";
});
var serviceProvider = services.BuildServiceProvider();
var transfersApi = serviceProvider.GetRequiredService<ITransfersApi>();
var webhooksApi = serviceProvider.GetRequiredService<IWebhooksApi>();
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| walletId | string | Yes | Your Devdraft wallet ID to receive the transfer |
| paymentRail | string | Yes | Payment method: wire, ach, sepa, spei |
| sourceCurrency | string | Yes | Source fiat currency: usd, eur, mxn |
| destinationCurrency | string | Yes | Destination currency in your wallet |
| amount | number | Yes | Amount 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);
}
}
from devdraft.model.create_direct_bank_transfer_dto import CreateDirectBankTransferDto
def create_bank_transfer():
transfer_data = CreateDirectBankTransferDto(
wallet_id='550e8400-e29b-41d4-a716-446655440000',
payment_rail='wire',
source_currency='usd',
destination_currency='usdc',
amount=1000.50
)
try:
transfers_api.transfer_controller_create_direct_bank_transfer(transfer_data)
print('Bank transfer initiated successfully')
except Exception as e:
print(f'Transfer failed: {e}')
func createBankTransfer(ctx context.Context, apiClient *devdraft.APIClient) {
transferData := devdraft.NewCreateDirectBankTransferDto(
"550e8400-e29b-41d4-a716-446655440000", // walletId
"wire", // paymentRail
"usdc", // destinationCurrency
"usd", // sourceCurrency
1000.50, // amount
)
_, httpRes, err := apiClient.TransfersAPI.TransferControllerCreateDirectBankTransfer(ctx).
CreateDirectBankTransferDto(*transferData).
Execute()
if err != nil {
fmt.Printf("Transfer failed: %v\n", err)
return
}
if httpRes.StatusCode == 201 {
fmt.Println("Bank transfer initiated successfully")
}
}
import org.openapitools.client.model.CreateDirectBankTransferDto;
import org.openapitools.client.ApiException;
public void createBankTransfer() {
CreateDirectBankTransferDto transferData = new CreateDirectBankTransferDto()
.walletId("550e8400-e29b-41d4-a716-446655440000")
.paymentRail("wire")
.sourceCurrency("usd")
.destinationCurrency("usdc")
.amount(1000.50);
try {
transfersApi.transferControllerCreateDirectBankTransfer(transferData);
System.out.println("Bank transfer initiated successfully");
} catch (ApiException e) {
System.err.println("Transfer failed: " + e.getMessage());
}
}
use Devdraft\Model\CreateDirectBankTransferDto;
use Devdraft\ApiException;
function createBankTransfer($transfersApi) {
$transferData = new CreateDirectBankTransferDto([
'wallet_id' => '550e8400-e29b-41d4-a716-446655440000',
'payment_rail' => 'wire',
'source_currency' => 'usd',
'destination_currency' => 'usdc',
'amount' => 1000.50
]);
try {
$transfersApi->transferControllerCreateDirectBankTransfer($transferData);
echo "Bank transfer initiated successfully\n";
} catch (ApiException $e) {
echo "Transfer failed: " . $e->getMessage() . "\n";
}
}
def create_bank_transfer
transfer_data = Devdraft::CreateDirectBankTransferDto.new(
wallet_id: '550e8400-e29b-41d4-a716-446655440000',
payment_rail: 'wire',
source_currency: 'usd',
destination_currency: 'usdc',
amount: 1000.50
)
begin
transfers_api.transfer_controller_create_direct_bank_transfer(transfer_data)
puts 'Bank transfer initiated successfully'
rescue Devdraft::ApiError => e
puts "Transfer failed: #{e.message}"
end
end
using Devdraft.Model;
public async Task CreateBankTransferAsync()
{
var transferData = new CreateDirectBankTransferDto
{
WalletId = "550e8400-e29b-41d4-a716-446655440000",
PaymentRail = "wire",
SourceCurrency = "usd",
DestinationCurrency = "usdc",
Amount = 1000.50m
};
try
{
await transfersApi.TransferControllerCreateDirectBankTransferAsync(transferData);
Console.WriteLine("Bank transfer initiated successfully");
}
catch (Exception ex)
{
Console.WriteLine($"Transfer failed: {ex.Message}");
}
}
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| walletId | string | Yes | Your Devdraft wallet ID to receive the transfer |
| network | string | Yes | Blockchain network: solana, ethereum, base, etc. |
| stableCoinCurrency | string | Yes | Stablecoin: usdc, eurc |
| amount | number | Yes | Amount 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);
}
}
from devdraft.model.create_direct_wallet_transfer_dto import CreateDirectWalletTransferDto
def create_wallet_transfer():
transfer_data = CreateDirectWalletTransferDto(
wallet_id='550e8400-e29b-41d4-a716-446655440000',
network='solana',
stable_coin_currency='usdc',
amount=500.00
)
try:
transfers_api.transfer_controller_create_direct_wallet_transfer(transfer_data)
print('Wallet transfer initiated successfully')
except Exception as e:
print(f'Transfer failed: {e}')
func createWalletTransfer(ctx context.Context, apiClient *devdraft.APIClient) {
transferData := devdraft.NewCreateDirectWalletTransferDto(
"550e8400-e29b-41d4-a716-446655440000", // walletId
"solana", // network
"usdc", // stableCoinCurrency
500.00, // amount
)
_, httpRes, err := apiClient.TransfersAPI.TransferControllerCreateDirectWalletTransfer(ctx).
CreateDirectWalletTransferDto(*transferData).
Execute()
if err != nil {
fmt.Printf("Transfer failed: %v\n", err)
return
}
if httpRes.StatusCode == 201 {
fmt.Println("Wallet transfer initiated successfully")
}
}
import org.openapitools.client.model.CreateDirectWalletTransferDto;
import org.openapitools.client.ApiException;
public void createWalletTransfer() {
CreateDirectWalletTransferDto transferData = new CreateDirectWalletTransferDto()
.walletId("550e8400-e29b-41d4-a716-446655440000")
.network("solana")
.stableCoinCurrency("usdc")
.amount(500.00);
try {
transfersApi.transferControllerCreateDirectWalletTransfer(transferData);
System.out.println("Wallet transfer initiated successfully");
} catch (ApiException e) {
System.err.println("Transfer failed: " + e.getMessage());
}
}
use Devdraft\Model\CreateDirectWalletTransferDto;
use Devdraft\ApiException;
function createWalletTransfer($transfersApi) {
$transferData = new CreateDirectWalletTransferDto([
'wallet_id' => '550e8400-e29b-41d4-a716-446655440000',
'network' => 'solana',
'stable_coin_currency' => 'usdc',
'amount' => 500.00
]);
try {
$transfersApi->transferControllerCreateDirectWalletTransfer($transferData);
echo "Wallet transfer initiated successfully\n";
} catch (ApiException $e) {
echo "Transfer failed: " . $e->getMessage() . "\n";
}
}
def create_wallet_transfer
transfer_data = Devdraft::CreateDirectWalletTransferDto.new(
wallet_id: '550e8400-e29b-41d4-a716-446655440000',
network: 'solana',
stable_coin_currency: 'usdc',
amount: 500.00
)
begin
transfers_api.transfer_controller_create_direct_wallet_transfer(transfer_data)
puts 'Wallet transfer initiated successfully'
rescue Devdraft::ApiError => e
puts "Transfer failed: #{e.message}"
end
end
using Devdraft.Model;
public async Task CreateWalletTransferAsync()
{
var transferData = new CreateDirectWalletTransferDto
{
WalletId = "550e8400-e29b-41d4-a716-446655440000",
Network = "solana",
StableCoinCurrency = "usdc",
Amount = 500.00m
};
try
{
await transfersApi.TransferControllerCreateDirectWalletTransferAsync(transferData);
Console.WriteLine("Wallet transfer initiated successfully");
}
catch (Exception ex)
{
Console.WriteLine($"Transfer failed: {ex.Message}");
}
}
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
| Event | Description |
|---|---|
transfer.initiated | Transfer process has started |
transfer.pending | Transfer is being processed |
transfer.completed | Transfer completed successfully |
transfer.failed | Transfer processing failed |
transfer.refunded | Failed 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;
}
}
from devdraft.model.create_webhook_dto import CreateWebhookDto
def create_transfer_webhook():
webhook_data = CreateWebhookDto(
url='https://your-app.com/webhooks/transfers',
name='Transfer Notifications',
is_active=True,
encrypted=False
)
try:
webhook = webhooks_api.webhook_controller_create(webhook_data)
print(f'Webhook created: {webhook.id}')
print(f'Signing secret: {webhook.signing_secret}')
return webhook
except Exception as e:
print(f'Webhook creation failed: {e}')
raise
func createTransferWebhook(ctx context.Context, apiClient *devdraft.APIClient) {
webhookData := devdraft.NewCreateWebhookDto("https://your-app.com/webhooks/transfers")
webhookData.SetName("Transfer Notifications")
webhookData.SetIsActive(true)
webhookData.SetEncrypted(false)
webhook, httpRes, err := apiClient.WebhooksAPI.WebhookControllerCreate(ctx).
CreateWebhookDto(*webhookData).
Execute()
if err != nil {
fmt.Printf("Webhook creation failed: %v\n", err)
return
}
if httpRes.StatusCode == 201 {
fmt.Printf("Webhook created: %s\n", webhook.Id)
fmt.Printf("Signing secret: %s\n", webhook.SigningSecret)
}
}
import org.openapitools.client.model.CreateWebhookDto;
import org.openapitools.client.model.WebhookResponseDto;
import org.openapitools.client.ApiException;
public WebhookResponseDto createTransferWebhook() {
CreateWebhookDto webhookData = new CreateWebhookDto()
.url("https://your-app.com/webhooks/transfers")
.name("Transfer Notifications")
.isActive(true)
.encrypted(false);
try {
WebhookResponseDto webhook = webhooksApi.webhookControllerCreate(webhookData);
System.out.println("Webhook created: " + webhook.getId());
System.out.println("Signing secret: " + webhook.getSigningSecret());
return webhook;
} catch (ApiException e) {
System.err.println("Webhook creation failed: " + e.getMessage());
throw new RuntimeException(e);
}
}
use Devdraft\Model\CreateWebhookDto;
use Devdraft\ApiException;
function createTransferWebhook($webhooksApi) {
$webhookData = new CreateWebhookDto([
'url' => 'https://your-app.com/webhooks/transfers',
'name' => 'Transfer Notifications',
'is_active' => true,
'encrypted' => false
]);
try {
$webhook = $webhooksApi->webhookControllerCreate($webhookData);
echo "Webhook created: " . $webhook->getId() . "\n";
echo "Signing secret: " . $webhook->getSigningSecret() . "\n";
return $webhook;
} catch (ApiException $e) {
echo "Webhook creation failed: " . $e->getMessage() . "\n";
throw $e;
}
}
def create_transfer_webhook
webhook_data = Devdraft::CreateWebhookDto.new(
url: 'https://your-app.com/webhooks/transfers',
name: 'Transfer Notifications',
is_active: true,
encrypted: false
)
begin
webhook = webhooks_api.webhook_controller_create(webhook_data)
puts "Webhook created: #{webhook.id}"
puts "Signing secret: #{webhook.signing_secret}"
webhook
rescue Devdraft::ApiError => e
puts "Webhook creation failed: #{e.message}"
raise
end
end
using Devdraft.Model;
public async Task<WebhookResponseDto> CreateTransferWebhookAsync()
{
var webhookData = new CreateWebhookDto
{
Url = "https://your-app.com/webhooks/transfers",
Name = "Transfer Notifications",
IsActive = true,
Encrypted = false
};
try
{
var response = await webhooksApi.WebhookControllerCreateAsync(webhookData);
var webhook = response.Ok();
Console.WriteLine($"Webhook created: {webhook.Id}");
Console.WriteLine($"Signing secret: {webhook.SigningSecret}");
return webhook;
}
catch (Exception ex)
{
Console.WriteLine($"Webhook creation failed: {ex.Message}");
throw;
}
}
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;
}
}
def list_webhooks():
try:
webhooks = webhooks_api.webhook_controller_find_all()
print(f'Found {len(webhooks)} webhooks')
for webhook in webhooks:
status = 'active' if webhook.is_active else 'inactive'
print(f'- {webhook.name}: {webhook.url} ({status})')
return webhooks
except Exception as e:
print(f'Failed to list webhooks: {e}')
raise
func listWebhooks(ctx context.Context, apiClient *devdraft.APIClient) {
webhooks, _, err := apiClient.WebhooksAPI.WebhookControllerFindAll(ctx).Execute()
if err != nil {
fmt.Printf("Failed to list webhooks: %v\n", err)
return
}
if webhooks != nil {
fmt.Printf("Found %d webhooks\n", len(*webhooks))
for _, webhook := range *webhooks {
status := "inactive"
if webhook.Active {
status = "active"
}
fmt.Printf("- %s: %s (%s)\n", webhook.Name, webhook.Url, status)
}
}
}
public void listWebhooks() {
try {
List<WebhookResponseDto> webhooks = webhooksApi.webhookControllerFindAll(null, null);
System.out.println("Found " + webhooks.size() + " webhooks");
for (WebhookResponseDto webhook : webhooks) {
String status = webhook.getIsActive() ? "active" : "inactive";
System.out.println("- " + webhook.getName() + ": " + webhook.getUrl() + " (" + status + ")");
}
} catch (ApiException e) {
System.err.println("Failed to list webhooks: " + e.getMessage());
}
}
function listWebhooks($webhooksApi) {
try {
$webhooks = $webhooksApi->webhookControllerFindAll();
echo "Found " . count($webhooks) . " webhooks\n";
foreach ($webhooks as $webhook) {
$status = $webhook->getIsActive() ? 'active' : 'inactive';
echo "- " . $webhook->getName() . ": " . $webhook->getUrl() . " (" . $status . ")\n";
}
return $webhooks;
} catch (ApiException $e) {
echo "Failed to list webhooks: " . $e->getMessage() . "\n";
throw $e;
}
}
def list_webhooks
begin
webhooks = webhooks_api.webhook_controller_find_all
puts "Found #{webhooks.length} webhooks"
webhooks.each do |webhook|
status = webhook.is_active ? 'active' : 'inactive'
puts "- #{webhook.name}: #{webhook.url} (#{status})"
end
webhooks
rescue Devdraft::ApiError => e
puts "Failed to list webhooks: #{e.message}"
raise
end
end
public async Task ListWebhooksAsync()
{
try
{
var response = await webhooksApi.WebhookControllerFindAllAsync();
var webhooks = response.Ok();
Console.WriteLine($"Found {webhooks.Count} webhooks");
foreach (var webhook in webhooks)
{
var status = webhook.IsActive ? "active" : "inactive";
Console.WriteLine($"- {webhook.Name}: {webhook.Url} ({status})");
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to list webhooks: {ex.Message}");
throw;
}
}
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');
});
import hmac
import hashlib
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhooks/transfers', methods=['POST'])
def handle_transfer_webhook():
signature = request.headers.get('x-webhook-signature')
payload = request.get_data(as_text=True)
# Verify signature
expected_signature = 'sha256=' + hmac.new(
os.environ['WEBHOOK_SECRET'].encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected_signature):
return 'Invalid signature', 401
event = request.get_json()
# Handle transfer events
if event['type'] == 'transfer.completed':
print(f"Transfer completed: {event['data']['object']['id']}")
# Update your database, notify user, etc.
elif event['type'] == 'transfer.failed':
print(f"Transfer failed: {event['data']['object']['id']}")
# Handle failure, notify user, etc.
elif event['type'] == 'transfer.pending':
print(f"Transfer pending: {event['data']['object']['id']}")
return 'OK', 200
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
func handleTransferWebhook(w http.ResponseWriter, r *http.Request) {
signature := r.Header.Get("x-webhook-signature")
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read body", http.StatusBadRequest)
return
}
// Verify signature
mac := hmac.New(sha256.New, []byte(os.Getenv("WEBHOOK_SECRET")))
mac.Write(body)
expectedSignature := "sha256=" + hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(signature), []byte(expectedSignature)) {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}
var event map[string]interface{}
json.Unmarshal(body, &event)
// Handle transfer events
eventType := event["type"].(string)
data := event["data"].(map[string]interface{})
object := data["object"].(map[string]interface{})
switch eventType {
case "transfer.completed":
fmt.Printf("Transfer completed: %s\n", object["id"])
case "transfer.failed":
fmt.Printf("Transfer failed: %s\n", object["id"])
case "transfer.pending":
fmt.Printf("Transfer pending: %s\n", object["id"])
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class WebhookHandler extends HttpServlet {
private final ObjectMapper objectMapper = new ObjectMapper();
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String signature = request.getHeader("x-webhook-signature");
String payload = request.getReader().lines().collect(Collectors.joining());
// Verify signature
try {
String webhookSecret = System.getenv("WEBHOOK_SECRET");
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(
webhookSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(secretKeySpec);
byte[] hash = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8));
StringBuilder expectedSignature = new StringBuilder("sha256=");
for (byte b : hash) {
expectedSignature.append(String.format("%02x", b));
}
if (!signature.equals(expectedSignature.toString())) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("Invalid signature");
return;
}
// Parse and handle event
JsonNode event = objectMapper.readTree(payload);
String eventType = event.get("type").asText();
JsonNode data = event.get("data").get("object");
switch (eventType) {
case "transfer.completed":
System.out.println("Transfer completed: " + data.get("id").asText());
// Update your database, notify user, etc.
break;
case "transfer.failed":
System.out.println("Transfer failed: " + data.get("id").asText());
// Handle failure, notify user, etc.
break;
case "transfer.pending":
System.out.println("Transfer pending: " + data.get("id").asText());
break;
}
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().write("OK");
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("Error processing webhook");
}
}
}
<?php
// webhook_handler.php
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');
// Verify signature
$webhookSecret = getenv('WEBHOOK_SECRET');
$expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $webhookSecret);
if (!hash_equals($signature, $expectedSignature)) {
http_response_code(401);
echo 'Invalid signature';
exit;
}
// Parse and handle event
$event = json_decode($payload, true);
$eventType = $event['type'];
$data = $event['data']['object'];
switch ($eventType) {
case 'transfer.completed':
error_log("Transfer completed: " . $data['id']);
// Update your database, notify user, etc.
break;
case 'transfer.failed':
error_log("Transfer failed: " . $data['id']);
// Handle failure, notify user, etc.
break;
case 'transfer.pending':
error_log("Transfer pending: " . $data['id']);
break;
}
http_response_code(200);
echo 'OK';
require 'sinatra'
require 'json'
require 'openssl'
post '/webhooks/transfers' do
signature = request.env['HTTP_X_WEBHOOK_SIGNATURE']
payload = request.body.read
# Verify signature
webhook_secret = ENV['WEBHOOK_SECRET']
expected_signature = 'sha256=' + OpenSSL::HMAC.hexdigest('sha256', webhook_secret, payload)
unless Rack::Utils.secure_compare(signature, expected_signature)
halt 401, 'Invalid signature'
end
# Parse and handle event
event = JSON.parse(payload)
event_type = event['type']
data = event['data']['object']
case event_type
when 'transfer.completed'
puts "Transfer completed: #{data['id']}"
# Update your database, notify user, etc.
when 'transfer.failed'
puts "Transfer failed: #{data['id']}"
# Handle failure, notify user, etc.
when 'transfer.pending'
puts "Transfer pending: #{data['id']}"
end
status 200
body 'OK'
end
using Microsoft.AspNetCore.Mvc;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
[ApiController]
[Route("webhooks")]
public class WebhookController : ControllerBase
{
[HttpPost("transfers")]
public async Task<IActionResult> HandleTransferWebhook()
{
var signature = Request.Headers["x-webhook-signature"].ToString();
using var reader = new StreamReader(Request.Body);
var payload = await reader.ReadToEndAsync();
// Verify signature
var webhookSecret = Environment.GetEnvironmentVariable("WEBHOOK_SECRET");
var expectedSignature = "sha256=" + ComputeHmacSha256(payload, webhookSecret);
if (signature != expectedSignature)
{
return Unauthorized("Invalid signature");
}
// Parse and handle event
var eventData = JsonSerializer.Deserialize<JsonElement>(payload);
var eventType = eventData.GetProperty("type").GetString();
var data = eventData.GetProperty("data").GetProperty("object");
switch (eventType)
{
case "transfer.completed":
Console.WriteLine($"Transfer completed: {data.GetProperty("id").GetString()}");
// Update your database, notify user, etc.
break;
case "transfer.failed":
Console.WriteLine($"Transfer failed: {data.GetProperty("id").GetString()}");
// Handle failure, notify user, etc.
break;
case "transfer.pending":
Console.WriteLine($"Transfer pending: {data.GetProperty("id").GetString()}");
break;
}
return Ok("OK");
}
private string ComputeHmacSha256(string data, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
Complete Integration Example
Here’s a real-world example that demonstrates the complete flow:- Configure the SDK with your API URL and credentials
- Retrieve your wallets from the API
- Use a wallet ID from the response to initiate a transfer
- Set up a webhook to receive real-time transfer status updates
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);
import os
import devdraft
from devdraft.model.create_direct_wallet_transfer_dto import CreateDirectWalletTransferDto
from devdraft.model.create_direct_bank_transfer_dto import CreateDirectBankTransferDto
from devdraft.model.create_webhook_dto import CreateWebhookDto
def real_world_example():
# Step 1: Configure the SDK with API URL and credentials
configuration = devdraft.Configuration(
host="https://api.devdraft.ai" # API base URL
)
configuration.api_key['x-client-key'] = os.environ['DEVDRAFT_CLIENT_KEY']
configuration.api_key['x-client-secret'] = os.environ['DEVDRAFT_CLIENT_SECRET']
with devdraft.ApiClient(configuration) as api_client:
transfers_api = devdraft.TransfersApi(api_client)
webhooks_api = devdraft.WebhooksApi(api_client)
wallets_api = devdraft.WalletsApi(api_client)
try:
# Step 2: Get your wallets from the API
print('Fetching your wallets...')
wallets_response = wallets_api.wallet_controller_get_wallets()
# In a real implementation, the API would return wallet data
# For this example, we'll use the first wallet from your account
first_wallet_id = '550e8400-e29b-41d4-a716-446655440000' # From API response
print(f'Using wallet: {first_wallet_id}')
# Step 3: Set up webhook to receive transfer events
print('Creating webhook for transfer notifications...')
webhook = webhooks_api.webhook_controller_create(CreateWebhookDto(
url='https://your-app.com/webhooks/transfers',
name='Transfer Status Updates',
is_active=True
))
print(f'✓ Webhook created: {webhook.id}')
print(f' Signing secret: {webhook.signing_secret}')
# Step 4: Initiate a direct wallet transfer using the wallet from Step 2
print('Initiating transfer...')
transfers_api.transfer_controller_create_direct_wallet_transfer(
CreateDirectWalletTransferDto(
wallet_id=first_wallet_id, # Using the wallet ID from API
network='solana',
stable_coin_currency='usdc',
amount=100.00
)
)
print('✓ Transfer initiated successfully!')
print(' Your webhook will receive status updates at:')
print(f' {webhook.url}')
# Alternative: Bank transfer example
# transfers_api.transfer_controller_create_direct_bank_transfer(
# CreateDirectBankTransferDto(
# wallet_id=first_wallet_id,
# payment_rail='wire',
# source_currency='usd',
# destination_currency='usdc',
# amount=1000.00
# )
# )
except Exception as e:
print(f'Error: {e}')
raise
if __name__ == '__main__':
real_world_example()
package main
import (
"context"
"fmt"
"os"
devdraft "github.com/devdraftengineer/go"
)
func main() {
// Step 1: Configure the SDK with API URL and credentials
configuration := devdraft.NewConfiguration()
configuration.Servers[0].URL = "https://api.devdraft.ai" // API base URL
apiClient := devdraft.NewAPIClient(configuration)
ctx := context.WithValue(context.Background(), devdraft.ContextAPIKeys, map[string]devdraft.APIKey{
"x-client-key": {Key: os.Getenv("DEVDRAFT_CLIENT_KEY")},
"x-client-secret": {Key: os.Getenv("DEVDRAFT_CLIENT_SECRET")},
})
// Step 2: Get your wallets from the API
fmt.Println("Fetching your wallets...")
_, err := apiClient.WalletsAPI.WalletControllerGetWallets(ctx).Execute()
if err != nil {
fmt.Printf("Failed to get wallets: %v\n", err)
return
}
// In a real implementation, the API would return wallet data
// For this example, we'll use the first wallet from your account
firstWalletId := "550e8400-e29b-41d4-a716-446655440000" // From API response
fmt.Printf("Using wallet: %s\n", firstWalletId)
// Step 3: Set up webhook to receive transfer events
fmt.Println("Creating webhook for transfer notifications...")
webhookData := devdraft.NewCreateWebhookDto("https://your-app.com/webhooks/transfers")
webhookData.SetName("Transfer Status Updates")
webhookData.SetIsActive(true)
webhook, _, err := apiClient.WebhooksAPI.WebhookControllerCreate(ctx).
CreateWebhookDto(*webhookData).
Execute()
if err != nil {
fmt.Printf("Failed to create webhook: %v\n", err)
return
}
fmt.Printf("✓ Webhook created: %s\n", webhook.Id)
fmt.Printf(" Signing secret: %s\n", webhook.SigningSecret)
// Step 4: Initiate a direct wallet transfer using the wallet from Step 2
fmt.Println("Initiating transfer...")
transferData := devdraft.NewCreateDirectWalletTransferDto(
firstWalletId, // Using the wallet ID from API
"solana",
"usdc",
100.00,
)
_, _, err = apiClient.TransfersAPI.TransferControllerCreateDirectWalletTransfer(ctx).
CreateDirectWalletTransferDto(*transferData).
Execute()
if err != nil {
fmt.Printf("Failed to create transfer: %v\n", err)
return
}
fmt.Println("✓ Transfer initiated successfully!")
fmt.Println(" Your webhook will receive status updates at:")
fmt.Printf(" %s\n", webhook.Url)
// Alternative: Bank transfer example
// bankTransferData := devdraft.NewCreateDirectBankTransferDto(
// firstWalletId,
// "wire",
// "usdc",
// "usd",
// 1000.00,
// )
// apiClient.TransfersAPI.TransferControllerCreateDirectBankTransfer(ctx).
// CreateDirectBankTransferDto(*bankTransferData).
// Execute()
}
import org.openapitools.client.ApiClient;
import org.openapitools.client.Configuration;
import org.openapitools.client.api.TransfersApi;
import org.openapitools.client.api.WebhooksApi;
import org.openapitools.client.api.WalletsApi;
import org.openapitools.client.model.CreateDirectWalletTransferDto;
import org.openapitools.client.model.CreateDirectBankTransferDto;
import org.openapitools.client.model.CreateWebhookDto;
import org.openapitools.client.model.WebhookResponseDto;
import org.openapitools.client.ApiException;
public class RealWorldExample {
public static void main(String[] args) {
// Step 1: Configure the SDK with API URL and credentials
ApiClient apiClient = Configuration.getDefaultApiClient();
apiClient.setBasePath("https://api.devdraft.ai"); // API base URL
String clientKey = System.getenv("DEVDRAFT_CLIENT_KEY");
String clientSecret = System.getenv("DEVDRAFT_CLIENT_SECRET");
if (clientKey == null) clientKey = "your-client-key";
if (clientSecret == null) clientSecret = "your-client-secret";
apiClient.addDefaultHeader("x-client-key", clientKey);
apiClient.addDefaultHeader("x-client-secret", clientSecret);
TransfersApi transfersApi = new TransfersApi(apiClient);
WebhooksApi webhooksApi = new WebhooksApi(apiClient);
WalletsApi walletsApi = new WalletsApi(apiClient);
try {
// Step 2: Get your wallets from the API
System.out.println("Fetching your wallets...");
walletsApi.walletControllerGetWallets();
// In a real implementation, the API would return wallet data
// For this example, we'll use the first wallet from your account
String firstWalletId = "550e8400-e29b-41d4-a716-446655440000"; // From API response
System.out.println("Using wallet: " + firstWalletId);
// Step 3: Set up webhook to receive transfer events
System.out.println("Creating webhook for transfer notifications...");
CreateWebhookDto webhookData = new CreateWebhookDto()
.url("https://your-app.com/webhooks/transfers")
.name("Transfer Status Updates")
.isActive(true);
WebhookResponseDto webhook = webhooksApi.webhookControllerCreate(webhookData);
System.out.println("✓ Webhook created: " + webhook.getId());
System.out.println(" Signing secret: " + webhook.getSigningSecret());
// Step 4: Initiate a direct wallet transfer using the wallet from Step 2
System.out.println("Initiating transfer...");
CreateDirectWalletTransferDto transferData = new CreateDirectWalletTransferDto()
.walletId(firstWalletId) // Using the wallet ID from API
.network("solana")
.stableCoinCurrency("usdc")
.amount(100.00);
transfersApi.transferControllerCreateDirectWalletTransfer(transferData);
System.out.println("✓ Transfer initiated successfully!");
System.out.println(" Your webhook will receive status updates at:");
System.out.println(" " + webhook.getUrl());
// Alternative: Bank transfer example
// CreateDirectBankTransferDto bankTransferData = new CreateDirectBankTransferDto()
// .walletId(firstWalletId)
// .paymentRail("wire")
// .sourceCurrency("usd")
// .destinationCurrency("usdc")
// .amount(1000.00);
// transfersApi.transferControllerCreateDirectBankTransfer(bankTransferData);
} catch (ApiException e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
<?php
require_once(__DIR__ . '/vendor/autoload.php');
use Devdraft\Configuration;
use Devdraft\Api\TransfersApi;
use Devdraft\Api\WebhooksApi;
use Devdraft\Api\WalletsApi;
use Devdraft\Model\CreateDirectWalletTransferDto;
use Devdraft\Model\CreateDirectBankTransferDto;
use Devdraft\Model\CreateWebhookDto;
use Devdraft\ApiException;
function realWorldExample() {
// Step 1: Configure the SDK with API URL and credentials
$config = Configuration::getDefaultConfiguration();
$config->setHost('https://api.devdraft.ai'); // API base URL
$config->setApiKey('x-client-key', getenv('DEVDRAFT_CLIENT_KEY') ?: 'your-client-key');
$config->setApiKey('x-client-secret', getenv('DEVDRAFT_CLIENT_SECRET') ?: 'your-client-secret');
$transfersApi = new TransfersApi(null, $config);
$webhooksApi = new WebhooksApi(null, $config);
$walletsApi = new WalletsApi(null, $config);
try {
// Step 2: Get your wallets from the API
echo "Fetching your wallets...\n";
$walletsApi->walletControllerGetWallets();
// In a real implementation, the API would return wallet data
// For this example, we'll use the first wallet from your account
$firstWalletId = '550e8400-e29b-41d4-a716-446655440000'; // From API response
echo "Using wallet: {$firstWalletId}\n";
// Step 3: Set up webhook to receive transfer events
echo "Creating webhook for transfer notifications...\n";
$webhookData = new CreateWebhookDto([
'url' => 'https://your-app.com/webhooks/transfers',
'name' => 'Transfer Status Updates',
'is_active' => true
]);
$webhook = $webhooksApi->webhookControllerCreate($webhookData);
echo "✓ Webhook created: " . $webhook->getId() . "\n";
echo " Signing secret: " . $webhook->getSigningSecret() . "\n";
// Step 4: Initiate a direct wallet transfer using the wallet from Step 2
echo "Initiating transfer...\n";
$transferData = new CreateDirectWalletTransferDto([
'wallet_id' => $firstWalletId, // Using the wallet ID from API
'network' => 'solana',
'stable_coin_currency' => 'usdc',
'amount' => 100.00
]);
$transfersApi->transferControllerCreateDirectWalletTransfer($transferData);
echo "✓ Transfer initiated successfully!\n";
echo " Your webhook will receive status updates at:\n";
echo " " . $webhook->getUrl() . "\n";
// Alternative: Bank transfer example
// $bankTransferData = new CreateDirectBankTransferDto([
// 'wallet_id' => $firstWalletId,
// 'payment_rail' => 'wire',
// 'source_currency' => 'usd',
// 'destination_currency' => 'usdc',
// 'amount' => 1000.00
// ]);
// $transfersApi->transferControllerCreateDirectBankTransfer($bankTransferData);
} catch (ApiException $e) {
echo "Error: " . $e->getMessage() . "\n";
}
}
realWorldExample();
require 'devdraft'
def real_world_example
# Step 1: Configure the SDK with API URL and credentials
Devdraft.configure do |config|
config.host = 'https://api.devdraft.ai' # API base URL
config.api_key['x-client-key'] = ENV['DEVDRAFT_CLIENT_KEY'] || 'your-client-key'
config.api_key['x-client-secret'] = ENV['DEVDRAFT_CLIENT_SECRET'] || 'your-client-secret'
end
transfers_api = Devdraft::TransfersApi.new
webhooks_api = Devdraft::WebhooksApi.new
wallets_api = Devdraft::WalletsApi.new
begin
# Step 2: Get your wallets from the API
puts 'Fetching your wallets...'
wallets_api.wallet_controller_get_wallets
# In a real implementation, the API would return wallet data
# For this example, we'll use the first wallet from your account
first_wallet_id = '550e8400-e29b-41d4-a716-446655440000' # From API response
puts "Using wallet: #{first_wallet_id}"
# Step 3: Set up webhook to receive transfer events
puts 'Creating webhook for transfer notifications...'
webhook_data = Devdraft::CreateWebhookDto.new(
url: 'https://your-app.com/webhooks/transfers',
name: 'Transfer Status Updates',
is_active: true
)
webhook = webhooks_api.webhook_controller_create(webhook_data)
puts "✓ Webhook created: #{webhook.id}"
puts " Signing secret: #{webhook.signing_secret}"
# Step 4: Initiate a direct wallet transfer using the wallet from Step 2
puts 'Initiating transfer...'
transfer_data = Devdraft::CreateDirectWalletTransferDto.new(
wallet_id: first_wallet_id, # Using the wallet ID from API
network: 'solana',
stable_coin_currency: 'usdc',
amount: 100.00
)
transfers_api.transfer_controller_create_direct_wallet_transfer(transfer_data)
puts '✓ Transfer initiated successfully!'
puts ' Your webhook will receive status updates at:'
puts " #{webhook.url}"
# Alternative: Bank transfer example
# bank_transfer_data = Devdraft::CreateDirectBankTransferDto.new(
# wallet_id: first_wallet_id,
# payment_rail: 'wire',
# source_currency: 'usd',
# destination_currency: 'usdc',
# amount: 1000.00
# )
# transfers_api.transfer_controller_create_direct_bank_transfer(bank_transfer_data)
rescue Devdraft::ApiError => e
puts "Error: #{e.message}"
end
end
real_world_example
using Microsoft.Extensions.DependencyInjection;
using Devdraft.Api;
using Devdraft.Client;
using Devdraft.Model;
using System;
using System.Threading.Tasks;
public class RealWorldExample
{
public static async Task Main(string[] args)
{
// Step 1: Configure the SDK with API URL and credentials
var services = new ServiceCollection();
services.AddDevdraft(options =>
{
options.BasePath = "https://api.devdraft.ai"; // API base URL
options.ApiKey["x-client-key"] = Environment.GetEnvironmentVariable("DEVDRAFT_CLIENT_KEY") ?? "your-client-key";
options.ApiKey["x-client-secret"] = Environment.GetEnvironmentVariable("DEVDRAFT_CLIENT_SECRET") ?? "your-client-secret";
});
var serviceProvider = services.BuildServiceProvider();
var transfersApi = serviceProvider.GetRequiredService<ITransfersApi>();
var webhooksApi = serviceProvider.GetRequiredService<IWebhooksApi>();
var walletsApi = serviceProvider.GetRequiredService<IWalletsApi>();
try
{
// Step 2: Get your wallets from the API
Console.WriteLine("Fetching your wallets...");
await walletsApi.WalletControllerGetWalletsAsync();
// In a real implementation, the API would return wallet data
// For this example, we'll use the first wallet from your account
string firstWalletId = "550e8400-e29b-41d4-a716-446655440000"; // From API response
Console.WriteLine($"Using wallet: {firstWalletId}");
// Step 3: Set up webhook to receive transfer events
Console.WriteLine("Creating webhook for transfer notifications...");
var webhookData = new CreateWebhookDto
{
Url = "https://your-app.com/webhooks/transfers",
Name = "Transfer Status Updates",
IsActive = true
};
var webhookResponse = await webhooksApi.WebhookControllerCreateAsync(webhookData);
var webhook = webhookResponse.Ok();
Console.WriteLine($"✓ Webhook created: {webhook.Id}");
Console.WriteLine($" Signing secret: {webhook.SigningSecret}");
// Step 4: Initiate a direct wallet transfer using the wallet from Step 2
Console.WriteLine("Initiating transfer...");
var transferData = new CreateDirectWalletTransferDto
{
WalletId = firstWalletId, // Using the wallet ID from API
Network = "solana",
StableCoinCurrency = "usdc",
Amount = 100.00m
};
await transfersApi.TransferControllerCreateDirectWalletTransferAsync(transferData);
Console.WriteLine("✓ Transfer initiated successfully!");
Console.WriteLine(" Your webhook will receive status updates at:");
Console.WriteLine($" {webhook.Url}");
// Alternative: Bank transfer example
// var bankTransferData = new CreateDirectBankTransferDto
// {
// WalletId = firstWalletId,
// PaymentRail = "wire",
// SourceCurrency = "usd",
// DestinationCurrency = "usdc",
// Amount = 1000.00m
// };
// await transfersApi.TransferControllerCreateDirectBankTransferAsync(bankTransferData);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
Error Handling
All SDK methods may throw exceptions. Here are common error scenarios and how to handle them:| HTTP Code | Error Type | Description |
|---|---|---|
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Invalid or missing API credentials |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 422 | Unprocessable | Business logic validation failed |
| 429 | Rate Limited | Too many requests |
TypeScript Error Handling
TypeScript Error Handling
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);
}
}
}
Python Error Handling
Python Error Handling
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}')
Go Error Handling
Go Error Handling
_, 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)
}
}
}
Java Error Handling
Java Error Handling
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);
}
}
PHP Error Handling
PHP Error Handling
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";
}
}
Ruby Error Handling
Ruby Error Handling
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
C# Error Handling
C# Error Handling
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
