npm package: @signa-so/sdk
Description: Official TypeScript SDK for the Signa trademark intelligence API
Latest version: 0.2.2

# @signa-so/sdk

Official TypeScript SDK for the Signa trademark intelligence API.

## Installation

```bash
npm install @signa-so/sdk
```

## Quick Start

```ts
import Signa from '@signa-so/sdk';

const signa = new Signa({ api_key: 'sig_live_xxx' });

// Retrieve a trademark
const tm = await signa.trademarks.retrieve('tm_abc123');

// Search trademarks
const results = await signa.search.query({ query: 'nike', office: 'USPTO' });

// List with auto-pagination
const page = await signa.trademarks.list({ limit: 50 });
for (const tm of page.data) {
  console.log(tm.mark_text);
}
```

## Configuration

```ts
const signa = new Signa({
  api_key: 'sig_live_xxx',       // Required (or set SIGNA_API_KEY env var)
  base_url: 'https://api.signa.so',  // Default
  timeout: 30_000,                    // 30s default
  max_retries: 2,                     // Automatic retry with backoff
  debug: false,                       // Log request/response details
  fetch: customFetch,                 // Custom fetch implementation
});
```

## Resources

All resources follow the same pattern: `.retrieve(id)`, `.list(params)`, plus resource-specific methods.

### `signa.trademarks`

```ts
await signa.trademarks.retrieve('tm_xxx');
await signa.trademarks.retrieve('tm_xxx', { expand: ['owners', 'attorneys'] });
await signa.trademarks.list({ office: 'USPTO', status: 'registered', limit: 50 });
await signa.trademarks.history('tm_xxx');
```

### `signa.owners`

```ts
await signa.owners.retrieve('own_xxx');
await signa.owners.list({ query: 'Nike', country: 'US' });
await signa.owners.trademarks('own_xxx');
```

### `signa.attorneys`

```ts
await signa.attorneys.retrieve('att_xxx');
await signa.attorneys.list({ query: 'Smith' });
await signa.attorneys.trademarks('att_xxx');
```

### `signa.firms`

```ts
await signa.firms.retrieve('firm_xxx');
await signa.firms.list({ query: 'Baker McKenzie' });
await signa.firms.attorneys('firm_xxx');
await signa.firms.trademarks('firm_xxx');
```

### `signa.proceedings`

```ts
await signa.proceedings.retrieve('prc_xxx');
await signa.proceedings.list({ trademark_id: 'tm_xxx' });
```

### `signa.search`

```ts
await signa.search.query({
  query: 'nike',
  office: 'USPTO',
  status: 'registered',
  nice_class: [25, 35],
  from: 0,
  size: 20,
});

await signa.search.suggest({ query: 'nik', size: 5 });
```

### `signa.references`

```ts
await signa.references.classifications();   // Nice classes
await signa.references.offices();           // Trademark offices
await signa.references.jurisdictions();     // Jurisdictions
await signa.references.statuses();          // Status codes
await signa.references.eventTypes();        // Event types
```

## Error Handling

All API errors throw typed exceptions for `instanceof` checks:

```ts
try {
  await signa.trademarks.retrieve('tm_invalid');
} catch (err) {
  if (err instanceof Signa.NotFoundError) {
    console.log('Not found:', err.message);
  } else if (err instanceof Signa.RateLimitError) {
    console.log('Rate limited, retry after:', err.retryAfter);
  } else if (err instanceof Signa.AuthenticationError) {
    console.log('Bad API key');
  }
}
```

**Error hierarchy:**

| Class | HTTP Status | Description |
|-------|-------------|-------------|
| `SignaError` | — | Base class (network errors, timeouts) |
| `SignaAPIError` | Any | Base for all API errors |
| `BadRequestError` | 400 | Invalid parameters |
| `AuthenticationError` | 401 | Missing or invalid API key |
| `PermissionError` | 403 | Insufficient scope |
| `NotFoundError` | 404 | Resource not found |
| `RateLimitError` | 429 | Rate limit exceeded |
| `InternalServerError` | 500 | Server error |
| `ConnectionError` | — | Network connectivity failure |
| `TimeoutError` | — | Request timeout |

## Pagination

List endpoints return a `SignaList` with cursor-based pagination:

```ts
const page = await signa.trademarks.list({ limit: 100 });

console.log(page.data);        // Trademark[]
console.log(page.has_more);    // boolean
console.log(page.next_cursor); // string | null
```

## Type Generation

The SDK auto-generates types from the API's OpenAPI spec:

```bash
bun run generate:types    # Regenerate from API OpenAPI spec
bun run check:types-sync  # Verify types are up-to-date (CI check)
```

## Scripts

```bash
bun run build       # Compile TypeScript
bun run test        # Run tests (uses msw for API mocking)
bun run dev         # Watch mode
bun run typecheck   # Type check
```

## Requirements

- Node.js >= 18 (uses native `fetch`)
- MIT License