npm package: @starshipper/api
Description: Official TypeScript/JavaScript SDK for the StarShipper Shipping & Trade API
Author: StarShipper
Latest version: 1.0.0

# @starshipper/api

Official TypeScript/JavaScript SDK for the **StarShipper Shipping & Trade API** - The comprehensive API for African shipping, trade tariffs, and customs documentation.

[![npm version](https://img.shields.io/npm/v/@starshipper/api.svg)](https://www.npmjs.com/package/@starshipper/api)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Features

✨ **Easy to Use** - Simple, intuitive API with full TypeScript support
🔐 **Built-in Authentication** - Automatic API key handling
🔄 **Automatic Retries** - Resilient error handling with exponential backoff
📊 **Rate Limit Tracking** - Monitor your API usage in real-time
🌍 **Comprehensive Coverage** - Access tariffs, HS codes, documents, and regional trade data
⚡ **Lightweight** - Zero dependencies, works in Node.js and browsers

## Installation

```bash
npm install @starshipper/api
```

Or with yarn:

```bash
yarn add @starshipper/api
```

Or with pnpm:

```bash
pnpm add @starshipper/api
```

## Quick Start

```typescript
import { StarShipperClient } from '@starshipper/api';

// Initialize the client
const client = new StarShipperClient({
  apiKey: 'sk_live_your_api_key_here'
});

// Get all live countries
const countries = await client.getCountries({ status: 'live' });
console.log(countries.data);

// Get tariff rates for South Africa
const tariffs = await client.getTariffRate('ZA', '0901.21');
console.log(tariffs.data);

// Classify a product description
const classification = await client.classify('roasted coffee beans');
console.log(classification.data);
```

## Getting an API Key

1. Visit [StarShipper Dashboard](https://starshipper.com/dashboard)
2. Sign up or log in to your account
3. Navigate to API Keys section
4. Generate a new API key (test or live)
5. Copy your key (format: `sk_live_xxxxx` or `sk_test_xxxxx`)

**Important:** Keep your API keys secure! Never commit them to version control.

## Usage

### Initialize the Client

```typescript
import { StarShipperClient } from '@starshipper/api';

const client = new StarShipperClient({
  apiKey: 'sk_live_your_api_key_here',
  baseUrl: 'https://starshipper.vercel.app/api', // optional, default shown
  timeout: 30000, // optional, 30 seconds default
  retries: 3, // optional, 3 retries default
});
```

### Countries API

```typescript
// Get all countries
const allCountries = await client.getCountries();

// Get only live countries
const liveCountries = await client.getCountries({ status: 'live' });

// Get countries by region
const ecowasCountries = await client.getCountries({ region: 'ECOWAS' });

// Get specific country
const southAfrica = await client.getCountry('ZA');
```

### Tariffs API

```typescript
// Get tariff rates for a country and HS code
const tariff = await client.getTariffRate('ZA', '0901.21');

// Query tariffs with filters
const tariffs = await client.getTariffs({
  country: 'KE',
  description: 'coffee',
  min_rate: 5,
  max_rate: 20,
  limit: 10,
  offset: 0
});

// Access tariff data
if (tariffs.success) {
  tariffs.data.tariffs.forEach(tariff => {
    console.log(`${tariff.hs_code}: ${tariff.rate}% - ${tariff.description}`);
  });
}
```

### HS Code Classification

```typescript
// Classify a product description
const result = await client.classify('roasted coffee beans');

// Classify with country context
const result = await client.classify('roasted coffee beans', 'ZA');

// Advanced classification
const result = await client.classifyProduct({
  description: 'roasted coffee beans',
  country: 'ZA',
  confidence_threshold: 0.8
});

// Access classification results
if (result.success) {
  result.data.results.forEach(item => {
    console.log(`${item.hs_code} (${item.confidence}%): ${item.description}`);
  });
}
```

### Trade Documents API

```typescript
// Get all required documents for a country
const docs = await client.getCountryDocuments('ZA');

// Get specific document types
const customsDocs = await client.getDocuments({
  country: 'KE',
  document_type: 'customs',
  required: true
});

// Access document information
if (docs.success) {
  docs.data.documents.forEach(doc => {
    console.log(`${doc.name} - Required: ${doc.required}`);
  });
}
```

### Regional Trade Blocs API

```typescript
// Get all regional blocs
const blocs = await client.getRegionalBlocs();

// Get blocs for a specific country
const countryBlocs = await client.getRegionalBlocs({ country: 'ZA' });

// Get specific bloc
const ecowas = await client.getRegionalBloc('ECOWAS');

// Access bloc information
if (ecowas.success) {
  console.log(`${ecowas.data.name}: ${ecowas.data.member_countries.join(', ')}`);
}
```

### Data Freshness API

```typescript
// Check data freshness status
const freshness = await client.getDataFreshness();

if (freshness.success) {
  console.log(`Overall status: ${freshness.data.overall_status}`);
  freshness.data.freshness.forEach(item => {
    console.log(`${item.entity}: ${item.status} (${item.record_count} records)`);
  });
}
```

## Error Handling

All methods return an `ApiResponse<T>` with a consistent structure:

```typescript
interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: {
    code: string;
    message: string;
    details?: any;
  };
  meta?: {
    timestamp: string;
    rateLimit?: {
      limit: number;
      remaining: number;
      reset: number;
    };
  };
}
```

Example error handling:

```typescript
const result = await client.getTariffRate('ZA', '0901.21');

if (result.success) {
  console.log('Tariff rate:', result.data);
} else {
  console.error('Error:', result.error.message);
  console.error('Error code:', result.error.code);
}

// Check rate limits
if (result.meta?.rateLimit) {
  console.log(`Rate limit: ${result.meta.rateLimit.remaining}/${result.meta.rateLimit.limit}`);
}
```

## Rate Limiting

The SDK automatically tracks rate limits and includes them in response metadata:

```typescript
const result = await client.getCountries();

if (result.meta?.rateLimit) {
  const { limit, remaining, reset } = result.meta.rateLimit;
  console.log(`Requests: ${remaining}/${limit}`);
  console.log(`Resets at: ${new Date(reset * 1000)}`);
}
```

**Rate Limits by Tier:**
- **Free:** 60/min, 1,000/hour, 10,000/day
- **Pro:** 600/min, 10,000/hour, 100,000/day
- **Enterprise:** Custom limits

## Advanced Configuration

### Custom Headers

```typescript
const client = new StarShipperClient({
  apiKey: 'sk_live_xxxxx',
  headers: {
    'X-Custom-Header': 'value'
  }
});
```

### Request-Level Options

```typescript
// Override timeout for specific request
const result = await client.getCountries({}, {
  timeout: 60000, // 60 seconds
  retries: 5,
  headers: { 'X-Request-ID': 'custom-id' }
});
```

### Update API Key at Runtime

```typescript
const client = new StarShipperClient();

// Set API key later
client.setApiKey('sk_live_xxxxx');

// Clear API key
client.clearApiKey();

// Get current config
const config = client.getConfig();
```

## TypeScript Support

Full TypeScript definitions are included:

```typescript
import type {
  Country,
  TariffRate,
  ClassificationResult,
  TradeDocument,
  RegionalBloc,
  ApiResponse
} from '@starshipper/api';

// All types are fully typed
const countries: ApiResponse<Country[]> = await client.getCountries();
```

## Browser Usage

The SDK works in browsers with modern fetch API support:

```html
<script type="module">
  import { StarShipperClient } from 'https://cdn.skypack.dev/@starshipper/api';

  const client = new StarShipperClient({
    apiKey: 'sk_live_xxxxx'
  });

  const countries = await client.getCountries();
  console.log(countries);
</script>
```

## Examples

### Calculate Total Import Cost

```typescript
async function calculateImportCost(
  countryCode: string,
  hsCode: string,
  goodsValue: number
) {
  const tariff = await client.getTariffRate(countryCode, hsCode);

  if (!tariff.success) {
    throw new Error(tariff.error.message);
  }

  const tariffAmount = (goodsValue * tariff.data.tariffs[0].rate) / 100;

  // Add additional taxes
  let additionalTaxes = 0;
  if (tariff.data.tariffs[0].additional_taxes) {
    for (const tax of tariff.data.tariffs[0].additional_taxes) {
      if (tax.type === 'percentage') {
        additionalTaxes += (goodsValue * tax.rate) / 100;
      } else {
        additionalTaxes += tax.rate;
      }
    }
  }

  return {
    goodsValue,
    tariffAmount,
    additionalTaxes,
    totalCost: goodsValue + tariffAmount + additionalTaxes
  };
}

// Usage
const cost = await calculateImportCost('ZA', '0901.21', 10000);
console.log(`Total import cost: $${cost.totalCost}`);
```

### Batch Processing

```typescript
async function processBatch(items: Array<{ country: string; hsCode: string }>) {
  const results = await Promise.all(
    items.map(item => client.getTariffRate(item.country, item.hsCode))
  );

  return results.map((result, index) => ({
    ...items[index],
    success: result.success,
    tariff: result.data?.tariffs[0],
    error: result.error
  }));
}

// Usage
const batch = await processBatch([
  { country: 'ZA', hsCode: '0901.21' },
  { country: 'KE', hsCode: '0901.21' },
  { country: 'NG', hsCode: '0901.21' }
]);
```

## Support

- **Documentation:** [https://starshipper.com/docs](https://starshipper.com/docs)
- **API Reference:** [https://starshipper.com/docs/api](https://starshipper.com/docs/api)
- **Issues:** [GitHub Issues](https://github.com/pengasuzie/starshipper/issues)
- **Email:** support@starshipper.com

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.

## License

MIT © StarShipper

---

Made with ❤️ for African trade and logistics