C# SDK Guide
Dependencies
Add to your .csproj:
xml
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>Or via NuGet Package Manager:
Install-Package Newtonsoft.JsonBasic Usage
csharp
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using Newtonsoft.Json;
public class KeyClaimClient
{
private readonly string apiKey;
private readonly string secret;
private readonly string baseUrl;
private readonly HttpClient httpClient;
public KeyClaimClient(string apiKey, string secret = null, string baseUrl = "https://keyclaim.org/api")
{
this.apiKey = apiKey;
this.secret = secret ?? apiKey;
this.baseUrl = baseUrl;
this.httpClient = new HttpClient();
}
// Step 1: Create a challenge
public async Task<ChallengeResponse> CreateChallengeAsync(int ttl = 30)
{
var requestBody = new
{
key = apiKey,
ttl = ttl
};
var json = JsonConvert.SerializeObject(requestBody);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync($"{baseUrl}/challenge/create", content);
response.EnsureSuccessStatusCode();
var responseJson = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<ChallengeResponse>(responseJson);
}
// Step 2: Generate response from challenge
// Option A: Simple echo (for testing)
public string GenerateResponseSimple(string challenge)
{
return challenge;
}
// Option B: HMAC-SHA256 (recommended)
public string GenerateResponseHMAC(string challenge)
{
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(challenge));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
// Option C: SHA256 Hash
public string GenerateResponseHash(string challenge)
{
using (var sha256 = SHA256.Create())
{
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(challenge + secret));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
// Step 3: Validate the response
public async Task<ValidationResponse> ValidateAsync(string challenge, string response)
{
var requestBody = new
{
key = apiKey,
challenge = challenge,
response = response
};
var json = JsonConvert.SerializeObject(requestBody);
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
var httpResponse = await httpClient.PostAsync($"{baseUrl}/challenge/validate", content);
var responseJson = await httpResponse.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<ValidationResponse>(responseJson);
if (!httpResponse.IsSuccessStatusCode)
{
result.Valid = false;
}
return result;
}
catch (Exception ex)
{
return new ValidationResponse
{
Valid = false,
Error = ex.Message
};
}
}
// Complete example
public async Task<ValidationResponse> ValidateChallengeAsync(string challenge, string method = "hmac")
{
string response = method switch
{
"echo" => GenerateResponseSimple(challenge),
"hmac" => GenerateResponseHMAC(challenge),
"hash" => GenerateResponseHash(challenge),
_ => throw new ArgumentException($"Unknown method: {method}")
};
return await ValidateAsync(challenge, response);
}
// Response classes
public class ChallengeResponse
{
[JsonProperty("challenge")]
public string Challenge { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
}
public class ValidationResponse
{
[JsonProperty("valid")]
public bool Valid { get; set; }
[JsonProperty("error")]
public string Error { get; set; }
[JsonProperty("signature")]
public string Signature { get; set; }
}
}Usage Example
csharp
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var client = new KeyClaimClient(
apiKey: "kc_your_api_key",
secret: "your-secret-key"
);
try
{
// Create challenge
var challengeResp = await client.CreateChallengeAsync(ttl: 30);
var challenge = challengeResp.Challenge;
Console.WriteLine($"Challenge: {challenge}");
// Generate response
var response = client.GenerateResponseHMAC(challenge);
Console.WriteLine($"Response: {response}");
// Validate
var result = await client.ValidateAsync(challenge, response);
Console.WriteLine($"Valid: {result.Valid}");
if (result.Valid)
{
Console.WriteLine("✓ Challenge validated successfully!");
if (!string.IsNullOrEmpty(result.Signature))
{
Console.WriteLine($"Signature: {result.Signature}");
}
}
else
{
Console.WriteLine($"✗ Validation failed: {result.Error}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}Response Generation Methods
Method 1: Echo (Testing)
csharp
public string GenerateResponseEcho(string challenge)
{
return challenge;
}Method 2: HMAC-SHA256 (Recommended)
csharp
public string GenerateResponseHMAC(string challenge)
{
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(challenge));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}Method 3: SHA256 Hash
csharp
public string GenerateResponseHash(string challenge)
{
using (var sha256 = SHA256.Create())
{
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(challenge + secret));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}Explore Other Documentation
Choose your preferred programming language

Node.js Documentation
JavaScript/TypeScript integration guide
View Guide→

Python Documentation
Python 3.7+ integration guide
View Guide→

PHP Documentation
PHP 7.4+ integration guide
View Guide→

Java Documentation
Java 8+ integration guide
View Guide→

Kotlin Documentation
Kotlin/JVM integration guide
View Guide→

Go Documentation
Go 1.18+ integration guide
View Guide→