Whisper .NET SDK

A comprehensive .NET SDK for interacting with the Whisper API Platform, providing intelligence and monitoring capabilities for domains, IPs, and web infrastructure.

Introduction

The Whisper C# SDK provides a fully-typed, async client for the Whisper API v1, designed for .NET applications requiring comprehensive intelligence gathering and monitoring capabilities for domains, IPs, and web infrastructure. Built on modern .NET standards, it offers seamless integration with ASP.NET Core, Azure Functions, and other .NET platforms.

Key Features

  • Fully Typed: Complete type definitions with IntelliSense support
  • Async/Await: Modern async programming model
  • Cross-Platform: .NET Standard 2.0+ compatible
  • Performance: <500ms typical response with strategic caching
  • Enterprise Ready: Dependency injection, logging, and configuration support

Getting Started

Prerequisites

  • .NET Standard 2.0+ / .NET Framework 4.6.1+ / .NET Core 2.0+ / .NET 5.0+
  • NuGet Package Manager
  • Whisper API key from dash.whisper.security

Installation

Package Manager Console

Install-Package Whisper.Api.Sdk

.NET CLI

dotnet add package Whisper.Api.Sdk

PackageReference

<PackageReference Include="Whisper.Api.Sdk" Version="1.0.0" />

Quick Start Example

using Whisper.Api.Sdk.Api;
using Whisper.Api.Sdk.Client;
using Whisper.Api.Sdk.Model;

class Program
{
    static async Task Main(string[] args)
    {
        // Configure API client
        var config = new Configuration
        {
            BasePath = "https://api.whisper.security",
            AccessToken = "YOUR_API_KEY"
        };

        var api = new IndicatorsApi(config);

        try
        {
            // Enrich an IP address
            var response = await api.GetIndicatorAsync("ip", "8.8.8.8");
            Console.WriteLine($"Organization: {response.Summary.Organization}");
            Console.WriteLine($"Risk Score: {response.Reputation.RiskScore}");
        }
        catch (ApiException e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
    }
}

Core Concepts

1. Architecture Overview

The SDK follows a clean architecture pattern with:

  • API Classes: Service layer for API endpoints (IndicatorsApi, LocationApi, OperationsApi)
  • Models: Strongly typed data transfer objects
  • Client: HTTP client wrapper with configuration
  • Exceptions: Structured error handling

2. Async-First Design

All API methods are async and return Task<T>:

// All methods are async
public async Task<IndicatorResponse> GetIndicatorAsync(string type, string value)
public async Task<LocationResponse> GetIpLocationAsync(string ip)
public async Task<JobResponse> BulkEnrichmentAsync(BulkRequest request)

3. Authentication

var config = new Configuration
{
    BasePath = "https://api.whisper.security",
    AccessToken = "wsk_live_your_api_key_here"
};

API Overview

IndicatorsApi - Intelligence & Enrichment

Core API for gathering intelligence on IPs and domains.

Methods:

// Single indicator enrichment with optional data modules
Task<IndicatorResponse> GetIndicatorAsync(string type, string value, string include = null)

// Historical data retrieval
Task<HistoryResponse> GetIndicatorHistoryAsync(string type, string value, int? limit = null)

// Infrastructure relationship mapping
Task<GraphResponse> GetIndicatorGraphAsync(string type, string value)

// Domain subdomain discovery
Task<SubdomainsResponse> GetSubdomainsAsync(string domain, int? limit = null)

// Similar domain generation (typosquatting detection)
Task<SimilarDomainsResponse> GenerateSimilarDomainsGetAsync(string domain, string type = null, int? limit = null)
Task<JobResponse> GenerateSimilarDomainsPostAsync(string domain, SimilarDomainsRequest request)

// Bulk operations (async jobs)
Task<JobResponse> BulkEnrichmentAsync(BulkRequest request)
Task<JobResponse> SearchIndicatorsAsync(SearchRequest request)

LocationApi - Geolocation Intelligence

Geographic and network location services.

Methods:

// IP geolocation
Task<LocationResponse> GetIpLocationAsync(string ip)

// Network/CIDR geolocation
Task<LocationResponse> GetNetworkLocationAsync(string network)

// Location-based search
Task<List<LocationResponse>> SearchLocationAsync(string field, string value, int? limit = null)

// Bulk IP geolocation
Task<BulkLocationResponse> BulkIpLocationAsync(BulkLocationRequest request)

// Database statistics
Task<LocationStats> GetLocationStatsAsync()

OperationsApi - Async Jobs & Tools

Long-running operations and monitoring tools.

Methods:

// Job management
Task<Job> GetJobAsync(string jobId)
Task<List<Job>> ListJobsAsync(string status = null, int? limit = null)

// Screenshot operations
Task<JobResponse> CreateScreenshotAsync(ScreenshotRequest request)
Task<JobResponse> ScheduleScreenshotsAsync(ScheduleRequest request)
Task<ScreenshotHistory> GetScreenshotHistoryAsync(string url)

// Infrastructure scanning
Task<JobResponse> CreateScanAsync(InfraScanRequest request)
Task<JobResponse> MapInfrastructureAsync(MapRequest request)

// Monitoring
Task<MonitoringStatus> GetMonitoringStatusAsync(string target)
Task<JobResponse> ConfigureMonitoringAlertAsync(string target, AlertConfig config)

Error Handling

Exception Types

// Base exception
ApiException
├── ApiClientException     // Client-side errors (4xx)
├── ApiServerException     // Server-side errors (5xx)
├── RateLimitException     // Rate limiting (429)
├── AuthenticationException // Authentication failures (401)
└── ValidationException    // Request validation errors

Error Handling Example

public class ResilientApiService
{
    private readonly IIndicatorsApi _api;
    private readonly ILogger<ResilientApiService> _logger;
    private readonly IPollyContext _pollyContext;

    public async Task<T> ExecuteWithRetryAsync<T>(
        Func<Task<T>> operation,
        string operationName)
    {
        var retryPolicy = Policy
            .Handle<ApiException>(ex => ShouldRetry(ex))
            .WaitAndRetryAsync(
                3,
                retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                onRetry: (exception, timeSpan, retryCount, context) =>
                {
                    _logger.LogWarning(
                        "Retry {RetryCount} after {Delay}s for {Operation}: {Error}",
                        retryCount, timeSpan.TotalSeconds, operationName, 
                        exception.Message);
                });

        var circuitBreakerPolicy = Policy
            .Handle<ApiException>()
            .CircuitBreakerAsync(
                3,
                TimeSpan.FromMinutes(1),
                onBreak: (exception, duration) =>
                {
                    _logger.LogError(
                        "Circuit breaker opened for {Duration}s: {Error}",
                        duration.TotalSeconds, exception.Message);
                },
                onReset: () =>
                {
                    _logger.LogInformation("Circuit breaker reset");
                });

        var timeoutPolicy = Policy
            .TimeoutAsync<T>(30);

        var resilientPolicy = Policy.WrapAsync(
            retryPolicy,
            circuitBreakerPolicy,
            timeoutPolicy);

        try
        {
            return await resilientPolicy.ExecuteAsync(operation);
        }
        catch (ApiException ex)
        {
            _logger.LogError(ex, 
                "API operation {Operation} failed after all retries", 
                operationName);
            
            throw new ApplicationException(
                $"Failed to execute {operationName}: {ex.Message}", ex);
        }
    }

    private bool ShouldRetry(ApiException ex)
    {
        // Retry on server errors and rate limiting
        if (ex.ErrorCode >= 500 || ex.ErrorCode == 429)
            return true;

        // Don't retry on client errors
        if (ex.ErrorCode >= 400 && ex.ErrorCode < 500)
            return false;

        // Retry on network errors
        return true;
    }
}

Support and Resources