# Hello

URL: https://docs.hanzo.ai/docs/guides/hello

> Identity — prove the key works and print who it belongs to.

**Identity — prove the key works and print who it belongs to.**

> Verified with a nonsense-sibling control: GET /v1/account/keys answers 403 {"code":"forbidden","error":"sign in to manage API keys"} with NO key and with a bogus one, while GET /v1/account/keys-zzq9 answers 404 — so the 403 is this route refusing, not a wildcard route. With a real key it returns the caller's own keys. An SDK's hello must be the call that says no.

Both halves are what makes the flow readable: an unreachable gateway and a rejected credential both end in "no", and only the open call separates them.

This replaces bot\_authMe (GET /v1/bot/auth/me), which no longer resolves: cloud relays all of /v1/bot through one `app.All("/v1/bot/*")`, so the document has `/v1/bot/{wildcard1}` and no operation named that address. The old id existed only in bot/openapi.yaml, and a hand-authored id vanishes with the hand-authored spec — which is exactly why an id here must come from the served document.

## Returns the list of available models from the routing table.

`GET /v1/models` · [reference →](https://docs.hanzo.ai/docs/openapi/ai)

Returns the list of available models from the routing table.

PUBLIC BY DESIGN, AND IT DOES NOT AUTHENTICATE — that is the whole contract, so it
is stated here rather than left to be inferred. The catalogue is the same for
everyone (listAvailableModels takes no principal), docs.hanzo.ai fetches it from
the browser, and every policy layer around it says so: the authz filter lists
"models" as public, filter\_balance does not gate it, the rate limiter excludes it,
and cloud's spend.Reachable carries /v1/models/ as "the model catalog the shell
reads for discovery".

SO THE Authorization HEADER IS NOT AN ADMISSION CHECK HERE. It is read for ONE
thing — annotating gated SKUs with the caller's own access standing — and
annotation degrades to nothing when there is no verified principal.

A credential that is presented is verified, never merely shape-checked: a caller
using /v1/models to ask "is my key working?" gets an honest answer, because a key
that does not verify annotates nothing rather than reading as accepted.

**CLI**

```bash
hanzo models list
```

**SDK**

**.ts**

```ts
import { Configuration, AiApi } from 'hanzoai';

const api = new AiApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.getModels();
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import AiApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = AiApi(client).get_models()
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.AiAPI.GetModels(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, ai_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = ai_api::get_models(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.AiApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new AiApi(client).getModels();
```

**HTTP**

```bash
curl https://api.hanzo.ai/v1/models \
  -H "Authorization: Bearer $HANZO_API_KEY"
```

**MCP**

MCP declares no tool for **ai** — `tools/list` on `https://api.hanzo.ai/v1/mcp` names the products it does reach. Use HTTP or an SDK.

## Returns the API keys the caller may see, newest first: their own, or every key the org holds when the caller administers it.

`GET /v1/account/keys` · [reference →](https://docs.hanzo.ai/docs/openapi/account)

Returns the API keys the caller may see, newest first: their own, or
every key the org holds when the caller administers it. Each is its own
credential with its own name, prefix, status, expiry and limit. Revoked keys
stay listed. No secret material comes back; a publishable key, which is public
by construction, carries its full value.

**CLI**

```bash
hanzo account keys get
```

**SDK**

**.ts**

```ts
import { Configuration, AccountApi } from 'hanzoai';

const api = new AccountApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.getAccountKeys();
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import AccountApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = AccountApi(client).get_account_keys()
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.AccountAPI.GetAccountKeys(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, account_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = account_api::get_account_keys(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.AccountApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new AccountApi(client).getAccountKeys();
```

**HTTP**

```bash
curl https://api.hanzo.ai/v1/account/keys \
  -H "Authorization: Bearer $HANZO_API_KEY"
```

**MCP**

MCP reaches **account** through the `account` tool, which names its 6 operations with its own verbs — this one among them, under a name only MCP declares. `describe` explains any of them:

```bash
curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "get_account_appearance"
         }
       }
     }'
```

---

Every command, call and tool above is generated from the same OpenAPI document that generates the SDKs themselves — the four surfaces are projections of one doc comment, so they cannot disagree.
