> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hiloop.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Use the SDKs

> Call the hiloop API from TypeScript or Python with typed clients.

hiloop ships a **TypeScript** and a **Python** SDK. Their typed operations and models are generated
from the same API contract as the [CLI](/reference/cli/hiloop) and the
[API reference](/api-reference). The clients and generated models ship together and stay versioned
in lockstep.

<Note>
  The SDKs are published at `0.x` during the public preview: typed, versioned, and functional. Pin a
  version and expect the surface to evolve until GA.
</Note>

## Install

<CodeGroup>
  ```sh npm theme={null}
  npm install @hiloopai/sdk
  ```

  ```sh pnpm theme={null}
  pnpm add @hiloopai/sdk
  ```

  ```sh pip theme={null}
  pip install hiloop
  ```
</CodeGroup>

## Configure a client

Point the client at the hiloop edge and authenticate with your
[API key](/guides/managing-api-keys). In TypeScript, pass it as the client's `auth` option; in
Python, as the `AuthenticatedClient` token. Either way the SDK sends it as an `Authorization: Bearer`
header on every request.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { createClient } from "@hiloopai/sdk";

  const client = createClient({
    baseUrl: "https://api.hiloop.ai",
    auth: process.env.HILOOP_API_KEY,
  });
  ```

  ```python Python theme={null}
  import os
  from hiloop import AuthenticatedClient

  client = AuthenticatedClient(
      base_url="https://api.hiloop.ai",
      token=os.environ["HILOOP_API_KEY"],
  )
  ```
</CodeGroup>

In TypeScript, `createClient` builds an isolated instance you pass to each call as `{ client }`.
If you'd rather configure once and skip threading it through, set the package-level default `client`
instead — then every operation uses it automatically:

```typescript TypeScript theme={null}
import { client } from "@hiloopai/sdk";

client.setConfig({
  baseUrl: "https://api.hiloop.ai",
  auth: process.env.HILOOP_API_KEY,
});
```

The package also exports `createConfig` for building a config object you reuse across instances.

## A first call

Echo your identity — the same check `hiloop whoami` runs:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { identityServiceWhoAmI } from "@hiloopai/sdk";

  const { data } = await identityServiceWhoAmI({ client });
  console.log(data?.principal);
  ```

  ```python Python theme={null}
  from hiloop.api.identity_service import identity_service_who_am_i

  resp = identity_service_who_am_i.sync(client=client)
  print(resp.principal)
  ```
</CodeGroup>

## Handle errors

Every API error uses the same typed envelope, and both SDKs surface it as `ErrorBody`. Branch on
its stable snake\_case `code` (for example `not_found`, `quota_exceeded`, `rate_limited`,
`internal`) — never on the message text, whose wording can change. In TypeScript the envelope is
the `error` half of each call's result; in Python an error response is returned as an `ErrorBody`
value you narrow with `isinstance`.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { identityServiceWhoAmI } from "@hiloopai/sdk";

  const { data, error } = await identityServiceWhoAmI({ client });
  if (error) {
    throw new Error(`whoami failed (${error.code}): ${error.message}`);
  }
  console.log(data?.principal);
  ```

  ```python Python theme={null}
  from hiloop.api.identity_service import identity_service_who_am_i
  from hiloop.models import ErrorBody

  resp = identity_service_who_am_i.sync(client=client)
  if isinstance(resp, ErrorBody):
      raise RuntimeError(f"whoami failed ({resp.code}): {resp.message}")
  print(resp.principal)
  ```
</CodeGroup>

Two fields carry extra signal when present:

* **`details.quota`** on `quota_exceeded` / `rate_limited` rejections names the limit that rejected
  the request (`metric`, `limit`, `current`, `retry_after_seconds`); rate limits also send a
  `Retry-After` header.
* **`request_id`** on server faults (5xx) — quote it when contacting support to locate the failing
  request.

## Patterns to know

* **Endpoint functions.** Every operation is an importable function (for example,
  `projectServiceListProjects`) called with `{ client, body }` in TypeScript, or a service module
  with `sync` / `asyncio` variants in Python.
* **Idempotency keys on create-style mutations.** Supply a key explicitly when a retry must remain
  safe across processes.
* **Typed request and response models.** Bodies and rows are typed (e.g. `DataView`,
  `QueryRequest`, `QueryResponse`), so your editor guides the call. Full type listings are in the
  [TypeScript](/reference/sdk/typescript/index) and [Python](/reference/sdk/python/index) SDK
  reference.

## Where to go next

* [Query telemetry](/guides/querying-telemetry) includes TypeScript and Python examples.
* The generated [TypeScript](/reference/sdk/typescript/index) and
  [Python](/reference/sdk/python/index) reference lists every function and type.
