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

# TypeScript SDK

> Type-safe SDK for the Alana Search API (Canal 2). Zero dependencies, works in Node.js, Edge, and browser environments.

## Installation

```bash theme={null}
npm install @alana-shopping/search-sdk
```

## Quick Start

<CodeGroup>
  ```typescript Node.js theme={null}
  import { AlanaSearchClient } from "@alana-shopping/search-sdk";

  const client = new AlanaSearchClient({ apiKey: "your-api-key" });

  const results = await client.search({ query: "running shoes" });
  console.log(results.hits);
  ```

  ```javascript CommonJS theme={null}
  const { AlanaSearchClient } = require("@alana-shopping/search-sdk");

  const client = new AlanaSearchClient({ apiKey: "your-api-key" });

  const results = await client.search({ query: "running shoes" });
  console.log(results.hits);
  ```
</CodeGroup>

## Constructor

```typescript theme={null}
const client = new AlanaSearchClient({
  apiKey?: string;    // x-api-key header (API key auth)
  m2mToken?: string;  // Bearer token (Auth0 M2M — service-to-service)
  baseUrl?: string;   // Override base URL (default: https://app.alana.shopping)
});
```

If both `apiKey` and `m2mToken` are provided, `m2mToken` takes precedence.

## Methods

### `search(params)`

Full-text product search with faceting, sorting, and personalization.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const { hits, nbHits, page, nbPages, facets } = await client.search({
    query: "running shoes",   // required
    page: 0,
    hitsPerPage: 20,
    sortBy: "price_asc",
    facets: ["brand", "size"],
    facetFilters: ["brand:Nike"],
    userId: "user-123",
    personalize: true,
  });
  ```

  ```bash cURL equivalent theme={null}
  curl -X POST https://app.alana.shopping/api/v1/search \
    -H "x-api-key: your-api-key" \
    -H "Content-Type: application/json" \
    -d '{"query": "running shoes", "page": 0, "hitsPerPage": 20}'
  ```
</CodeGroup>

### `autocomplete(params)`

Query suggestions with optional product previews for search-as-you-type.

```typescript theme={null}
const { suggestions, products } = await client.autocomplete({
  query: "run",
  limit: 5,
  includeProducts: true,
});
```

### `browse(params)`

Category-based product listing — no free-text query required.

```typescript theme={null}
const { hits, nbHits } = await client.browse({
  categoryPath: "shoes/running",
  page: 0,
  hitsPerPage: 24,
  sortBy: "price_asc",
  facets: ["brand", "color"],
  facetFilters: [["color:red", "color:blue"]],
});
```

### `recommend(params)`

ML-powered product recommendations.

```typescript theme={null}
const { hits, model, fallback } = await client.recommend({
  model: "related-products",
  productId: "sku-123",
  userId: "user-456",
  limit: 10,
});
```

**Available models:** `related-products`, `frequently-bought-together`, `trending-items`, `trending-facet-values`, `personalized-trending`, `recently-viewed`, `bought-together`, `visually-similar`

### `trackEvent(params)`

Track user interactions for personalization and analytics.

<CodeGroup>
  ```typescript Search event theme={null}
  await client.trackEvent({
    events: [{ type: "search", query: "running shoes", userId: "u1" }],
  });
  ```

  ```typescript Product view theme={null}
  await client.trackEvent({
    events: [{ type: "detail-page-view", objectID: "sku-123", userId: "u1" }],
  });
  ```

  ```typescript Purchase theme={null}
  await client.trackEvent({
    events: [{
      type: "purchase-complete",
      orderID: "ord-789",
      items: [{ objectID: "sku-123", quantity: 1, price: 99.99 }],
      revenue: 99.99,
      currency: "USD",
      userId: "u1",
    }],
  });
  ```
</CodeGroup>

**Supported event types:** `home-page-view`, `search`, `category-view`, `detail-page-view`, `add-to-cart`, `shopping-cart-page-view`, `purchase-complete`

## Error Handling

```typescript theme={null}
import { AlanaSearchClient, AlanaApiError } from "@alana-shopping/search-sdk";

const client = new AlanaSearchClient({ apiKey: "your-key" });

try {
  const results = await client.search({ query: "shoes" });
} catch (err) {
  if (err instanceof AlanaApiError) {
    console.error(`API error ${err.status}:`, err.message);
    // err.body contains the full response body
  } else {
    // Network error, request timeout, etc.
    console.error("Network error:", err);
  }
}
```

## Retry Behavior

The SDK retries automatically:

| Status                     | Behavior                                                        |
| -------------------------- | --------------------------------------------------------------- |
| `429 Too Many Requests`    | Retry using `Retry-After` header value (or exponential backoff) |
| `500`, `502`, `503`, `504` | Retry with exponential backoff                                  |
| `400`, `401`, `403`, `404` | Throw immediately — no retry                                    |
| Network errors             | Retry with exponential backoff                                  |

Backoff schedule (without `Retry-After`): 100ms → 400ms → 1600ms (max 3 retries).

## TypeScript Types

All request params and response shapes are fully typed. Key types:

```typescript theme={null}
import type {
  SearchParams,
  SearchResponse,
  SearchHit,
  AutocompleteParams,
  AutocompleteResponse,
  BrowseParams,
  BrowseResponse,
  RecommendModel,
  RecommendParams,
  RecommendResponse,
  TrackEventParams,
  TrackEvent,
} from "@alana-shopping/search-sdk";
```

## Package

* **npm:** [`@alana-shopping/search-sdk`](https://www.npmjs.com/package/@alana-shopping/search-sdk)
* **Zero runtime dependencies** — uses native `fetch` (Node 18+, Edge, browser)
* **Dual ESM + CJS** — works with both `import` and `require`
