← Back to Documentation
Documentation
AdGuard DNS API Client - Code Examples
This document provides practical examples using the refactored helper classes.
Configuration Examples
Using ConfigurationHelper
using AdGuard.ApiClient.Helpers;
using AdGuard.ApiClient.Api;
// Simple API Key configuration
var config = ConfigurationHelper.CreateWithApiKey("your-api-key-here");
// With custom base path
var config = ConfigurationHelper.CreateWithApiKey(
"your-api-key-here",
"https://custom-api.adguard-dns.io"
);
// Bearer token configuration
var config = ConfigurationHelper.CreateWithBearerToken("your-access-token");
// Fluent configuration with method chaining
var config = ConfigurationHelper
.CreateCustom()
.WithApiKey("your-api-key-here")
.WithTimeout(30000) // 30 seconds
.WithUserAgent("MyApp/1.0");
// Use the configuration
var devicesApi = new DevicesApi(config);
DateTime Helper Examples
Working with Unix Milliseconds
using AdGuard.ApiClient.Helpers;
using AdGuard.ApiClient.Api;
var queryLogApi = new QueryLogApi(config);
// Get query log for the last 24 hours
var timeFrom = DateTimeExtensions.DaysAgo(1);
var timeTo = DateTimeExtensions.Now();
var queryLog = await queryLogApi.GetQueryLogAsync(timeFrom, timeTo);
// Get query log for the last week
var weekAgo = DateTimeExtensions.DaysAgo(7);
var now = DateTimeExtensions.Now();
var weeklyLog = await queryLogApi.GetQueryLogAsync(weekAgo, now);
// Get query log for today only
var startOfDay = DateTimeExtensions.StartOfToday();
var endOfDay = DateTimeExtensions.EndOfToday();
var todayLog = await queryLogApi.GetQueryLogAsync(startOfDay, endOfDay);
// Get query log for the last 6 hours
var sixHoursAgo = DateTimeExtensions.HoursAgo(6);
var recentLog = await queryLogApi.GetQueryLogAsync(sixHoursAgo, now);
// Convert DateTime to Unix milliseconds
var specificDate = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var unixMillis = specificDate.ToUnixMilliseconds();
// Convert Unix milliseconds back to DateTime
var dateTime = DateTimeExtensions.FromUnixMilliseconds(unixMillis);
// Using TimeSpan for relative times
var customTime = DateTimeExtensions.FromNow(TimeSpan.FromHours(-12));
Retry Policy Examples
Basic Retry Usage
using AdGuard.ApiClient.Helpers;
using AdGuard.ApiClient.Api;
using AdGuard.ApiClient.Client;
var devicesApi = new DevicesApi(config);
// Execute with automatic retry on transient failures
var devices = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => devicesApi.ListDevicesAsync()
);
// Custom retry count
var devices = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => devicesApi.ListDevicesAsync(),
maxRetries: 5
);
// Using retry policy directly
var retryPolicy = RetryPolicyHelper.CreateDefaultRetryPolicy<List<Device>>();
var devices = await retryPolicy.ExecuteAsync(
() => devicesApi.ListDevicesAsync()
);
Rate Limit Handling
// Create rate limit specific retry policy (for 429 errors)
var rateLimitPolicy = RetryPolicyHelper.CreateRateLimitRetryPolicy(
maxRetries: 5,
baseDelay: 5 // 5 seconds base delay
);
// Execute with rate limit handling
var result = await rateLimitPolicy.ExecuteAsync(async () =>
{
return await devicesApi.CreateDeviceAsync(newDevice);
});
Custom Retry Logic
using Polly;
// Combine multiple policies
var retryPolicy = RetryPolicyHelper.CreateDefaultRetryPolicy<Device>();
var timeoutPolicy = Policy.TimeoutAsync<Device>(TimeSpan.FromSeconds(30));
var combinedPolicy = Policy.WrapAsync(retryPolicy, timeoutPolicy);
var device = await combinedPolicy.ExecuteAsync(
() => devicesApi.GetDeviceAsync(deviceId)
);
Complete Examples
Device Management with Retry
using AdGuard.ApiClient.Api;
using AdGuard.ApiClient.Client;
using AdGuard.ApiClient.Model;
using AdGuard.ApiClient.Helpers;
// Configure client
var config = ConfigurationHelper
.CreateWithApiKey("your-api-key")
.WithTimeout(30000);
var devicesApi = new DevicesApi(config);
// Create device with automatic retry
var newDevice = new DeviceCreate
{
Name = "My iPhone",
DeviceType = "IOS",
DnsServerId = "dns-server-id"
};
var createdDevice = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => devicesApi.CreateDeviceAsync(newDevice)
);
Console.WriteLine($"Device created: {createdDevice.Id}");
// List devices with retry
var devices = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => devicesApi.ListDevicesAsync()
);
foreach (var device in devices)
{
Console.WriteLine($"{device.Name}: {device.Id}");
}
Query Log Analysis
using AdGuard.ApiClient.Api;
using AdGuard.ApiClient.Helpers;
var config = ConfigurationHelper.CreateWithApiKey("your-api-key");
var queryLogApi = new QueryLogApi(config);
var statsApi = new StatisticsApi(config);
// Get last 7 days of query logs
var weekAgo = DateTimeExtensions.DaysAgo(7);
var now = DateTimeExtensions.Now();
// Fetch query log with retry
var queryLog = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => queryLogApi.GetQueryLogAsync(weekAgo, now, limit: 1000)
);
// Fetch statistics with retry
var stats = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => statsApi.GetTimeQueriesStatsAsync(weekAgo, now)
);
// Analyze results
var totalQueries = stats.Stats.Sum(s => s.Value.Queries);
var totalBlocked = stats.Stats.Sum(s => s.Value.Blocked);
var blockRate = (double)totalBlocked / totalQueries * 100;
Console.WriteLine($"Total Queries: {totalQueries:N0}");
Console.WriteLine($"Total Blocked: {totalBlocked:N0}");
Console.WriteLine($"Block Rate: {blockRate:F2}%");
Bulk Operations with Error Handling
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AdGuard.ApiClient.Api;
using AdGuard.ApiClient.Client;
using AdGuard.ApiClient.Model;
using AdGuard.ApiClient.Helpers;
public class DeviceManager
{
private readonly DevicesApi _devicesApi;
private readonly int _maxRetries = 3;
public DeviceManager(string apiKey)
{
var config = ConfigurationHelper.CreateWithApiKey(apiKey);
_devicesApi = new DevicesApi(config);
}
public async Task<List<Device>> MigrateDevicesToServer(
string oldServerId,
string newServerId)
{
// Get all devices with retry
var devices = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => _devicesApi.ListDevicesAsync(),
_maxRetries
);
var devicesToMigrate = devices
.Where(d => d.DnsServerId == oldServerId)
.ToList();
var migratedDevices = new List<Device>();
var failures = new List<(Device device, Exception error)>();
foreach (var device in devicesToMigrate)
{
try
{
var update = new DeviceUpdate
{
DnsServerId = newServerId
};
await RetryPolicyHelper.ExecuteWithRetryAsync(
() => _devicesApi.UpdateDeviceAsync(device.Id, update),
_maxRetries
);
// Fetch updated device
var updatedDevice = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => _devicesApi.GetDeviceAsync(device.Id),
_maxRetries
);
migratedDevices.Add(updatedDevice);
Console.WriteLine($"✓ Migrated: {device.Name}");
}
catch (ApiException ex)
{
failures.Add((device, ex));
Console.WriteLine($"✗ Failed to migrate {device.Name}: {ex.Message}");
}
}
if (failures.Any())
{
Console.WriteLine($"\nMigration completed with {failures.Count} failures:");
foreach (var (device, error) in failures)
{
Console.WriteLine($" - {device.Name}: {error.Message}");
}
}
return migratedDevices;
}
public async Task<Dictionary<string, int>> GetDeviceCountByType()
{
var devices = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => _devicesApi.ListDevicesAsync(),
_maxRetries
);
return devices
.GroupBy(d => d.DeviceType)
.ToDictionary(g => g.Key, g => g.Count());
}
}
Authentication Flow
using AdGuard.ApiClient.Api;
using AdGuard.ApiClient.Client;
using AdGuard.ApiClient.Model;
using AdGuard.ApiClient.Helpers;
public class AuthenticationManager
{
private Configuration _config;
private AccessTokenResponse? _currentToken;
public async Task<bool> LoginAsync(string username, string password, string? mfaToken = null)
{
// Create config without auth for initial login
_config = ConfigurationHelper.CreateCustom();
var authApi = new AuthenticationApi(_config);
var credentials = new AccessTokenCredentials
{
Username = username,
Password = password,
MfaToken = mfaToken
};
try
{
// No retry on login - if it fails, credentials are likely wrong
_currentToken = await authApi.AccessTokenAsync(credentials);
// Update configuration with the access token
_config.WithBearerToken(_currentToken.AccessToken);
return true;
}
catch (ApiException ex)
{
Console.WriteLine($"Login failed: {ex.Message}");
return false;
}
}
public async Task<bool> RefreshTokenAsync()
{
if (_currentToken?.RefreshToken == null)
return false;
var authApi = new AuthenticationApi(_config);
var credentials = new AccessTokenCredentials
{
RefreshToken = _currentToken.RefreshToken
};
try
{
_currentToken = await authApi.AccessTokenAsync(credentials);
_config.WithBearerToken(_currentToken.AccessToken);
return true;
}
catch (ApiException ex)
{
Console.WriteLine($"Token refresh failed: {ex.Message}");
return false;
}
}
public Configuration GetConfiguration()
{
if (_config == null)
throw new InvalidOperationException("Must login first");
return _config;
}
}
Statistics Monitoring
using System;
using System.Threading.Tasks;
using AdGuard.ApiClient.Api;
using AdGuard.ApiClient.Helpers;
public class StatsMonitor
{
private readonly StatisticsApi _statsApi;
public StatsMonitor(string apiKey)
{
var config = ConfigurationHelper.CreateWithApiKey(apiKey);
_statsApi = new StatisticsApi(config);
}
public async Task<DailyStats> GetDailyStatsAsync()
{
var startOfDay = DateTimeExtensions.StartOfToday();
var now = DateTimeExtensions.Now();
var stats = await RetryPolicyHelper.ExecuteWithRetryAsync(
() => _statsApi.GetTimeQueriesStatsAsync(startOfDay, now)
);
return new DailyStats
{
TotalQueries = stats.Stats.Sum(s => s.Value.Queries),
BlockedQueries = stats.Stats.Sum(s => s.Value.Blocked),
Companies = stats.Stats.FirstOrDefault()?.Value.Companies ?? 0
};
}
public async Task<WeeklyReport> GetWeeklyReportAsync()
{
var weekAgo = DateTimeExtensions.DaysAgo(7);
var now = DateTimeExtensions.Now();
// Fetch all stats in parallel
var timeStatsTask = RetryPolicyHelper.ExecuteWithRetryAsync(
() => _statsApi.GetTimeQueriesStatsAsync(weekAgo, now)
);
var deviceStatsTask = RetryPolicyHelper.ExecuteWithRetryAsync(
() => _statsApi.GetDevicesQueriesStatsAsync(weekAgo, now)
);
var companyStatsTask = RetryPolicyHelper.ExecuteWithRetryAsync(
() => _statsApi.GetCompaniesStatsAsync(weekAgo, now)
);
await Task.WhenAll(timeStatsTask, deviceStatsTask, companyStatsTask);
var timeStats = await timeStatsTask;
var deviceStats = await deviceStatsTask;
var companyStats = await companyStatsTask;
return new WeeklyReport
{
StartTime = DateTimeExtensions.FromUnixMilliseconds(weekAgo),
EndTime = DateTimeExtensions.FromUnixMilliseconds(now),
TotalQueries = timeStats.Stats.Sum(s => s.Value.Queries),
TotalBlocked = timeStats.Stats.Sum(s => s.Value.Blocked),
ActiveDevices = deviceStats.Stats.Count,
TopCompanies = companyStats.Stats.Take(10).ToList()
};
}
}
public class DailyStats
{
public long TotalQueries { get; set; }
public long BlockedQueries { get; set; }
public int Companies { get; set; }
public double BlockRate => TotalQueries > 0 ? (double)BlockedQueries / TotalQueries * 100 : 0;
}
public class WeeklyReport
{
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public long TotalQueries { get; set; }
public long TotalBlocked { get; set; }
public int ActiveDevices { get; set; }
public List<CompanyQueriesStats> TopCompanies { get; set; }
}
Best Practices
- Always use retry policies for production code to handle transient failures
- Use ConfigurationHelper for clean, fluent configuration setup
- Use DateTimeExtensions for all time-based operations to avoid manual Unix milliseconds conversion
- Handle rate limiting by using appropriate retry policies with exponential backoff
- Parallelize independent API calls using Task.WhenAll for better performance
- Cache Configuration instances - create once, reuse across API calls
- Use async/await throughout your code for better resource utilization
- Implement proper error handling and logging for production scenarios