C# SDK
Official .NET SDK for TruthMark invisible watermarking.
Installation
.NET CLI
dotnet add package TruthMark.SDKPackage Manager
Install-Package TruthMark.SDKQuick Example
using TruthMark.SDK;
var client = new TruthMarkClient(new TruthMarkConfig
{
ApiKey = "tm_live_your_key",
BaseUrl = "https://truthmark-api.onrender.com"
});
// Encode
var result = await client.EncodeAsync("image.png", "Copyright 2025");
Console.WriteLine($"Download: {result.DownloadUrl}");
Console.WriteLine($"PSNR: {result.Metadata.Psnr:F1} dB");
// Decode
var decoded = await client.DecodeAsync("watermarked.png");
if (decoded.Found)
{
Console.WriteLine($"Message: {decoded.Message}");
Console.WriteLine($"Confidence: {decoded.Confidence * 100:F1}%");
}API Reference
TruthMarkClient(TruthMarkConfig config)
Create a new client with configuration.
ApiKey(string): Your API keyBaseUrl(string): API base URLTimeout(TimeSpan): Request timeout
EncodeAsync(string imagePath, string message)
Embed an invisible watermark. Returns Task<EncodeResult>.
DecodeAsync(string imagePath)
Extract watermark. Returns Task<DecodeResult>.
Error Handling
try
{
var result = await client.EncodeAsync("image.png", "message");
}
catch (TruthMarkException ex)
{
switch (ex.StatusCode)
{
case 401: Console.Error.WriteLine("Invalid API key"); break;
case 429: Console.Error.WriteLine($"Rate limited. Retry after {ex.RetryAfter}s"); break;
case 413: Console.Error.WriteLine("Image too large (max 20MB)"); break;
default: Console.Error.WriteLine($"Error: {ex.Message}"); break;
}
}Advanced Examples
ASP.NET Core Controller
[ApiController]
[Route("api/[controller]")]
public class WatermarkController : ControllerBase
{
private readonly TruthMarkClient _client;
public WatermarkController(TruthMarkClient client) => _client = client;
[HttpPost("encode")]
public async Task<IActionResult> Encode(IFormFile file, [FromForm] string message)
{
var tempPath = Path.GetTempFileName();
await using (var stream = System.IO.File.Create(tempPath))
await file.CopyToAsync(stream);
try
{
var result = await _client.EncodeAsync(tempPath, message);
return Ok(result);
}
finally
{
System.IO.File.Delete(tempPath);
}
}
}Dependency Injection
// Program.cs
builder.Services.AddSingleton(new TruthMarkClient(new TruthMarkConfig
{
ApiKey = builder.Configuration["TruthMark:ApiKey"]!,
}));Parallel Batch Processing
var files = Directory.GetFiles("./images", "*.png");
var semaphore = new SemaphoreSlim(5);
var tasks = files.Select(async file =>
{
await semaphore.WaitAsync();
try
{
var result = await client.EncodeAsync(file, "© 2025");
Console.WriteLine($"✓ {Path.GetFileName(file)}: PSNR={result.Metadata.Psnr:F1}dB");
return result;
}
finally { semaphore.Release(); }
});
var results = await Task.WhenAll(tasks);
Console.WriteLine($"Watermarked {results.Length} images");Best Practices
Use DI for client registration
Register TruthMarkClient as a singleton in your DI container.
Store keys in User Secrets or Key Vault
Use dotnet user-secrets for development, Azure Key Vault for production.
Don't block async code
Always use await — never .Result or .Wait().