New: the MailCraft MCP server is live — connect your AI agent in one line. Connect your agent →
All articles

Engineering

One API, Ten SDKs: How We Built MailCraft’s Client Libraries

Node, PHP, Laravel, Python, Ruby, Go, Java, .NET, Rust and Elixir — the same 13 resources, the same error shape, in the idioms each language actually uses.

MailCraft Team · September 27, 2026 · 7 min read

An API is only as easy to use as its worst-documented edge case, and most teams hit that edge case in whatever language they already write in — not the one the API’s docs happen to use for every example. So instead of shipping one official SDK and leaving the rest to community maintainers, we built ten: Node.js, PHP, a Laravel package on top of the PHP SDK, Python, Ruby, Go, Java, .NET, Rust and Elixir.

The same shape, on purpose

Every SDK exposes the same 13 resources the dashboard and REST API are built around: emails, domains, senders, contacts, lists, segments, properties, templates, template folders, campaigns, webhooks, suppressions and metrics. If you've sent an email with the Node SDK, you already know the shape of the Python, Go or Rust client — the method names and parameters follow each language's own conventions, but the resources and what they do don't change underneath you.

One error type, everywhere

MailCraft's API returns two different error shapes depending on what went wrong: a business-rule failure like a plan limit looks like {"error": {"type", "message"}}, while a validation failure looks like {"message", "errors": {"field": [...]}}. Rather than making every caller sniff the response shape, each SDK normalizes both into a single typed error — MailCraftApiError, MailCraftApiException, or the idiomatic equivalent per language — with the status, an optional business-rule type, and field errors all available the same way.

A client you can actually test against

Every SDK accepts an injectable transport instead of hard-wiring a specific HTTP client, and every test suite runs the real client code against that swapped-out transport — a Guzzle client in PHP, httpx.MockTransport in Python, a fake HttpMessageHandler in .NET, a Req adapter in Elixir — rather than mocking the resource layer itself. Go, Java and Rust go a step further and test against an actual local HTTP server, so the request encoding, headers and error decoding are exercised exactly as they would be in production.

Language-native, not lowest-common-denominator

A Python SDK that reads like translated Java helps no one. Each MailCraft SDK leans into what its language does well: the Python client works as a context manager and closes its connection pool on exit; the Rust client returns a typed Result and builds on rustls so it never needs OpenSSL; the Go client threads context.Context through every call for cancellation and timeouts; the Elixir client ships an optional Swoosh adapter so a Phoenix app can send through MailCraft with one line of config, no direct API calls required.

Where things stand

The Node, PHP and Laravel SDKs are published and are the reference implementation the other seven were built against. Python, Ruby, Go, Java, .NET, Rust and Elixir are complete, tested and tagged, and are being published to their registries — PyPI, RubyGems, the Go module proxy, Maven Central, NuGet, crates.io and Hex — over the coming weeks. All ten source repos already live under the mail-craft GitHub organization.

Put it into practice

Start on MailCraft's free plan — 3,000 emails a month, no credit card required.

Start free