// Primenza C# SDK v1 using System.Net.Http.Headers; using System.Text; using System.Text.Json; namespace Primenza.Sdk; public class PrimenzaClient : IDisposable { private readonly HttpClient _client; private readonly string _baseUrl; private readonly string _apiKey; public PrimenzaClient(string apiKey, string baseUrl = "https://primenza.com/api/v1") { _apiKey = apiKey; _baseUrl = baseUrl.TrimEnd('/'); _client = new HttpClient(); _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); _client.DefaultRequestHeaders.Add("X-API-Key", apiKey); _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); } private JsonElement Unwrap(JsonDocument doc) { var root = doc.RootElement; if (root.TryGetProperty("errors", out var errors) && errors.GetArrayLength() > 0) { throw new InvalidOperationException(errors[0].GetProperty("message").GetString() ?? "API request failed"); } return root.TryGetProperty("data", out var data) ? data : root; } public async Task GetAsync(string path) { var response = await _client.GetAsync($"{_baseUrl}{path}"); response.EnsureSuccessStatusCode(); using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); return Unwrap(json); } public async Task PostAsync(string path, object? body = null) { var content = body != null ? new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json") : null; var response = await _client.PostAsync($"{_baseUrl}{path}", content); response.EnsureSuccessStatusCode(); using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); return Unwrap(json); } public async Task PatchAsync(string path, object? body = null) { var content = body != null ? new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json") : null; var request = new HttpRequestMessage(HttpMethod.Patch, $"{_baseUrl}{path}") { Content = content }; var response = await _client.SendAsync(request); response.EnsureSuccessStatusCode(); using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); return Unwrap(json); } public async Task DeleteAsync(string path) { var response = await _client.DeleteAsync($"{_baseUrl}{path}"); response.EnsureSuccessStatusCode(); using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); return Unwrap(json); } public async Task PutAsync(string path, object? body = null) { var content = body != null ? new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json") : null; var response = await _client.PutAsync($"{_baseUrl}{path}", content); response.EnsureSuccessStatusCode(); using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); return Unwrap(json); } public Task Dashboard(int? domainId = null) => GetAsync("/dashboard" + (domainId.HasValue ? $"?domain_id={domainId}" : "")); public Task Domains() => GetAsync("/domains"); public Task Domain(int domainId) => GetAsync($"/domains/{domainId}"); public Task CreateDomain(string url, string? name = null) => PostAsync("/domains", new { url, name }); public Task UpdateDomain(int domainId, object fields) => PatchAsync($"/domains/{domainId}", fields); public Task Crawl(int domainId) => PostAsync($"/domains/{domainId}/crawl"); public Task Audit(int domainId) => PostAsync($"/domains/{domainId}/audit"); public Task Seo(int domainId) => GetAsync($"/domains/{domainId}/seo"); public Task RunSeo(int domainId) => PostAsync($"/domains/{domainId}/seo/run"); public Task Geo(int domainId) => GetAsync($"/domains/{domainId}/geo"); public Task RunGeo(int domainId) => PostAsync($"/domains/{domainId}/geo/run"); public Task AiVisibility(int domainId) => GetAsync($"/domains/{domainId}/ai-visibility"); public Task RunAiVisibility(int domainId) => PostAsync($"/domains/{domainId}/ai-visibility/run"); public Task Performance(int domainId) => GetAsync($"/domains/{domainId}/performance"); public Task RunPerformance(int domainId) => PostAsync($"/domains/{domainId}/performance/run"); public Task Links(int domainId) => GetAsync($"/domains/{domainId}/links"); public Task RunLinks(int domainId) => PostAsync($"/domains/{domainId}/links/run"); public Task ContentGaps(int domainId) => GetAsync($"/domains/{domainId}/content-gaps"); public Task DiscoverContentGaps(int domainId) => PostAsync($"/domains/{domainId}/content-gaps/discover"); public Task DeleteDomain(int domainId) => DeleteAsync($"/domains/{domainId}"); public Task VerifyDomain(int domainId) => PostAsync($"/domains/{domainId}/verify"); public Task DetectTech(int domainId) => PostAsync($"/domains/{domainId}/detect-tech"); public Task Pages(int domainId, int page = 1) => GetAsync($"/domains/{domainId}/pages?page={page}"); public Task Audits(int domainId) => GetAsync($"/domains/{domainId}/audits"); public Task Schema(int domainId) => GetAsync($"/domains/{domainId}/schema"); public Task Robots(int domainId) => GetAsync($"/domains/{domainId}/robots"); public Task DeployRobots(int domainId) => PostAsync($"/domains/{domainId}/robots/deploy"); public Task DeployLlms(int domainId, string type = "llms") => PostAsync($"/domains/{domainId}/llms-txt/deploy", new { type }); public Task Competitors(int domainId) => GetAsync($"/domains/{domainId}/competitors"); public Task AddCompetitor(int domainId, string url) => PostAsync($"/domains/{domainId}/competitors", new { url }); public Task RefreshCompetitor(int domainId, int competitorId) => PostAsync($"/domains/{domainId}/competitors/{competitorId}/refresh"); public Task RemoveCompetitor(int domainId, int competitorId) => DeleteAsync($"/domains/{domainId}/competitors/{competitorId}"); public Task Tenant() => GetAsync("/tenant"); public Task Schedules() => GetAsync("/schedules"); public Task KnowledgeGraph(int domainId) => GetAsync($"/domains/{domainId}/knowledge-graph"); public Task BuildKnowledgeGraph(int domainId) => PostAsync($"/domains/{domainId}/knowledge-graph/build"); public Task Citation(int domainId) => GetAsync($"/domains/{domainId}/citation"); public Task DeployPreview(int domainId, string artifact = "robots") => GetAsync($"/domains/{domainId}/deploy/preview?artifact={artifact}"); public Task Agents(int domainId) => GetAsync($"/domains/{domainId}/agents"); public Task RegisterAgent(int domainId, string name, string type) => PostAsync($"/domains/{domainId}/agents", new { name, type }); public Task TestWebhook() => PostAsync("/webhooks/test"); public Task Monitoring(int domainId) => GetAsync($"/domains/{domainId}/monitoring"); public Task Reports(int domainId) => GetAsync($"/domains/{domainId}/reports"); public Task GraphQL(string query, object? variables = null) => PostAsync("/graphql", new { query, variables }); public Task CreateSchedule(object data) => PostAsync("/schedules", data); public Task UpdateSchedule(int id, object data) => PatchAsync($"/schedules/{id}", data); public Task DeleteSchedule(int id) => DeleteAsync($"/schedules/{id}"); public Task Workspaces() => GetAsync("/workspaces"); public Task CreateWorkspace(object data) => PostAsync("/workspaces", data); public Task UpdateWorkspace(int id, object data) => PatchAsync($"/workspaces/{id}", data); public Task DeleteWorkspace(int id) => DeleteAsync($"/workspaces/{id}"); public Task Team() => GetAsync("/team"); public Task InviteTeamMember(object data) => PostAsync("/team/invitations", data); public Task UpdateTeamRole(int userId, string role) => PatchAsync($"/team/{userId}", new { role }); public Task RemoveTeamMember(int userId) => DeleteAsync($"/team/{userId}"); public Task CancelInvitation(int invitationId) => DeleteAsync($"/team/invitations/{invitationId}"); public Task Settings() => GetAsync("/settings"); public Task UpdateSettings(object data) => PatchAsync("/settings", data); public Task CreateApiKey(object data) => PostAsync("/api-keys", data); public Task DeleteApiKey(int id) => DeleteAsync($"/api-keys/{id}"); public Task AuditLogs(string query = "") => GetAsync("/audit-logs" + (query != "" ? $"?{query}" : "")); public Task Notifications() => GetAsync("/notifications"); public Task MarkNotificationRead(int id) => PostAsync($"/notifications/{id}/read"); public Task MarkAllNotificationsRead() => PostAsync("/notifications/read-all"); public Task RegenerateVerification(int domainId) => PostAsync($"/domains/{domainId}/verification/regenerate"); public Task UpdateVerificationMethod(int domainId, string method) => PatchAsync($"/domains/{domainId}/verification-method", new { method }); public Task ActivateDomain(int domainId) => PostAsync($"/domains/{domainId}/activate"); public Task GenerateContentGapOutline(int domainId, int gapId) => PostAsync($"/domains/{domainId}/content-gaps/{gapId}/outline"); public Task GenerateContentGapArticle(int domainId, int gapId) => PostAsync($"/domains/{domainId}/content-gaps/{gapId}/article"); public Task DismissContentGap(int domainId, int gapId) => PostAsync($"/domains/{domainId}/content-gaps/{gapId}/dismiss"); public Task ContentOptimizer(int domainId) => GetAsync($"/domains/{domainId}/content-optimizer"); public Task RefreshContentOptimizer(int domainId) => PostAsync($"/domains/{domainId}/content-optimizer/refresh"); public Task SimulateAiVisibility(int domainId, object? data = null) => PostAsync($"/domains/{domainId}/ai-visibility/simulate", data ?? new { }); public Task InstallAgent(int domainId, object data) => PostAsync($"/domains/{domainId}/agents/install", data); public Task GenerateSchema(int domainId, object? data = null) => PostAsync($"/domains/{domainId}/schema/generate", data ?? new { }); public Task DeploySchema(int domainId, object? data = null) => PostAsync($"/domains/{domainId}/schema/deploy", data ?? new { }); public Task UpdateRobots(int domainId, string content) => PutAsync($"/domains/{domainId}/robots", new { content }); public Task GenerateLlms(int domainId, string type = "llms") => PostAsync($"/domains/{domainId}/llms-txt/generate", new { type }); public Task StoreSubdomain(int domainId, object data) => PostAsync($"/domains/{domainId}/subdomains", data); public Task DestroySubdomain(int domainId, int subdomainId) => DeleteAsync($"/domains/{domainId}/subdomains/{subdomainId}"); public Task DownloadReport(int domainId) => GetAsync($"/domains/{domainId}/reports/download"); public Task DownloadReportPdf(int domainId) => GetAsync($"/domains/{domainId}/reports/download/pdf"); public Task SuggestCitation(int domainId, int pageId, object? data = null) => PostAsync($"/domains/{domainId}/citation/{pageId}/suggest", data ?? new { }); public Task ApproveAgentCommand(int domainId, int commandId) => PostAsync($"/domains/{domainId}/agents/commands/{commandId}/approve"); public void Dispose() => _client.Dispose(); } public class PrimenzaAgentClient : IDisposable { private readonly HttpClient _client; private readonly string _baseUrl; private readonly string _agentToken; public PrimenzaAgentClient(string agentToken, string baseUrl = "https://primenza.com/api/v1") { _agentToken = agentToken; _baseUrl = baseUrl.TrimEnd('/'); _client = new HttpClient(); _client.DefaultRequestHeaders.Add("X-Agent-Token", agentToken); _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); } private JsonElement Unwrap(JsonDocument doc) { var root = doc.RootElement; if (root.TryGetProperty("errors", out var errors) && errors.GetArrayLength() > 0) { throw new InvalidOperationException(errors[0].GetProperty("message").GetString() ?? "API request failed"); } return root.TryGetProperty("data", out var data) ? data : root; } private async Task PostAsync(string path, object? body = null) { var content = body != null ? new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json") : null; var response = await _client.PostAsync($"{_baseUrl}{path}", content); response.EnsureSuccessStatusCode(); using var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); return Unwrap(json); } public Task Poll() => PostAsync("/agent/poll"); public Task Report(int commandId, object result) => PostAsync("/agent/report", new { command_id = commandId, result }); public void Dispose() => _client.Dispose(); }