Skip to main content

MisarDev Python SDK

Build, ship and run apps on MisarDev from Python — sync and async, from the same client.

PyPI python license

21 resources · 106 methods · 3 SSE streams · 109 operations, each with an async twin

MisarDev turns a prompt into a deployed app. This SDK reaches every public route of its API: create and edit projects, write files, build and deploy them, start from templates, call the OpenAI-compatible chat endpoint, search your code, and read your usage and plan.

Every resource method has an a-prefixed async twin (projects.list / projects.alist) on the same client, so sync and async code share one object. Python 3.9+, httpx the only runtime dependency.


Install

pip

pip install misardev

uv

uv add misardev

Authentication

Create an API key at https://www.misar.dev/settings/api-keys. It starts with mdk_ and is sent as Authorization: Bearer mdk_…. Pass it to the client, or set MISARDEV_API_KEY and construct the client with no arguments.

Every call is checked server-side against the subscription attached to that key. There is no client-side limit checking — the server decides, and the SDK surfaces its answer. A plan refusal carries code: "plan_limit_exceeded", raises PlanLimitError, and is never retried.

import os
from misardev import MisarDev

dev = MisarDev(os.environ["MISARDEV_API_KEY"])
dev = MisarDev()  # same thing: reads MISARDEV_API_KEY

Resources

Every resource the client exposes, and every method on it. Each method also has an a-prefixed async twin — projects.list / projects.alist, chat.completions_stream / chat.acompletions_stream.

Call shape: resource.method(path_params..., required_query..., body=None, query=None, *, headers=None). body exists only where the route reads a JSON body, query only where it takes optional query parameters (a dict keyed by the API's own parameter names).

Build and ship

Resource Methods What it covers
dev.projects add_collaborator, archive, build_status, cancel_build, check_subdomain, create, create_conversation, delete, delete_env, delete_skills, deploy, duplicate, export, get, get_backend, get_deployment, get_domain, get_env, get_knowledge, get_skills, get_tools, import_artifact, list, list_checkpoints, list_collaborators, list_conversations, list_files, provision_backend, remove_collaborator, remove_domain, restore, set_domain, undeploy, update, update_env, update_knowledge, update_skills, update_subdomain, update_tools, write_files, build_stream Projects end to end: create, edit, files, builds, deploys, domains, env vars, collaborators, knowledge, skills, tools, export.
dev.templates create, delete, get, list, remix, update, use Starter templates: browse, create, remix, and start a project from one.
dev.checkpoints delete, restore, update Saved project snapshots: rename, restore, delete.
dev.builds list Recent builds across your projects.

AI

Resource Methods What it covers
dev.chat completions, studio_stream, completions_stream OpenAI-compatible chat completions (plain and streamed) and the studio build conversation stream.
dev.search code, web Web-grounded answers with citations, and search across your own code.
dev.rag clear, index, search Index a project's code for semantic search, query it, clear it.

Connect

Resource Methods What it covers
dev.connectors available, create_connection, delete_connection, list, list_connections, test_connection, toggle, update_connection Connector catalogue, per-account enable state, and per-project connections.
dev.github disconnect, get_connection The linked GitHub account: read it or disconnect it.
dev.skills get, list Your Misar.AI skills library, read-only.

Teams and community

Resource Methods What it covers
dev.organizations accept_invitation, create, create_invitation, list, list_invitations, list_members, remove_member, revoke_invitation, update_member Organizations, members and invitations.
dev.gallery like, list, unlike The public community gallery, and likes.
dev.profile follow, get, unfollow Public builder profiles, follow and unfollow.
dev.notifications list, mark_all_read, mark_read In-app notifications and read state.
dev.reports create Report abusive content.

Account, plan and billing

Resource Methods What it covers
dev.account create_key, delete_key, export, list_keys, update_key Account API keys (with expiry and IP allowlists) and your data export.
dev.api_keys create, delete, list API keys — create, list, revoke.
dev.usage list, plan, track Usage for a period, your plan's allowances, and usage events.
dev.billing checkout, comparison, plans, subscription, switch_plan Plans, plan comparison, subscription, checkout, plan switch.
dev.audit list Your account's audit log.
dev.domains lookup Custom-domain availability lookup.

Client

Thing Detail
Entry point MisarDev(api_key=None, *, base_url=None, max_retries=3, timeout=60.0, headers=None, http_client=None, async_http_client=None, transport=None) — every resource is an attribute on it.
api_key Falls back to MISARDEV_API_KEY; raises MisarDevError pointing at https://www.misar.dev/settings/api-keys when neither is set.
base_url MISARDEV_BASE_URL, else https://api.misar.io/dev.
max_retries Total attempts for a retryable failure. Default 3.
timeout Per-attempt timeout in seconds. Default 60.
http_client / async_http_client / transport Inject your own httpx.Client, httpx.AsyncClient, or an httpx transport such as httpx.MockTransport for tests.
Async await dev.projects.alist() — an a-prefixed twin of every method and stream.
Retried 429 on any verb; 500, 502, 503, 504 and network failures only on GET, HEAD, OPTIONS, PUT, DELETE. Retry-After (seconds or HTTP-date) is honoured, otherwise exponential backoff from 250 ms with jitter, capped at 60 s.
Never retried Plan refusals (code: "plan_limit_exceeded", whatever the status), 5xx on POST/PATCH, and streams.
Errors MisarDevError and its subclasses, all exported from misardev — see Errors.
Escape hatches dev.request(method, path, query=, body=), dev.stream(...), and their arequest / astream twins.
Lifecycle dev.close() / await dev.aclose(), or with MisarDev() as dev: / async with MisarDev() as dev:.

Quick start

from misardev import MisarDev, PlanLimitError

dev = MisarDev()  # MISARDEV_API_KEY

projects = dev.projects.list({"limit": 10})
project = dev.projects.create({"name": "My landing page", "description": "A launch page for my app"})

try:
    dev.projects.deploy(project["project"]["id"], {"target": "misar"})
except PlanLimitError as e:
    print(e.offer["headline"], e.upgrade_url)

Async, from the same client:

import asyncio
from misardev import MisarDev

async def main():
    async with MisarDev() as dev:
        projects = await dev.projects.alist()
        plan = await dev.usage.aplan()

asyncio.run(main())

Primary functions

Create a project

created = dev.projects.create({"name": "Recipe box", "description": "Save and tag recipes"})
project_id = created["project"]["id"]

Write files

dev.projects.write_files(project_id, {
    "files": [
        {"path": "app/page.tsx", "content": "export default function Page() { return <h1>Hi</h1>; }"},
    ],
})
files = dev.projects.list_files(project_id)

Deploy

available = dev.projects.check_subdomain(project_id, "recipe-box")
deployment = dev.projects.deploy(project_id, {"target": "misar", "subdomain": "recipe-box"})
status = dev.projects.get_deployment(project_id)

List templates and start from one

templates = dev.templates.list({"featured": True, "limit": 12})
first = templates["templates"][0]
started = dev.templates.use(first["id"], {"projectName": "From a template"})

OpenAI-compatible chat completion

reply = dev.chat.completions({
    "model": "misar-online",
    "messages": [{"role": "user", "content": "Suggest three names for a recipe app."}],
})
print(reply["choices"][0]["message"]["content"])

Streamed completion

for event in dev.chat.completions_stream({"messages": [{"role": "user", "content": "Write a haiku."}]}):
    print(event.data["choices"][0]["delta"].get("content", ""), end="", flush=True)
hits = dev.search.code({"q": "useAuth", "types": "project,template", "limit": 20})
answers = dev.rag.search(project_id, {"query": "where is the login form?"})

Read usage and plan

plan = dev.usage.plan()
usage = dev.usage.list({"days": 30})

Errors

Every non-2xx answer raises a subclass of MisarDevError. Each carries status, message, code (from body.code or body.error.code), body (the decoded error body) and request_id (the x-request-id header — quote it to support).

Class When
MisarDevError Base class; also raised for any status not listed below, and for a missing API key.
ValidationError 400, 422 — malformed request or failed validation.
AuthenticationError 401 — key missing, revoked, expired, or not a MisarDev key.
PermissionDeniedError 403 — authenticated, but not allowed to touch this resource.
NotFoundError 404 — no such resource, or not one this key can see.
ConflictError 409 — conflicts with current state, e.g. a build already running.
RateLimitError 429 that is an ordinary throttle, after retries; retry_after in seconds.
ServerError 5xx after retries (idempotent verbs) or at once (POST, PATCH).
NetworkError No HTTP answer at all (DNS, TLS, reset, timeout); status == 0, cause is the httpx error.
PlanLimitError Body code == "plan_limit_exceeded", whatever the status. Never retried.
from misardev import MisarDev, MisarDevError, NotFoundError

try:
    dev.projects.get("does-not-exist")
except NotFoundError:
    print("no such project")
except MisarDevError as e:
    print(e.status, e.code, e.message, e.request_id)

Plan limits

The server decides what a key's plan allows, and refuses with an upgrade offer:

Status upgrade.reason Meaning
402 feature_locked The feature is not on the plan.
429 quota_exhausted An allowance is spent until the period resets; Retry-After says when.

Both carry code: "plan_limit_exceeded". The SDK keys on that code rather than the status — a spent quota is a 429 that would otherwise look like an ordinary throttle — and raises PlanLimitError at once, without retrying, because retrying cannot help.

Field Value
offer The full upgrade object exactly as sent, every field kept: headline, plans, cta, usage, urls, …
upgrade_url offer["urls"]["billing"], falling back to offer["urls"]["pricing"].
feature The limit that was hit, e.g. api_access.
current_plan offer["current_plan"]["slug"], e.g. starter.
recommended_plan offer["recommended_plan"], e.g. pro.
retry_after Seconds from Retry-After, for quota_exhausted.
from misardev import PlanLimitError

try:
    dev.projects.deploy(project_id, {"target": "misar"})
except PlanLimitError as e:
    offer = e.offer or {}
    print(offer.get("headline"))
    for plan in offer.get("plans", []):
        print(f"  {plan['name']}: {plan['price']} — {plan.get('unlocks') or ''}")
    print(offer.get("cta"), e.upgrade_url)

Read dev.usage.plan() before an expensive call rather than discovering the ceiling through a refusal.


Streaming

Three routes stream Server-Sent Events. Each stream method yields SSEEvent(event, data, id) — data JSON-decoded when it is JSON, else the raw string — and has an async twin for async for. Streams are never retried: replaying one that failed mid-flight would duplicate whatever you had already read. A frame carrying code: "plan_limit_exceeded" raises PlanLimitError, exactly like the same refusal on a plain call.

Method Route Ends
chat.completions_stream POST /v1/chat/completions At data: [DONE], which is consumed, not yielded. Sets "stream": True in the body for you.
chat.studio_stream POST /chat When the server closes the stream.
projects.build_stream GET /projects/{id}/build-stream When the server closes the stream.
for event in dev.projects.build_stream(project_id):
    print(event.event, event.data)

async for event in dev.chat.acompletions_stream({"messages": [{"role": "user", "content": "hi"}]}):
    print(event.data["choices"][0]["delta"].get("content", ""), end="")

Pagination

Offset-paginated lists (templates, gallery, API keys, …) return one page at a time. dev.paginate(fetch_page, page_size=50, max_items=None) walks them: it calls fetch_page(offset, limit), yields each item — read from the page itself when it is a list, otherwise from its first list-valued field — and stops on a short page.

for template in dev.paginate(lambda offset, limit: dev.templates.list({"offset": offset, "limit": limit})):
    print(template["name"])

async for item in dev.apaginate(lambda offset, limit: dev.gallery.alist({"offset": offset, "limit": limit}), max_items=100):
    print(item)

MIT © Misar.AI

Metadata

Release files for misardev 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for misardev 1.0.0
File Size Uploaded
misardev-1.0.0.tar.gz 32.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for misardev 1.0.0
File Interpreter ABI Platform
misardev-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 75.1 kB

Release files / misardev-1.0.0.tar.gz

Download URL misardev-1.0.0.tar.gz
Size 32.5 kB
Tags Source
SHA-256 checksum
How to use checksums
5e41f65a99b0040961dfda1034ad338fbdae66cbe7374ec94ca2e03615efeaf4
BLAKE2b-256 checksum
How to use checksums
c92aac80707ff213d4026cb5aae013b12659064c55099006fab256c4d38c47d9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / misardev-1.0.0-py3-none-any.whl

Download URL misardev-1.0.0-py3-none-any.whl
Size 42.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f0040bf5a3720074fe14f8c35fcbfc582fb725a814ae24f2166f173fd4aa0e8d
BLAKE2b-256 checksum
How to use checksums
de8668a857453b12d80b56d501bd344d2e80e977cb7be9d93f79dee047597080
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page