Skip to main content
July 2026

Python SDK

A fully typed Python client, synchronous and asynchronous, with scheduled-send management and webhook signature verification. Python 3.12 and later.

mailkube is the official Python client, licensed Apache-2.0. pip install mailkube or uv add mailkube, set an API key, and the first message is a few lines.

Mailkube and AsyncMailkube carry the same methods. Switching a service from sync to async is a new constructor and an await.

from mailkube import Mailkube

with Mailkube() as client:
    email = client.emails.send(
        from_="Acme <hello@yourdomain.com>",
        to="customer@example.com",
        subject="Hello world",
        html="<p>It works!</p>",
    )
    print("sent:", email.id)

from_ carries a trailing underscore because from is a Python keyword. The SDK maps it to the wire field for you.

What it handles for you

Failures raise a subclass of MailkubeError, and one except is a real backstop. RateLimitError carries .retry_after, which turns backoff into a value rather than a policy you invent. Every API error carries .error_name, .status_code and .request_id for the support thread.

mailkube.verify(raw_body, headers, signing_secret) checks a webhook signature. It is a plain function, standing outside the client and the HTTP layer. A Flask receiver and a FastAPI one differ only in how each hands you the raw bytes. An event type newer than your installed version arrives as UnknownEvent instead of raising.

Pass scheduled_at to emails.send and the message queues. client.scheduled_emails manages it from there, including iter_all. That one is a generator: ask for the first five and it fetches one page, not the campaign.

Installing the Python client

  1. Install the SDK: pip install mailkube
  2. Set your key as MAILKUBE_API_KEY, or pass api_key= to the client
  3. Send a first message with client.emails.send(...)
  4. Verify an inbound webhook with mailkube.verify(...)

Reuse one client for the life of the process. The sync client is thread-safe, and the async one belongs to the event loop that created it. The Python SDK docs(opens in a new tab) cover attachments, reply threading, idempotency and the full error reference.