npm package: @signthem/sdk
Description: Official TypeScript SDK for the SignThem e-signature API
Author: SignThem
Latest version: 0.1.0-beta.1

# @signthem/sdk

Official TypeScript SDK for the SignThem e-signature API.

## Requirements

- **Node.js 18+** (uses native `fetch`)
- A SignThem API key (generate one in Settings > API Keys)

## Installation

```bash
npm install @signthem/sdk
```

## Quick Start

```typescript
import { SignThemClient } from '@signthem/sdk';

const client = new SignThemClient({
  baseUrl: 'https://api.example.com',
  apiKey: 'sk_live_your_key_here',
});
```

## Examples

### 1. Create and send an envelope

```typescript
import { readFileSync } from 'node:fs';
import { SignThemClient } from '@signthem/sdk';

const client = new SignThemClient({
  baseUrl: 'https://api.example.com',
  apiKey: process.env.SENDSIGN_API_KEY!,
});

// Upload a PDF and create an envelope
const pdf = readFileSync('./contract.pdf');
const envelope = await client.envelopes.create(Buffer.from(pdf), {
  name: 'Service Agreement',
});

// Add a recipient
const recipient = await client.envelopes.addRecipient(envelope.id, {
  name: 'Jane Doe',
  email: 'jane@example.com',
});

// Add a signature field
await client.envelopes.configureFields(envelope.id, [{
  documentId: envelope.documents[0].id,
  type: 'Signature',
  pageNumber: 1,
  x: 100, y: 600, width: 200, height: 50,
  isRequired: true,
  recipientId: recipient.id,
  assigneeType: 'Recipient',
}]);

// Send for signing
const result = await client.envelopes.send(envelope.id);
console.log('Signing links:', result.signingLinks);
```

### 2. List envelopes with auto-pagination

```typescript
// Single page
const page = await client.envelopes.list({ pageSize: 20, status: 'Sent' });

// Iterate through ALL envelopes automatically
for await (const envelope of client.envelopes.listAll({ pageSize: 50 })) {
  console.log(`[${envelope.status}] ${envelope.name}`);
}
```

### 3. Create from template

```typescript
const templates = await client.templates.list();
const envelope = await client.templates.createEnvelope(templates[0].id, {
  name: 'Generated Contract',
  recipients: [{ name: 'Bob', email: 'bob@co.com' }],
});
```

## Authentication

### API Key (recommended for server-to-server)

```typescript
const client = new SignThemClient({
  baseUrl: 'https://api.example.com',
  apiKey: 'sk_live_abc123',
});
```

### JWT Token (for user-context operations)

```typescript
const client = new SignThemClient({
  baseUrl: 'https://api.example.com',
  token: 'eyJhbGciOiJIUzI1NiIs...',
});
```

## Error Handling

The SDK throws typed errors for each HTTP status category:

```typescript
import {
  SignThemClient,
  NotFoundError,
  RateLimitError,
  AuthenticationError,
  ApiError,
} from '@signthem/sdk';

try {
  await client.envelopes.get('nonexistent-id');
} catch (err) {
  if (err instanceof NotFoundError) {
    console.log('Envelope not found');
  } else if (err instanceof RateLimitError) {
    console.log(`Rate limited. Retry after ${err.retryAfter}s`);
  } else if (err instanceof AuthenticationError) {
    console.log('Invalid API key');
  } else if (err instanceof ApiError) {
    console.log(`API error ${err.status}: ${err.code} — ${err.message}`);
  }
}
```

**Error hierarchy:**

| Error Class | HTTP Status | When |
|-------------|-------------|------|
| `BadRequestError` | 400 | Invalid request parameters |
| `AuthenticationError` | 401 | Invalid/missing API key or token |
| `ForbiddenError` | 403 | Insufficient permissions |
| `NotFoundError` | 404 | Resource not found |
| `ConflictError` | 409 | Conflict (e.g., PDF not ready) |
| `GoneError` | 410 | Expired or voided resource |
| `RateLimitError` | 429 | Too many requests |
| `ServerError` | 5xx | Server error |
| `ValidationError` | — | Client-side validation (before HTTP) |
| `TimeoutError` | — | Request timed out |
| `NetworkError` | — | Connection failure |

## Configuration Options

```typescript
const client = new SignThemClient({
  baseUrl: 'https://api.example.com', // Required
  apiKey: 'sk_live_abc123',            // Required (or token)
  timeout: 30_000,                     // Default: 30s
  maxRetries: 3,                       // Default: 3
  retryDelay: 1_000,                   // Default: 1s base delay
});
```

**Retry behavior:**
- Retries on: 408, 429, 500, 502, 503, 504
- Only idempotent methods (GET, PUT, DELETE) are retried by default
- Exponential backoff with jitter
- Respects `Retry-After` header on 429 responses

## API Reference

### `client.envelopes`

| Method | Description |
|--------|-------------|
| `list(params?)` | List envelopes (paginated) |
| `listAll(params?)` | Async iterator over all envelopes |
| `get(id)` | Get envelope details |
| `getAudit(id)` | Get audit trail |
| `create(file, params)` | Create envelope from PDF |
| `delete(id)` | Soft-delete envelope |
| `void(id)` | Void envelope |
| `addRecipient(envId, params)` | Add recipient |
| `updateRecipient(envId, recId, params)` | Update recipient |
| `removeRecipient(envId, recId)` | Remove recipient |
| `configureFields(envId, fields)` | Set signature fields |
| `send(id)` | Send for signing |
| `getSigningLink(envId, recId)` | Get signing URL |
| `resendInvite(envId, recId)` | Resend invitation email |
| `downloadOriginal(envId, docId)` | Download original PDF |
| `downloadSigned(envId)` | Download signed PDF |

### `client.templates`

| Method | Description |
|--------|-------------|
| `list()` | List all templates |
| `get(templateId)` | Get template details |
| `downloadPdf(templateId)` | Download template preview |
| `createEnvelope(templateId, params?)` | Create envelope from template |

### `client.billing`

| Method | Description |
|--------|-------------|
| `getQuota()` | Get quota/usage |
| `getSubscription()` | Get subscription status |
| `getPlans()` | Get available plans |

## Running Examples

```bash
cd sdk/typescript

# Install dependencies
npm install

# Set environment variables
export SENDSIGN_BASE_URL=http://localhost:5000
export SENDSIGN_API_KEY=your-key-here

# Run examples
npx tsx examples/list-envelopes.ts
npx tsx examples/create-and-send.ts
npx tsx examples/create-from-template.ts
```

## Development

```bash
# Build
npm run build

# Type check
npm run typecheck

# Run tests
npm test

# Watch mode
npm run dev
```

## License

MIT