@sputnikx/eu-trade-sdk
v1.0.0
Published
Lightweight JavaScript SDK for SputnikX EU Trade Analytics API — 28M+ Eurostat COMEXT records, product catalog, orders, and fuel calculator
Maintainers
Readme
@sputnikx/eu-trade-sdk
Lightweight JavaScript SDK for the SputnikX EU Trade Analytics API — 28M+ Eurostat COMEXT records across 27 EU countries, plus commerce endpoints for product catalog, pricing, quotes, and orders.
Zero dependencies. Uses native fetch (Node 18+). Full TypeScript support via JSDoc + .d.ts.
Quick Start
npm install @sputnikx/eu-trade-sdkimport { TradeClient } from '@sputnikx/eu-trade-sdk';
const trade = new TradeClient({ apiKey: process.env.SPUTNIKX_API_KEY });
const { data } = await trade.overview();
console.log(`${data.total_records.toLocaleString()} trade records`);Authentication
Public endpoints (products, prices, calculator) require no API key.
Agent endpoints (trade data, availability, quotes, orders) require a Bearer token:
export SPUTNIKX_API_KEY=sk_live_your_key_hereGet your API key at sputnikx.xyz admin panel or via the x402 USDC payment protocol.
Configuration
| Option | Env Variable | Default |
|--------|-------------|---------|
| apiKey | SPUTNIKX_API_KEY | (none) |
| baseUrl | SPUTNIKX_API_URL | https://sputnikx.xyz |
| tenant | SPUTNIKX_TENANT | siltums |
| timeout | SPUTNIKX_TIMEOUT | 30000 |
Legacy env vars (SILTUMS_API_KEY, etc.) are supported as fallbacks.
API Reference
TradeClient
EU trade data endpoints. All require authentication with read scope.
import { TradeClient } from '@sputnikx/eu-trade-sdk';
const trade = new TradeClient({ apiKey: '...' });trade.overview()
High-level statistics: total records, countries, date range, yearly breakdown.
const { data } = await trade.overview();
// { total_records: 28000000+, countries_with_data: 27, date_range: { from, to }, years: [...] }trade.countries()
EU27 countries with data availability status.
const { data } = await trade.countries();
// [{ code: 'LV', name_en: 'Latvia', has_data: true, total_records: 1200000, years_available: [2021,2022,...] }]trade.timeline(opts?)
Monthly trade volume time series.
| Parameter | Type | Description |
|-----------|------|-------------|
| reporters | string[] | EU27 codes, e.g. ['LV', 'DE'] |
| flow | string | 'IMPORT' or 'EXPORT' |
| years | string | Range '2021-2025' or single '2024' |
| limit | number | Max rows (default: 1000, max: 10000) |
const { data } = await trade.timeline({
reporters: ['LV', 'EE', 'LT'],
flow: 'EXPORT',
years: '2023-2025',
});trade.topPartners(opts)
Top trading partners by value for a reporter country.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| reporter | string | Yes | EU27 country code |
| year | number | No | Filter by year |
| flow | string | No | 'IMPORT' or 'EXPORT' |
| limit | number | No | Max results (default: 20) |
const { data } = await trade.topPartners({ reporter: 'LV', flow: 'EXPORT', year: 2025 });trade.topProducts(opts)
Top HS2 product categories by value.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| reporter | string | Yes | EU27 country code |
| year | number | No | Filter by year |
| flow | string | No | 'IMPORT' or 'EXPORT' |
| limit | number | No | Max results (default: 20) |
const { data } = await trade.topProducts({ reporter: 'DE', year: 2025, limit: 10 });trade.balance(opts)
Trade balance (export - import) over time.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| reporter | string | Yes | EU27 country code |
| years | string | No | Range (default: last 5 years) |
const { data } = await trade.balance({ reporter: 'LV', years: '2020-2025' });
// [{ year: 2020, import_eur, export_eur, balance_eur, ... }]trade.woodProducts(opts)
Wood products HS4-level breakdown (Chapter 44) with top 3 partners per product.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| reporter | string | Yes | EU27 country code |
| year | number | No | Filter by year |
| flow | string | No | 'IMPORT' or 'EXPORT' |
const { data } = await trade.woodProducts({ reporter: 'LV', year: 2025, flow: 'EXPORT' });
// [{ hs4_code: '4407', hs4_name: 'Wood sawn lengthwise', value_eur, top_partners: [...] }]trade.heatmap(opts)
Cross-country comparison for a product/year combination.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| year | number | Yes | Year |
| flow | string | No | 'IMPORT' or 'EXPORT' |
| hs2 | string | No | HS2 code (e.g. '44' for wood) |
const { data } = await trade.heatmap({ year: 2025, hs2: '44', flow: 'IMPORT' });
// [{ code: 'DE', name: 'Germany', value_eur: 5200000000, weight_kg: ... }]trade.productDetail(opts)
Deep dive into an HS2 chapter: monthly series + top 20 partners.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| reporter | string | Yes | EU27 country code |
| hs2 | string | Yes | HS2 code (e.g. '44') |
| years | string | No | Range (default: last 3 years) |
const { monthly, top_partners } = await trade.productDetail({
reporter: 'LV', hs2: '44', years: '2023-2025',
});trade.usage()
Check API rate limits and usage for the current key.
const usage = await trade.usage();CommerceClient
Product catalog, pricing, calculator, quotes, and orders.
import { CommerceClient } from '@sputnikx/eu-trade-sdk';
const commerce = new CommerceClient({ apiKey: '...' }); // apiKey optional for public endpointscommerce.products() (public)
Full product catalog of in-stock items.
const products = await commerce.products();commerce.prices() (public)
Real-time price feed with per-kg and per-ton rates.
const { prices, currency, updated_at } = await commerce.prices();commerce.calculator(opts?) (public)
Fuel consumption calculator for heating season planning.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| boiler_kw | number | 15 | Boiler power (1-500 kW) |
| desired_temp | number | 20 | Indoor temperature (C) |
| heating_months | number | 6 | Season length (1-12) |
| insulation | string | 'average' | poor/average/good/excellent |
const { data } = await commerce.calculator({ boiler_kw: 25, insulation: 'good' });
console.log(`Need ${data.granulas.kg}kg pellets (${data.granulas.bags} bags)`);commerce.availability(opts?) (auth)
Check real-time stock levels per warehouse location.
const { data } = await commerce.availability({ slug: 'premium-granulas-a1' });commerce.createQuote(opts) (auth, quote scope)
Create a price quote with automatic VAT calculation (21%).
const quote = await commerce.createQuote({
client_name: 'Acme SIA',
client_email: '[email protected]',
items: [
{ slug: 'premium-granulas-a1', quantity: 10, unit: 'pallet' },
{ slug: 'ozola-briketes', quantity: 50, unit: 'bag' },
],
});
console.log(`Quote ${quote.data.quote_number}: EUR ${quote.data.total_with_vat}`);commerce.placeOrder(opts) (auth, order scope)
Place an order. Maximum EUR 50,000 per order.
const order = await commerce.placeOrder({
slug: 'premium-granulas-a1',
quantity: 5,
unit: 'pallet',
customer_name: 'Janis Berzins',
customer_email: '[email protected]',
delivery_address: 'Brivibas iela 100, Riga, LV-1001',
idempotency_key: 'order-abc-123',
});commerce.orderStatus(orderId) (auth, order scope)
Check order status.
const { data } = await commerce.orderStatus(42);
console.log(`Order #${data.id}: ${data.status}`);Constants
import { EU27_COUNTRIES, EU27_CODES, TRADE_FLOWS, HS2_CHAPTERS, WOOD_HS4 } from '@sputnikx/eu-trade-sdk';
EU27_COUNTRIES.LV // 'Latvia'
EU27_CODES.has('DE') // true
TRADE_FLOWS.EXPORT // 'EXPORT'
HS2_CHAPTERS['44'] // 'Wood and articles of wood; wood charcoal'
WOOD_HS4['4412'] // 'Plywood'Error Handling
All API errors throw SputnikXError with HTTP status and response data:
import { TradeClient, SputnikXError } from '@sputnikx/eu-trade-sdk';
try {
await trade.topPartners({ reporter: 'XX' }); // invalid country
} catch (err) {
if (err instanceof SputnikXError) {
console.error(`API error (${err.status}): ${err.message}`);
console.error('Response:', err.data);
}
}| Status | Meaning |
|--------|---------|
| 400 | Bad request (invalid parameters) |
| 401 | Missing or invalid API key |
| 403 | Insufficient scope |
| 404 | Resource not found |
| 408 | Request timeout |
| 429 | Rate limit exceeded |
| 500 | Server error |
Shared Client
Both TradeClient and CommerceClient can share a single SputnikXClient:
import { SputnikXClient, TradeClient, CommerceClient } from '@sputnikx/eu-trade-sdk';
const client = new SputnikXClient({ apiKey: '...' });
const trade = new TradeClient(client);
const commerce = new CommerceClient(client);x402 USDC Payments
The SputnikX API supports the x402 payment protocol for pay-per-request access using USDC on Base. No API key needed — pay with crypto per request.
Related
- MCP Server:
mcp-sputnikx-market— Model Context Protocol server for Claude, ChatGPT, and other AI assistants - OpenAPI:
https://sputnikx.xyz/api/openapi.json - Agent Card:
https://sputnikx.xyz/.well-known/agent-card.json - Website: sputnikx.xyz
License
MIT --- SputnikX
