Matter Docs
Overview
Official Matter client libraries — strongly typed, idempotent, version-pinned. Generated from the canonical OpenAPI spec, hand-finished for each language's idioms.
Last updated
SDKs.
Official client libraries for Node, Python, and Go. Generated from the canonical OpenAPI spec, hand-finished for each language's idioms. Strongly typed, idempotent by default, version-pinned at construction.
TL;DR. Three official SDKs — @mattermode/node, matter-sdk (Python), and
github.com/matterhq/matter-go. All generated from apps/docs/api-reference/openapi.yaml,
all type-safe, all idempotency-aware. Auto-paginators, typed errors, signed-webhook
helpers, and SSE streaming come standard. Currently Beta — pin a minor version.
The SDKs are thin wrappers around the JSON REST API. They handle the boring parts —
header construction, idempotency-key generation, exponential backoff, cursor pagination,
SSE framing, HMAC signature verification — and stay out of your way for everything else.
Every typed ID prefix in the API (ent_, tok_, flg_, …) becomes a branded type in
the SDK so a DocumentId cannot be passed where an EntityId is expected. The
OpenAPI Generator produces the wire stubs; a hand-finishing
pass adds the helpers and idiomatic types each language community expects (e.g. async
iterators in Node, httpx.AsyncClient in Python, context.Context in Go).
When to use an SDK vs raw HTTP
Use an SDK in application code where typed clients accelerate development and the helpers (auto-pagination, signature verification, exponential backoff) save real work. Use raw HTTP in shell scripts, generic API gateways, polyglot environments where adding a Matter dependency to every service is overkill, or when you need a language that doesn't have an official SDK yet — every endpoint is plain JSON over HTTPS, so the curl examples port directly to anything that speaks the Fetch API.
Install
# No install — Matter is a JSON REST API. The SDKs exist to spare you the
# idempotency-key / version-pin / backoff plumbing, not to gate access.
curl https://api.mattermode.com/v1/entities \
-H "Authorization: Bearer sk_test_..." \
-H "Matter-Version: 2026-05-01" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"jurisdiction":"US-DE","legal_name":"Waypoint Systems, Inc."}'npm i @mattermode/node
# or: pnpm add @mattermode/node
# or: bun add @mattermode/nodepip install matter-sdk
# or: uv add matter-sdk
# or: poetry add matter-sdkgo get github.com/matterhq/matter-goComparison
| Language | Package | Min runtime | ID types | Async style | Streaming | Webhooks helper |
|---|---|---|---|---|---|---|
| Node / TypeScript | @mattermode/node | Node 20+ | Branded string types | async / await | AsyncIterable<Event> | verifySignature |
| Python | matter-sdk | Python 3.11+ | NewType-aliased str | asyncio + sync facade | async for event in … | verify_signature |
| Go | github.com/matterhq/matter-go | Go 1.22+ | Defined type … string | context.Context | for ev := range stream.C() | webhook.Verify |
All three SDKs:
- Pin
Matter-Versionat client construction. No implicit "latest." - Auto-generate UUID v4
Idempotency-Keyheaders unless you supply one. - Surface
202 Acceptedas a typed pending resource — async by default is the contract, not an SDK opinion. - Retry
429and5xxwith full exponential backoff and jitter, honoringretry_after. - Map every RFC 7807
typeURI to a typed exception class. - Ship branded ID types so resource-level type confusion is a compile-time error (TypeScript, Go) or a runtime check at the boundary (Python).
Languages
Node / TypeScript
@mattermode/node. Discriminated unions on expand[], full type narrowing, Edge-runtime
safe. Targets Node 20+, Bun, Deno, and Workers.
Python
matter-sdk. Pydantic models for every resource, sync and async clients, optional
httpx-backed transport. Targets Python 3.11+.
Go
github.com/matterhq/matter-go. context.Context everywhere, error wrapping via
errors.As, idiomatic option-functions. Targets Go 1.22+.
Patterns
The five cross-language patterns most teams hit on day one. Each page shows the same behavior in all three SDKs, side by side, with the JSON REST equivalent for reference.
Error handling
Typed error hierarchy mapped to RFC 7807. Catch MatterValidationError separately
from MatterRateLimitError. Retry policy by error class.
Webhooks
Receiver helpers per language — Express, Flask, net/http. Constant-time HMAC
signature verification. Replay-safe handlers.
Pagination
for await auto-paginators across pages, manual cursor for backpressure. Memory
considerations for long lists.
Expand
Type-safe ?expand[]=… usage. TypeScript narrows the response type at compile time;
Python and Go narrow at runtime.
Agents
Creating tier-3 / tier-4 tokens, handling the Authorization pause, verifying
dual-attribution events.
What the SDKs do not do
- They do not hide the contract.
202 Acceptedstays202 Accepted. The pending resource is what you receive — terminal outcomes still arrive via webhooks. No SDK has a "wait until done" helper that polls for you. (See async by default.) - They do not auto-pin a version. You pass
Matter-Versionat construction. The SDK refuses to start without it — implicit version drift in long-lived applications would silently change behavior across deployments. - They do not retry on
4xx. Only429and5xxare retried. A400is a bug in your code; a409is a state conflict — neither retries safely. - They do not deserialize PDFs.
Document.pdf_urlis a presigned URL; download it yourself. The structured JSON twin (Document.data) is what the SDK exposes as a typed object. - They do not bundle credentials. No SDK reads from
process.env.MATTER_API_KEYor similar by default. Pass the key explicitly. Implicit env reads have caused too many prod-mode-on-localhost incidents.
Generation pipeline
Each SDK lives in its own repo and regenerates on every OpenAPI release. The pipeline:
- Matter publishes a new spec version to
apps/docs/api-reference/openapi.yaml. - CI runs
bun run sdks:bumpwhich invokes the per-language generator. - Generated diff lands in a PR. Hand-written code (idempotency, transport, error shaping) lives outside the generated boundary and is preserved.
- Each SDK ships a minor version per spec release. Major versions ship only on breaking client-shape changes (rare).
The generator is apps/api/scripts/generate-mcp-tools.ts for the MCP server and a
similar pipeline for each SDK repo. Hand-authored API-backed clients are not accepted.
Status
All three SDKs are Beta. Shape is stable; surface area grows as the OpenAPI
spec grows. We follow semver — pin a minor version (^0.7.0) until 1.0. Track
releases at /changelog.