Python
The generated Python SDK: a typed, zero-dependency client built on the standard library, written the way Python developers expect.
The Python SDK shares the SDK feature set: typed payloads and errors, auto-pagination, retries, hooks, validation, webhooks, and streaming. This page covers what is specific to the Python package. Python packages are SDK-only. The CLI and MCP server are TypeScript platforms.
Package
- The distribution and import name derive from your API's title. The Acme API produces
acme, installed withpip install .from the package directory or from PyPI once you publish it. Set a different name per project in the console under package names. pyproject.tomldeclaresdependencies = []andrequires-python >= 3.11. The runtime isurllibonly.- The package ships
py.typed, so type checkers see everyTypedDictandLiteral.
Idioms
- Raise, don't return. Every failure is an exception under
TypeshipError. See Results and errors. - Keyword arguments for bodies. When an operation's request body is an inline object (JSON or form-encoded), its fields become keyword arguments:
client.accounts.create(name="Ops", currency="usd"). When the body is a named schema, an array, or plain text, it stays onebody=argument typed accordingly (AccountWrite,List[AccountWrite],str). If a body field is spelled like a path or query parameter, the whole body steps aside intobody=rather than producing a duplicate argument. - Dicts, typed. Responses are the parsed JSON, typed as
TypedDicts. You readaccount["id"], notaccount.id. There is no conversion layer between you and the wire. - Generators for pages.
for account in client.accounts.list():walks every page.client.accounts.list_page()returns one raw envelope. request_optionsper call. A dict withtimeout,max_retries, andheaders.
Environment variables
The client reads these when the matching option is not passed:
| Variable | Sets |
|---|---|
ACME_TOKEN | bearer_token |
ACME_BASE_URL | base_url |
ACME_WEBHOOK_KEY | webhook_key |
ACME_DEBUG=1 | debug |
A single API key is api_key= and ACME_API_KEY, the same spelling as the TypeScript SDK and the CLI; several keys get one keyword and variable each, named after the header or parameter. Basic auth reads ACME_USERNAME and ACME_PASSWORD. The prefix comes from your package name.
Transport
Pass transport= to replace urllib. A transport is a callable that takes (method, url, headers, body_bytes, timeout) and returns (status, headers, body_bytes). Use it to route through a proxy, a recording layer, or a test double. Streaming endpoints read the response incrementally and go straight to urllib, so they bypass a custom transport.
Webhooks
client.webhooks.unwrap(payload, headers) verifies and parses. unwrap_unsafe parses only. Module-level verify_webhook and sign_webhook are exported for handlers that do not hold a client. Events are TypedDicts discriminated by their type field. WEBHOOK_NAMES and WEBHOOK_SAMPLES list every declared event with a sample payload.
Async
AsyncAcmeClient takes the same options and has the same methods, awaitable: await client.accounts.get(...), and async for over paginated methods and streams. Requests run on the event loop's default executor, so nothing blocks the loop and there is still nothing to install. Both clients are context managers (with / async with) and have close() / aclose().
Uploads
A multipart/form-data field is a keyword argument that accepts raw bytes, an open binary file (its name becomes the filename), or a (filename, data, content_type) tuple; the other fields of the body travel alongside as form parts. A raw binary body (application/octet-stream, image/png, ...) is body= with bytes or a file object, sent under the spec's content type.
GraphQL
A GraphQL schema generates one method per query and mutation field, keyed under client.query and client.mutation. Arguments are keyword arguments and become variables. Every scalar field to depth 2 is selected by default, with a fragment per concrete type for unions and interfaces, and select="{ id name }" overrides that with a raw selection set on methods that return an object. Connection fields paginate like everything else. Errors in a 200 raise GraphQLRequestError (an ApiError) with the raw errors list.
Connections
The default transport pools keep-alive connections per client on http.client, one per scheme/host/port, honoring HTTP_PROXY/HTTPS_PROXY/NO_PROXY. A request that fails on a reused connection before any response arrived is retried once on a fresh one (the server closed an idle keep-alive, the same case Go's net/http retries), so pooling never turns into spurious transport errors. Redirects follow the rules urllib applied.