Files
zeekay 4998a916fd the client sends the credential the document now declares
hanzoai/cloud@113cf7d6 declares components.securitySchemes.bearer and applies it
document-wide, so regenerating writes a populated Configuration.auth_settings()
and auth_settings=['bearer'] into 2498 call sites; ApiClient._apply_auth_params
sets Authorization: Bearer <token> from access_token, which was read by nothing
before. Four call sites carry an empty list — exactly the operations the document
marks security: [] (get_models, get_models_providers, get_commands,
get_openapi_json) — so the public routes still go out with no credential.

examples/client.py drops the header_name/header_value compensation and passes
access_token. examples/models is a new flow on the public catalog: it runs before
a reader has a key, which makes the install checkable in one command.

Proven on api.hanzo.ai, not by reading: examples.models prints 112 models with no
credential; examples.hello returns the caller's keys with a real sk- and 403
"sign in to manage API keys" with a bogus one.
2026-08-14 17:22:30 -07:00

54 lines
2.2 KiB
Python

"""models — the catalog, with no credential at all.
``GET /v1/models`` (operationId ``get_models``): every model the router can
reach, with its owner and its per-token price.
This is the flow that runs before you have a key, and the only one that can. The
document marks four of its 2479 operations ``security: []`` and this is one of
them: the catalog is the same for every caller, so the operation takes no
principal and the generated method sends no ``Authorization`` header. That is
visible in the generated code — ``_get_models_serialize`` carries an empty
``_auth_settings``, where all 2498 other call sites carry ``['bearer']``.
So this doubles as the install check. If it prints a count, the package imports,
the host resolves, and the client speaks the API. If it prints a count when you
expected a refusal, that is not a broken key — this route never looks at one.
The payload is read through the generated ``*_without_preload_content`` variant
because the operation declares no response ``content``: 834 of the document's
operations model no body, so the typed method returns None. It becomes an
ordinary typed call the day the schema lands, and nothing else here changes.
python -m examples.models
"""
import json
from hanzoai.cloud import ModelsApi
from examples.client import BASE_URL, public, run
def main() -> None:
with public() as api:
response = ModelsApi(api).get_models_without_preload_content()
body = response.read()
# The raw variant does NOT raise on a 4xx — that check is part of the typed
# deserialization this operation does not have.
if response.status >= 400:
raise SystemExit(f"HTTP {response.status}: {body.decode(errors='replace')}")
models = json.loads(body).get("data", [])
print(f"{BASE_URL} serves {len(models)} models, no credential required")
for model in models[:10]:
price = (model.get("pricing") or {}).get("input")
rate = f"${price}/Mtok in" if price is not None else "unpriced"
print(f" {model['id']} · {model.get('owned_by') or 'unowned'} · {rate}")
if len(models) > 10:
print(f" … and {len(models) - 10} more")
if __name__ == "__main__":
run(main)