# SDKs

Source: https://developers.leonai.io/docs/sdks/

:::warning[Not published yet]
The SDKs on this page are not on npm or PyPI yet. Do not install `leonai` from PyPI — that
name belongs to an unrelated project — or any `@leonai/` package from npm. Until we publish
them, call the REST API directly: see the [API reference](https://developers.leonai.io/docs/api-reference/) and the
[OpenAPI 3.1 spec](https://api.short.leonai.io/api/v1/openapi.json). The interface below is what the SDKs will
offer.
:::

## TypeScript / JavaScript

The TypeScript SDK will call the LeonAI API from Node.js, edge runtimes, or the browser.

- **Zero runtime dependencies** — built on the global `fetch` (Node.js 18+, edge, browsers)
- **Fully typed** — request and response types mirror the API exactly
- **Automatic retries** — exponential backoff + jitter on `429`/`5xx` (idempotent methods only), honors `Retry-After`
- **Rate-limit aware** — `X-RateLimit-*` surfaced on every response and error
- **Auto-pagination** — iterate all links with `for await`
- **Webhook signature verification** — WebCrypto HMAC SHA-256

### Requirements

Node.js 18+ (or any runtime with global `fetch` and WebCrypto). Not published yet — see the
note at the top of this page.

### Initialize

```ts
import { LeonAI } from '@leonai/sdk';

const leonai = new LeonAI({ apiKey: process.env.LEONAI_API_KEY! });
```

### Client options

```ts
const leonai = new LeonAI({
  apiKey: 'lk_...', // required — sent as X-API-Key
  baseUrl: 'https://api.short.leonai.io', // API origin (default shown)
  redirectBaseUrl: 'https://short.leonai.io', // host serving /:code and /:code/qr (defaults to baseUrl)
  maxRetries: 3, // automatic retries on 429/5xx (default 3)
  fetch: customFetch, // custom fetch implementation (testing/proxies)
});
```

Every method accepts an optional final `{ signal }` argument for cancellation with
`AbortSignal`.

### Resource map

| Namespace            | Purpose                                                      | Guide                                                            |
| -------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------- |
| `leonai.links`       | Create/get/list/update/delete/bulk/export links              | [Links](https://developers.leonai.io/docs/guides/links/)                                      |
| `leonai.analytics`   | Per-link & account analytics, real-time, export, conversions | [Analytics](https://developers.leonai.io/docs/guides/analytics/)                              |
| `leonai.conversions` | Record conversions (`track`)                                 | [Analytics](https://developers.leonai.io/docs/guides/analytics/#conversion-tracking-business) |
| `leonai.qr`          | Build public QR image URLs                                   | [QR codes](https://developers.leonai.io/docs/guides/qr-codes/)                                |
| `leonai.domains`     | Custom domains + DNS verification                            | —                                                                |
| `leonai.webhooks`    | Manage webhook endpoints                                     | [Webhooks](https://developers.leonai.io/docs/guides/webhooks/)                                |
| `leonai.bioPages`    | Link-in-bio pages and items                                  | [Link-in-bio](https://developers.leonai.io/docs/guides/link-in-bio/)                          |

### Error handling

Every non-2xx response throws an `APIError`:

```ts
import { APIError } from '@leonai/sdk';

try {
  await leonai.links.get('nope');
} catch (error) {
  if (error instanceof APIError) {
    error.status; // 404
    error.code; // 'Not Found' (the API's error label)
    error.message; // 'Link not found'
    error.details; // validation issues on 400 responses
    error.rateLimit; // { limit, remaining, reset } when headers present
    error.retryAfter; // Retry-After in ms (429/503)
  }
}
```

See the [Errors reference](https://developers.leonai.io/docs/errors/) for the wire format behind these fields.

### Retries

Requests that fail with **429 or 5xx** (or a network error) are retried automatically
with exponential backoff and jitter (500 ms base, doubling up to 8 s, max 3 attempts
by default). A `Retry-After` header, when present, is honored exactly.

Only **idempotent** methods (GET/PUT/DELETE) are retried — POST/PATCH are never
replayed, so a create is never accidentally duplicated. Configure with
`new LeonAI({ maxRetries: 5 })` or disable with `maxRetries: 0`.

## Python

The Python SDK will mirror the TypeScript client — zero runtime dependencies
(standard-library `urllib` only), typed helpers, automatic retries, and rate-limit
parsing. Python 3.9+.

### Install

Not published yet. The PyPI name `leonai` belongs to an unrelated project — do not install it.

### Initialize

```python
import leonai

client = leonai.Client(api_key="lk_live_your_key_here")
# Options: base_url (default https://api.short.leonai.io), redirect_base_url,
# max_retries=3, timeout=30.0
```

Responses are raw JSON envelopes (`{"success": True, "data": ...}`).

### Create a link

```python
created = client.links.create({
    "longUrl": "https://example.com/spring-sale",
    "shortCode": "spring-sale",
    "tags": ["marketing", "q2"],
})
print(created["data"]["shortUrl"])  # https://short.leonai.io/spring-sale
```

### List & paginate

```python
page = client.links.list({"search": "sale", "tags": ["marketing"], "limit": 50})
print(page["pagination"]["hasMore"])

for link in client.links.list_all({"tags": ["marketing"]}, page_size=100):
    print(link["shortUrl"], link["clicks"])
```

### Analytics

```python
data = client.analytics.link("<link-id>", days=30)
summary = client.analytics.summary()
```

### Resources & errors

`client.links`, `client.analytics`, `client.conversions`, `client.qr`,
`client.domains`, `client.webhooks`, `client.bio_pages`. Verify webhooks with
`leonai.verify_webhook_signature(raw_body, signature, secret)`. Every non-2xx raises
`leonai.APIError` (`.status`, `.code`, `.message`, `.details`, `.rate_limit`,
`.retry_after`); network errors surface as status `0`.

## Other languages

| Language                | Status               |
| ----------------------- | -------------------- |
| TypeScript / JavaScript | 🚧 Not published yet |
| Python                  | 🚧 Not published yet |
| Go                      | 🚧 Roadmap           |

Until the SDKs are published, and for every other language, call the API directly: the
[OpenAPI spec](https://developers.leonai.io/docs/api-reference/) can generate a client for most languages.
