Misar Docs
MisarMailMisar.BlogMisarReachMisarPostMisar.DevMisar PlatformMisar IdentityMisar Posts API
Sdks

Python SDK

Install and use the official MisarBlog Python SDK to publish and manage blog content programmatically.

Installation

pip install misar-blog

Authentication

import os
from misar_blog import MisarBlogClient

client = MisarBlogClient(api_key=os.environ["MISARBLOG_API_KEY"])

Generate an API key at misar.blog/dashboard/api-keys. See the Authentication guide for key scopes.


Profile

# Get your profile
me = client.me.get()
print(me.username)
print(me.display_name)
print(me.follower_count)

Articles

List articles

result = client.articles.list(limit=20, offset=0)
for article in result.data:
    print(article.title, article.slug)

Get a single article

article = client.articles.get("my-first-article")  # slug
print(article.title)
print(article.content_html)
print(article.tags)

Publish an article

article = client.articles.publish(
    title="Getting Started with MisarBlog API",
    content="## Introduction\n\nThis guide covers...",
    excerpt="A practical intro to building with the MisarBlog Python SDK.",
    tags=["python", "api", "tutorial"],
    featured_image_url="https://example.com/cover.jpg",
)
print("Published:", article.slug)

Delete an article

client.articles.delete("my-first-article")  # slug

Drafts

# Save a new draft
draft = client.drafts.save(
    title="Work in Progress",
    content="## Introduction\n\nComing soon...",
    tags=["draft", "wip"],
)
print("Draft saved:", draft.id)

Series

# List all series
series_list = client.series.list()

# Create a series
new_series = client.series.create(
    title="Python for Bloggers",
    description="A 5-part series on building blog tools with Python.",
)

# Add an article to a series
client.series.add_article(
    series_slug=new_series.slug,
    article_slug="getting-started-with-misarblog-api",
)

AI Tools

# Generate title suggestions from a topic
titles = client.ai.suggest_titles(topic="productivity hacks for developers")
for title in titles:
    print(title)

# AI research — returns structured Markdown with citations
research = client.ai.research(topic="Next.js App Router caching strategies")
print(research.content)  # Markdown string

Images

# Upload a cover image from a local file
with open("cover.jpg", "rb") as f:
    result = client.images.upload(f, content_type="image/jpeg")
print("Cover URL:", result.url)

# Generate an AI cover image
result = client.images.generate(
    prompt="Abstract geometric pattern in green and white",
    style="digital-art",
    aspect_ratio="16:9",
)
print("Generated URL:", result.url)

Analytics

stats = client.analytics.get()
print(f"Total views: {stats.total_views}")
print(f"Subscribers: {stats.subscriber_count}")
print(f"Revenue (USD cents): {stats.revenue_cents}")

API Keys

# List your API keys
keys = client.keys.list()
for key in keys.keys:
    print(key.name, key.last_used_at)

# Create a new key
new_key = client.keys.create(name="CI/CD Key", scopes=["articles:write"])
print("New key:", new_key.key)  # shown once

# Revoke a key
client.keys.revoke(key_id="key-uuid")

Webhook Integration

The Python SDK can also help you build webhook receiver endpoints. See the Webhooks reference for the full payload schema.

from fastapi import FastAPI, Request

app = FastAPI()

@app.post("/webhook")
async def receive_webhook(request: Request):
    event = request.headers.get("x-webhook-event")
    payload = await request.json()

    if event == "article.published":
        print("New article:", payload["article"]["title"])
    elif event == "article.updated":
        print("Updated:", payload["article"]["slug"])
    elif event == "article.deleted":
        print("Deleted:", payload["article"]["id"])

    return {"ok": True}

Error Handling

from misar_blog.exceptions import MisarBlogAPIError, MisarBlogNetworkError

try:
    article = client.articles.get("non-existent-slug")
except MisarBlogAPIError as e:
    if e.status_code == 401:
        print("Invalid or expired API key")
    elif e.status_code == 404:
        print("Article not found")
    elif e.status_code == 429:
        print(f"Rate limited. Retry after {e.retry_after}s")
    else:
        print(f"API error {e.status_code}: {e.message}")
except MisarBlogNetworkError as e:
    print(f"Network error: {e}")

Configuration

client = MisarBlogClient(
    api_key="mbk_your_api_key",
    base_url="https://api.misar.io/blog",  # default
    timeout=30,                              # seconds, default 30
)