MisarMisar Docs
MisarMailMisarBlogMisarReachMisarPostMisarDevMisarCoderMisarSEOMisar PlatformMisar SSO
SDKs

C# SDK

Publish articles, manage series, and run AI tools with the MisarBlog C# SDK, plus post-embed helpers.

The C# SDK ships a full async client for the developer API (https://api.misar.io/blog/v1) plus the iframe embed helpers, in the Misar.Blog NuGet package (v1.0.0).

Installation

dotnet add package Misar.Blog

API Client

MisarBlogClient authenticates with an mbk_ key (or an OAuth 2.1 access token) and defaults to https://api.misar.io/blog/v1 (the gateway strips /api). Every method is async and returns a JsonElement. Retryable statuses (429, 500, 502, 503, 504) are retried with exponential back-off. The client is IDisposable.

using MisarBlog;

using var blog = new MisarBlogClient("mbk_YOUR_KEY");

// Override the base URL if needed
using var staging = new MisarBlogClient(
    "mbk_YOUR_KEY",
    baseUrl: "https://api.misar.io/blog/v1");

Articles

// List your articles
JsonElement result = await blog.Articles_ListAsync(status: "published", limit: 20);
foreach (var a in result.GetProperty("articles").EnumerateArray())
    Console.WriteLine($"{a.GetProperty("title")} {a.GetProperty("url")}");

// Get one by slug (or UUID)
JsonElement article = await blog.Articles_GetAsync("my-first-article");

// Publish
JsonElement created = await blog.Articles_PublishAsync(new
{
    title = "Getting Started with the MisarBlog API",
    body_markdown = "## Introduction\n\nThis guide covers…",
    tags = new[] { "csharp", "api" },
    cover_image_url = "https://example.com/cover.jpg",
    visibility = "public",
});

// Save a draft, then update / publish it
JsonElement draft = await blog.Articles_CreateDraftAsync(new
{
    title = "Work in progress", body_markdown = "## Soon…",
});
await blog.Articles_UpdateAsync(draft.GetProperty("slug").GetString()!, new { publish = true });

Other resources

await blog.Series_ListAsync();
await blog.Series_CreateAsync("A Series", description: "Optional");

await blog.Ai_TitlesAsync(action: "seo", prompt: "best AI writing tools 2026");
await blog.Ai_CompleteAsync("Tighten this intro: …", system: "You are an editor.", maxTokens: 300);

await blog.Images_GenerateAsync("A minimalist cover", size: "1792x1024");

await blog.SearchAsync(q: "react", type: "articles", sort: "newest");
await blog.Recommendations_GetAsync(articleId, limit: 5);

await blog.Analytics_GetAsync(days: 30);
await blog.Profile_GetAsync();     // GET /me
await blog.Plan_GetAsync();
await blog.Trial_StatusAsync();

await blog.Reactions_GetAsync(articleId);
await blog.Reactions_AddAsync(articleId, "like");     // "like" | "clap" | "bookmark"
await blog.Reactions_RemoveAsync(articleId, "like");

Methods

GroupMethods
ArticlesArticles_ListAsync · Articles_GetAsync · Articles_PublishAsync · Articles_UpdateAsync · Articles_CreateDraftAsync
SeriesSeries_ListAsync · Series_CreateAsync · Series_AddArticleAsync
AIAi_TitlesAsync · Ai_CompleteAsync
ImagesImages_GenerateAsync · Images_UploadAsync
Search / RecommendationsSearchAsync · Recommendations_GetAsync
AnalyticsAnalytics_GetAsync
AccountProfile_GetAsync (GET /me) · Plan_GetAsync · Trial_StatusAsync · Trial_StartAsync
ReactionsReactions_GetAsync · Reactions_AddAsync · Reactions_RemoveAsync
UpsellUpsell_FunnelAsync — platform-admin only

Error handling

try
{
    await blog.Articles_GetAsync("missing-slug");
}
catch (MisarBlogException ex)
{
    Console.Error.WriteLine($"{ex.Status}: {ex.Message}"); // + RequiredScope / GrantedScopes on 403
}

MisarBlogNetworkException (a MisarBlogException with Status == 0) is thrown when the request never completes or retries are exhausted.

Embed helpers

The no-key iframe helpers are static:

using MisarBlog;

// Profile embed
var url = Embed.Url("johndoe");

// Single-post embed with a theme
var postUrl = Embed.Url("johndoe", slug: "my-first-post", theme: "dark");

// For gated (paywalled) embeds, refresh the session token
TokenResult result = await Auth.RefreshToken("current-session-token");
Console.WriteLine($"{result.Token} {result.ExpiresAt}");

static string Embed.Url(string username, string? slug = null, string theme = "auto") returns a public embed-viewer URL. static Task<TokenResult> Auth.RefreshToken(string token, string baseUrl = "https://misar.blog", HttpClient? client = null) returns a TokenResult(Token, ExpiresAt); it throws on a non-success status.