MisarMisar Docs
MisarMailMisarBlogMisarReachMisarPostMisarDevMisarCoderMisarSEOMisar PlatformMisar SSO
SDKs

PHP SDK

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

The PHP SDK ships a full client for the developer API (https://api.misar.io/blog/v1) plus the iframe embed helpers, in the misarblog/sdk package (v1.0.0).

Installation

composer require misarblog/sdk

API Client

MisarBlog\Client 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 returns the decoded response as an array. Retryable statuses (429, 500, 502, 503, 504) are retried with exponential back-off.

use MisarBlog\Client;

$blog = new Client('mbk_YOUR_KEY');

// Override the base URL if needed
$staging = new Client('mbk_YOUR_KEY', 'https://api.misar.io/blog/v1');

Articles

// List your articles
$result = $blog->articles->list(['status' => 'published', 'limit' => 20]);
foreach ($result['articles'] as $a) {
    echo $a['title'], ' ', $a['url'], PHP_EOL;
}

// Get one by slug (or UUID)
$article = $blog->articles->get('my-first-article');

// Publish
$created = $blog->articles->publish([
    'title'           => 'Getting Started with the MisarBlog API',
    'body_markdown'   => "## Introduction\n\nThis guide covers…",
    'tags'            => ['php', 'api'],
    'cover_image_url' => 'https://example.com/cover.jpg',
    'visibility'      => 'public',
]);

// Save a draft, then update / publish it
$draft = $blog->articles->createDraft([
    'title' => 'Work in progress', 'body_markdown' => '## Soon…',
]);
$blog->articles->update($draft['slug'], ['publish' => true]);

Other resources

$blog->series->list();
$blog->series->create('A Series', 'Optional');

$blog->ai->titles('seo', 'best AI writing tools 2026');
$blog->ai->complete('Tighten this intro: …', 'You are an editor.', 300);

$blog->images->generate('A minimalist cover', '1792x1024');

$blog->search->query(['q' => 'react', 'type' => 'articles', 'sort' => 'newest']);
$blog->recommendations->get($articleId, 5);

$blog->analytics->get(30);
$blog->profile->get();     // GET /me
$blog->plan->get();
$blog->trial->status();

$blog->reactions->get($articleId);
$blog->reactions->add($articleId, 'like');     // "like" | "clap" | "bookmark"
$blog->reactions->remove($articleId, 'like');

Resources

ResourceMethods
$blog->articleslist · get · publish · update · createDraft
$blog->serieslist · create · addArticle
$blog->aititles · complete
$blog->imagesgenerate · upload
$blog->searchquery
$blog->recommendationsget
$blog->analyticsget
$blog->profileget — GET /me
$blog->planget
$blog->trialstatus · start
$blog->reactionsget · add · remove
$blog->upsellfunnel — platform-admin only

Error handling

use MisarBlog\ApiError;

try {
    $blog->articles->get('missing-slug');
} catch (ApiError $err) {
    echo $err->status, ' ', $err->getMessage(); // + $err->requiredScope / $err->grantedScopes on 403
}

MisarBlog\NetworkError (an ApiError with status === 0) is thrown when the request never completes or retries are exhausted.

Embed helpers

The no-key iframe helpers are static:

use MisarBlog\Embed;
use MisarBlog\Auth;

// Profile embed
$url = Embed::url('johndoe');

// Single-post embed with a theme
$postUrl = Embed::url('johndoe', 'my-first-post', 'dark');

// For gated (paywalled) embeds, refresh the session token
$result = Auth::refreshToken('current-session-token');
echo $result['token'], ' ', $result['expiresAt'];

MisarBlog\Embed::url(string $username, ?string $slug = null, string $theme = 'auto'): string returns a public embed-viewer URL. MisarBlog\Auth::refreshToken(string $token, string $baseUrl = 'https://misar.blog'): array returns the new token payload, or throws \RuntimeException on a non-200 response.