One API shape in nine languages, and the harness that proves it #3
bucabay
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Shipped June 21, 2026 — 58 cases across 9 languages as of July.
"Official SDKs for every language" usually means one good SDK and eight that drifted. The Go one takes a different argument order, the Ruby one swallows an error the Node one raises, and you find out in production.
We hold all nine to one contract, mechanically, and the harness is in the repo.
The contract is data, not prose
sdks/spec/is the single source of truth:cases.json— 58 cases. Each one names a method, its arguments, the exact HTTP request it must produce, and the value it must return (or the error it must raise).schemas/— JSON Schemas for every request and response shape.api.json— the API surface itself.No SDK owns its own idea of what
send()does. The spec does.How the harness runs
sdks/conformance/run.mjsdoes this for every language:MK_BASE_URL,MK_CASES, andMK_API_KEYin the environment. The runner calls each SDK method with the case's args and prints one JSON line per case —{"name", "result"}or{"name", "error": {status, message}}.Bearercredential,That last one matters as much as the first. Matching the wire format but raising a different error type is still drift.
Nine languages, one command
Node · Python · Ruby · Java · Go · PHP · .NET · Rust · Elixir. Each runs only if its toolchain is on
PATH; the rest report as skipped, and the exit code is non-zero if any runnable SDK fails a case.mailkitemailkite-devmailkitedev.mailkite:mailkitemailkite/mailkiteMailKitemailkitemailkitePlus five client SDKs for apps that talk to us directly over OAuth 2.1 + PKCE — JS, Swift, Kotlin, Flutter, Expo.
What this buys you
You can read the Node examples in our docs and translate them to Rust in your head, and be right. When we add a case, every language has to satisfy it before release — so a fix in one SDK isn't a fix that leaves the other eight behind.
The SDK repos are read-only release mirrors of a private monorepo, so PRs against them can't be merged. If an SDK does something surprising, open a Bug report here with the language and version — the spec is where it gets fixed, which means it gets fixed everywhere at once.
Missing a language you need? Feature requests. The codegen and the harness are the hard part, and both already exist.
All reactions