{"_id":"@alphabite/econt-monorepo","_rev":"2-34a9176a0ce8c1dfca0467f017b10bdb","name":"@alphabite/econt-monorepo","dist-tags":{"latest":"1.1.2"},"versions":{"1.1.1":{"name":"@alphabite/econt-monorepo","version":"1.1.1","keywords":["econt","shipping","bulgaria","logistics","courier","delivery","sdk","api","typescript","cache","nomenclatures"],"author":{"name":"Alphabite"},"license":"MIT","_id":"@alphabite/econt-monorepo@1.1.1","maintainers":[{"name":"darkbound","email":"todor@alphabite.io"},{"name":"nikola-alphabite","email":"nikola@alphabite.io"},{"name":"ivan_alphabite","email":"ivan@alphabite.io"}],"homepage":"https://github.com/alphabite-dev/econt-sdk#readme","bugs":{"url":"https://github.com/alphabite-dev/econt-sdk/issues"},"dist":{"shasum":"992d4d0b653111f8a1ee426756b680d722317392","tarball":"https://registry.npmjs.org/@alphabite/econt-monorepo/-/econt-monorepo-1.1.1.tgz","fileCount":26,"integrity":"sha512-ySVXahFqnEX3Z3Ze0yC8iWk6hY9kVM9U6zTpeoVwz7fhl1Hv5I0Fhcf9SNsJ1147sev2Rhh0SiqcepQOHCQjcQ==","signatures":[{"sig":"MEUCIQCAkjql00Y4mot357cpP4Hi1RZ8VvgmlP/1d30trooXcwIgOaFxGrc7NXVPCKv6+rnkJ3qazmfC7RUQZQ70Vq8JSzw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":263546},"engines":{"node":">=14.0.0"},"gitHead":"4c3adfee525feae76a03d11db3cc1b15d8fd1465","scripts":{"dev":"npm run dev -w @alphabite/econt-sdk","test":"npm run test -w @alphabite/econt-sdk","build":"npm run build --workspaces","clean":"npm run clean --workspaces --if-present","test:ui":"npm run test:ui -w @alphabite/econt-sdk","build:sdk":"npm run build -w @alphabite/econt-sdk","typecheck":"npm run typecheck --workspaces","test:watch":"npm run test:watch -w @alphabite/econt-sdk","build:types":"npm run build -w @alphabite/econt-types"},"_npmUser":{"name":"darkbound","email":"todor@alphabite.io"},"repository":{"url":"git+https://github.com/alphabite-dev/econt-sdk.git","type":"git"},"workspaces":["packages/*"],"_npmVersion":"10.8.2","description":"Monorepo for Econt SDK and Types","directories":{},"_nodeVersion":"20.19.0","dependencies":{"axios":"^1.6.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.1","dotenv":"^17.2.3","vitest":"^4.0.3","@vitest/ui":"^4.0.3","typescript":"^5.3.3","@types/node":"^20.10.5"},"_npmOperationalInternal":{"tmp":"tmp/econt-monorepo_1.1.1_1763043626369_0.10897137354095321","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"@alphabite/econt-monorepo","version":"1.1.2","description":"Monorepo for Econt SDK and Types","workspaces":["packages/*"],"scripts":{"build":"npm run build --workspaces","build:types":"npm run build -w @alphabite/econt-types","build:sdk":"npm run build -w @alphabite/econt-sdk","dev":"npm run dev -w @alphabite/econt-sdk","test":"npm run test -w @alphabite/econt-sdk","test:watch":"npm run test:watch -w @alphabite/econt-sdk","test:ui":"npm run test:ui -w @alphabite/econt-sdk","typecheck":"npm run typecheck --workspaces","clean":"npm run clean --workspaces --if-present"},"keywords":["econt","shipping","bulgaria","logistics","courier","delivery","sdk","api","typescript","cache","nomenclatures"],"author":{"name":"Alphabite"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/alphabite-dev/econt-sdk.git"},"bugs":{"url":"https://github.com/alphabite-dev/econt-sdk/issues"},"homepage":"https://github.com/alphabite-dev/econt-sdk#readme","engines":{"node":">=14.0.0"},"dependencies":{"axios":"^1.6.2"},"devDependencies":{"@types/node":"^20.10.5","@vitest/ui":"^4.0.3","dotenv":"^17.2.3","tsup":"^8.0.1","typescript":"^5.3.3","vitest":"^4.0.3"},"_id":"@alphabite/econt-monorepo@1.1.2","gitHead":"4c3adfee525feae76a03d11db3cc1b15d8fd1465","_nodeVersion":"20.19.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-Ix52tB94H8wDJmBU+j84g5somwhw1rsv/QZ65h4faIyyWxD2yVuvC194NeQqST0xRtHg0wTGpjyyQb4ybKII0Q==","shasum":"b3a5f20e9f90dd3f937e781b39ff5a2675afa6da","tarball":"https://registry.npmjs.org/@alphabite/econt-monorepo/-/econt-monorepo-1.1.2.tgz","fileCount":26,"unpackedSize":263546,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBG8UoTNXEViOEhp5n5WnmLbd3+4E8luSFRBgoOsgvHHAiAfdkWXDv8eajzrmoU6co1m4sFPNqFfIz2vXxz6Y7yl6Q=="}]},"_npmUser":{"name":"darkbound","email":"todor@alphabite.io"},"directories":{},"maintainers":[{"name":"darkbound","email":"todor@alphabite.io"},{"name":"nikola-alphabite","email":"nikola@alphabite.io"},{"name":"ivan_alphabite","email":"ivan@alphabite.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/econt-monorepo_1.1.2_1763043871277_0.6300343480859545"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-13T14:20:25.561Z","modified":"2025-11-13T14:24:31.683Z","1.1.1":"2025-11-13T14:20:26.559Z","1.1.2":"2025-11-13T14:24:31.459Z"},"bugs":{"url":"https://github.com/alphabite-dev/econt-sdk/issues"},"author":{"name":"Alphabite"},"license":"MIT","homepage":"https://github.com/alphabite-dev/econt-sdk#readme","keywords":["econt","shipping","bulgaria","logistics","courier","delivery","sdk","api","typescript","cache","nomenclatures"],"repository":{"type":"git","url":"git+https://github.com/alphabite-dev/econt-sdk.git"},"description":"Monorepo for Econt SDK and Types","maintainers":[{"name":"darkbound","email":"todor@alphabite.io"},{"name":"nikola-alphabite","email":"nikola@alphabite.io"},{"name":"ivan_alphabite","email":"ivan@alphabite.io"}],"readme":"# @alphabite/econt-sdk\r\n\r\n[![npm version](https://img.shields.io/npm/v/@alphabite/econt-sdk.svg)](https://www.npmjs.com/package/@alphabite/econt-sdk)\r\n[![TypeScript](https://img.shields.io/badge/TypeScript-100%25-blue.svg)](https://www.typescriptlang.org/)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n\r\nA complete, lightweight TypeScript SDK for the Econt Shipping API. Simple, type-safe, and production-ready.\r\n\r\n## ✨ Features\r\n\r\n- 🎯 **Complete API Coverage** - All 26 Econt API endpoints\r\n- 🔒 **100% Type Safe** - Zero `any` types, full TypeScript support\r\n- 📦 **Dual Format** - CommonJS and ES Modules support\r\n- 🧪 **Well Tested** - 96% test coverage (25/26 tests passing)\r\n- 🚀 **Production Ready** - Lightweight and focused\r\n- 📚 **Well Documented** - Clear examples and guides\r\n- ⚡ **Smart Defaults** - Required filters prevent huge responses\r\n\r\n## 📦 Installation\r\n\r\n```bash\r\nnpm install @alphabite/econt-sdk\r\n```\r\n\r\n## 🚀 Quick Start\r\n\r\n```typescript\r\nimport { EcontClient, ShipmentType } from \"@alphabite/econt-sdk\";\r\n\r\nconst client = new EcontClient({\r\n  username: \"your-username\",\r\n  password: \"your-password\",\r\n  environment: \"demo\",\r\n});\r\n\r\n// Get cities (countryCode required to prevent huge responses)\r\nconst cities = await client.offices.getCities({ countryCode: \"BGR\" });\r\n\r\n// Get offices (filter required)\r\nconst offices = await client.offices.list({ countryCode: \"BGR\" });\r\n\r\n// Calculate shipping\r\nconst cost = await client.shipments.calculate({\r\n  senderClient: { name: \"Sender\", phones: [\"+359888123456\"] },\r\n  senderAddress: { city: cities[0], street: \"Main St\", num: \"1\" },\r\n  receiverClient: { name: \"Receiver\", phones: [\"+359888654321\"] },\r\n  receiverOfficeCode: \"1000\",\r\n  packCount: 1,\r\n  shipmentType: ShipmentType.PACK,\r\n  weight: 2.5,\r\n});\r\n```\r\n\r\n## ⚙️ Configuration\r\n\r\n```typescript\r\nconst client = new EcontClient({\r\n  username: \"your-username\",\r\n  password: \"your-password\",\r\n  environment: \"demo\", // 'demo' or 'production'\r\n  timeout: 30000, // Optional, default: 30000ms\r\n  maxRetries: 3, // Optional, default: 3\r\n});\r\n```\r\n\r\n## ⚠️ Important: Required Filters\r\n\r\nTo prevent timeout errors and huge responses, certain methods require filters:\r\n\r\n### getCities() - countryCode Required\r\n\r\n```typescript\r\n// ✅ Correct\r\nconst cities = await client.offices.getCities({ countryCode: \"BGR\" });\r\n\r\n// ❌ Wrong - will throw error\r\nconst cities = await client.offices.getCities(); // Error!\r\n```\r\n\r\n### list() - At Least One Filter Required\r\n\r\n```typescript\r\n// ✅ Any of these work\r\nconst offices = await client.offices.list({ countryCode: \"BGR\" });\r\nconst offices = await client.offices.list({ cityId: 41 });\r\nconst offices = await client.offices.list({ officeCode: \"1000\" });\r\n\r\n// ❌ Wrong - will throw error\r\nconst offices = await client.offices.list(); // Error!\r\n```\r\n\r\n## 🗄️ Caching Strategies (User-Implemented)\r\n\r\nThe SDK doesn't include built-in caching to keep it lightweight and flexible. Here are recommended caching patterns you can implement:\r\n\r\n### Option 1: Redis Cache\r\n\r\n```typescript\r\nimport Redis from \"ioredis\";\r\n\r\nconst redis = new Redis();\r\nconst client = new EcontClient({\r\n  username: process.env.ECONT_USERNAME!,\r\n  password: process.env.ECONT_PASSWORD!,\r\n});\r\n\r\nasync function getCitiesWithCache(countryCode: string) {\r\n  const key = `econt:cities:${countryCode}`;\r\n\r\n  // Check cache\r\n  const cached = await redis.get(key);\r\n  if (cached) return JSON.parse(cached);\r\n\r\n  // Fetch from API\r\n  const cities = await client.offices.getCities({ countryCode });\r\n\r\n  // Store in cache (24 hour TTL)\r\n  await redis.set(key, JSON.stringify(cities), \"EX\", 86400);\r\n\r\n  return cities;\r\n}\r\n```\r\n\r\n### Option 2: File System Cache\r\n\r\n```typescript\r\nimport * as fs from \"fs\";\r\nimport * as path from \"path\";\r\n\r\nconst CACHE_DIR = \"./cache\";\r\nconst TTL = 24 * 60 * 60 * 1000; // 24 hours\r\n\r\nasync function getCitiesWithFileCache(countryCode: string) {\r\n  const file = path.join(CACHE_DIR, `cities-${countryCode}.json`);\r\n\r\n  // Check if cache exists and is fresh\r\n  if (fs.existsSync(file)) {\r\n    const stats = fs.statSync(file);\r\n    const age = Date.now() - stats.mtime.getTime();\r\n\r\n    if (age < TTL) {\r\n      return JSON.parse(fs.readFileSync(file, \"utf-8\"));\r\n    }\r\n  }\r\n\r\n  // Fetch from API\r\n  const cities = await client.offices.getCities({ countryCode });\r\n\r\n  // Save to cache\r\n  if (!fs.existsSync(CACHE_DIR)) {\r\n    fs.mkdirSync(CACHE_DIR, { recursive: true });\r\n  }\r\n  fs.writeFileSync(file, JSON.stringify(cities, null, 2));\r\n\r\n  return cities;\r\n}\r\n```\r\n\r\n### Option 3: In-Memory Cache\r\n\r\n```typescript\r\nconst cache = new Map<string, { data: any; timestamp: number }>();\r\nconst TTL = 24 * 60 * 60 * 1000;\r\n\r\nasync function getCitiesWithMemoryCache(countryCode: string) {\r\n  const key = `cities:${countryCode}`;\r\n  const cached = cache.get(key);\r\n\r\n  // Check if cache is fresh\r\n  if (cached && Date.now() - cached.timestamp < TTL) {\r\n    return cached.data;\r\n  }\r\n\r\n  // Fetch from API\r\n  const cities = await client.offices.getCities({ countryCode });\r\n\r\n  // Store in cache\r\n  cache.set(key, { data: cities, timestamp: Date.now() });\r\n\r\n  return cities;\r\n}\r\n```\r\n\r\n### Option 4: Database Cache\r\n\r\n```typescript\r\n// Using your ORM (Prisma, TypeORM, etc.)\r\nasync function getCitiesWithDbCache(countryCode: string) {\r\n  // Check database\r\n  let cacheEntry = await db.cache.findUnique({\r\n    where: { key: `cities:${countryCode}` },\r\n  });\r\n\r\n  if (cacheEntry && Date.now() - cacheEntry.timestamp < TTL) {\r\n    return JSON.parse(cacheEntry.data);\r\n  }\r\n\r\n  // Fetch from API\r\n  const cities = await client.offices.getCities({ countryCode });\r\n\r\n  // Store in database\r\n  await db.cache.upsert({\r\n    where: { key: `cities:${countryCode}` },\r\n    create: {\r\n      key: `cities:${countryCode}`,\r\n      data: JSON.stringify(cities),\r\n      timestamp: Date.now(),\r\n    },\r\n    update: {\r\n      data: JSON.stringify(cities),\r\n      timestamp: Date.now(),\r\n    },\r\n  });\r\n\r\n  return cities;\r\n}\r\n```\r\n\r\n## 🎯 Complete Features\r\n\r\n### 1. Nomenclatures (5 endpoints)\r\n\r\n```typescript\r\n// Countries (returns all ~236)\r\nconst countries = await client.offices.getCountries();\r\n\r\n// Cities (requires countryCode)\r\nconst bulgarianCities = await client.offices.getCities({\r\n  countryCode: \"BGR\",\r\n});\r\n\r\n// Offices (requires filter)\r\nconst offices = await client.offices.list({ countryCode: \"BGR\" });\r\nconst sofiaOffices = await client.offices.list({ cityId: 41 });\r\n\r\n// Convenience methods\r\nconst office = await client.offices.get(\"1000\"); // By code\r\nconst byCity = await client.offices.getByCity(41); // By city\r\nconst byCountry = await client.offices.getByCountry(\"BGR\"); // By country\r\n\r\n// Streets\r\nconst streets = await client.offices.getStreets(41); // All in city\r\nconst search = await client.offices.getStreets(41, \"Витоша\"); // Search\r\n\r\n// Quarters\r\nconst quarters = await client.offices.getQuarters(41);\r\n```\r\n\r\n### 2. Address Services (3 endpoints)\r\n\r\n```typescript\r\n// Validate address\r\nconst validation = await client.address.validateAddress({\r\n  address: {\r\n    city: cityObject,\r\n    street: \"бул. Витоша\",\r\n    num: \"100\",\r\n  },\r\n});\r\n\r\n// Get service times\r\nconst times = await client.address.addressServiceTimes({\r\n  city: 41,\r\n  address: \"бул. Витоша 100\",\r\n  date: \"2025-10-29\",\r\n  shipmentType: ShipmentType.PACK,\r\n});\r\n\r\n// Find nearest offices\r\nconst nearest = await client.address.getNearestOffices({\r\n  address: addressObject,\r\n  shipmentType: ShipmentType.PACK,\r\n});\r\n```\r\n\r\n### 3. Shipments & Labels (8 endpoints)\r\n\r\n```typescript\r\nimport { ShipmentType } from \"@alphabite/econt-sdk\";\r\n\r\n// Calculate cost\r\nconst cost = await client.shipments.calculate(labelData);\r\n\r\n// Validate label\r\nconst validation = await client.shipments.validate(labelData);\r\n\r\n// Create shipment\r\nconst shipment = await client.shipments.createLabel(labelData, { mode: \"create\" });\r\n\r\n// Create multiple\r\nconst shipments = await client.shipments.createLabels([label1, label2]);\r\n\r\n// Update\r\nconst updated = await client.shipments.updateLabel(updateData);\r\n\r\n// Delete/cancel\r\nawait client.shipments.deleteLabels([\"123456\", \"123457\"]);\r\n\r\n// Check if editable\r\nconst canEdit = await client.shipments.checkPossibleShipmentEditions([123456]);\r\n\r\n// Group shipments\r\nconst group = await client.shipments.grouping([123456, 123457]);\r\n\r\n// Cancel grouping\r\nawait client.shipments.groupingCancelation(groupId);\r\n```\r\n\r\n### 4. Shipment Services (6 endpoints)\r\n\r\n```typescript\r\n// Request courier\r\nconst courier = await client.shipments.requestCourier({\r\n  senderClient: { name: \"Sender\", phones: [\"+359888123456\"] },\r\n  senderAddress: addressObject,\r\n  shipmentType: ShipmentType.PACK,\r\n});\r\n\r\n// Get courier status\r\nconst courierStatus = await client.shipments.getRequestCourierStatus([\"requestId\"]);\r\n\r\n// Track shipments\r\nconst statuses = await client.shipments.getShipmentStatuses([\"shipmentNumber\"]);\r\n\r\n// Get AWB info\r\nconst awb = await client.shipments.getMyAWB({\r\n  dateFrom: \"2025-10-01\",\r\n  dateTo: \"2025-10-31\",\r\n  side: \"all\",\r\n  page: 1,\r\n});\r\n\r\n// Set ITU code\r\nawait client.shipments.setITUCode(\"awbBarcode\", \"truckRegNum\", \"ITU_code\");\r\n```\r\n\r\n### 5. Tracking (2 methods)\r\n\r\n```typescript\r\n// Track multiple\r\nconst statuses = await client.tracking.track([\"num1\", \"num2\"]);\r\n\r\n// Track single (convenience)\r\nconst status = await client.tracking.trackOne(\"shipmentNumber\");\r\n```\r\n\r\n### 6. Profile Services (2 endpoints)\r\n\r\n```typescript\r\n// Get profiles\r\nconst profiles = await client.profile.getClientProfiles();\r\n\r\n// Create COD agreement\r\nconst agreement = await client.profile.createCDAgreement({\r\n  clientProfile: { name: \"Company\", phones: [\"+359888123456\"] },\r\n  agreementDetails: \"Terms\",\r\n});\r\n```\r\n\r\n## 🛡️ Error Handling\r\n\r\n```typescript\r\nimport { EcontAPIError } from \"@alphabite/econt-sdk\";\r\n\r\ntry {\r\n  const shipment = await client.shipments.createLabel(data);\r\n} catch (error) {\r\n  if (error instanceof EcontAPIError) {\r\n    console.error(\"Status:\", error.statusCode);\r\n    console.error(\"Message:\", error.message);\r\n    console.error(\"Details:\", error.response);\r\n  }\r\n}\r\n```\r\n\r\n## 📘 TypeScript Support\r\n\r\nFull type safety with IntelliSense support:\r\n\r\n```typescript\r\nimport { EcontClient, ShipmentType, City, Office, ShippingLabel } from \"@alphabite/econt-sdk\";\r\n\r\n// All types exported\r\nconst city: City = cities[0];\r\nconst office: Office = offices[0];\r\n\r\n// Enum for shipment types\r\nconst type: ShipmentType = ShipmentType.PACK;\r\n// Available: PACK, DOCUMENT, PALLET, CARGO, etc.\r\n```\r\n\r\n## 💡 Complete Example\r\n\r\n```typescript\r\nimport { EcontClient, ShipmentType } from \"@alphabite/econt-sdk\";\r\n\r\nconst client = new EcontClient({\r\n  username: process.env.ECONT_USERNAME!,\r\n  password: process.env.ECONT_PASSWORD!,\r\n  environment: \"demo\",\r\n});\r\n\r\nasync function createShipment() {\r\n  // 1. Get nomenclatures\r\n  const cities = await client.offices.getCities({ countryCode: \"BGR\" });\r\n  const sofia = cities.find((c) => c.name === \"София\")!;\r\n\r\n  // 2. Find receiver office\r\n  const offices = await client.offices.list({ cityId: sofia.id });\r\n\r\n  // 3. Calculate cost\r\n  const cost = await client.shipments.calculate({\r\n    senderClient: { name: \"Sender\", phones: [\"+359888123456\"] },\r\n    senderAddress: { city: sofia, street: \"Main St\", num: \"1\" },\r\n    receiverClient: { name: \"Receiver\", phones: [\"+359888654321\"] },\r\n    receiverOfficeCode: offices[0].code,\r\n    packCount: 1,\r\n    shipmentType: ShipmentType.PACK,\r\n    weight: 2.5,\r\n  });\r\n\r\n  console.log(`Cost: ${cost.label.totalPrice} ${cost.label.currency}`);\r\n\r\n  // 4. Create shipment\r\n  const shipment = await client.shipments.createLabel(\r\n    cost, // Reuse calculation data\r\n    { mode: \"create\" }\r\n  );\r\n\r\n  console.log(`Shipment: ${shipment.label.shipmentNumber}`);\r\n  console.log(`Label PDF: ${shipment.label.pdfURL}`);\r\n\r\n  // 5. Track\r\n  const status = await client.tracking.trackOne(shipment.label.shipmentNumber!);\r\n\r\n  console.log(`Status: ${status?.shortDeliveryStatus}`);\r\n}\r\n```\r\n\r\n## 📖 API Reference\r\n\r\n### Complete Endpoint Coverage (26 endpoints)\r\n\r\n#### Nomenclatures\r\n\r\n- `getCountries()` - All countries (~236)\r\n- `getCities({ countryCode })` - Cities in country (required)\r\n- `list({ countryCode | cityId | officeCode })` - Offices (filter required)\r\n- `getStreets(cityId, searchTerm?)` - Streets in city\r\n- `getQuarters(cityId)` - Quarters in city\r\n\r\n#### Address Services\r\n\r\n- `validateAddress(params)` - Validate address\r\n- `addressServiceTimes(params)` - Get service times\r\n- `getNearestOffices(params)` - Find nearest offices\r\n\r\n#### Shipments\r\n\r\n- `calculate(label)` - Calculate shipping cost\r\n- `validate(label)` - Validate label\r\n- `createLabel(label, options)` - Create shipment\r\n- `createLabels(labels)` - Bulk create\r\n- `updateLabel(data)` - Update shipment\r\n- `updateLabels(data)` - Bulk update\r\n- `deleteLabels(numbers)` - Cancel shipments\r\n- `checkPossibleShipmentEditions(nums)` - Check if editable\r\n- `grouping(labels)` - Group shipments\r\n- `groupingCancelation(groupId)` - Cancel group\r\n\r\n#### Tracking\r\n\r\n- `track(numbers)` - Track multiple\r\n- `trackOne(number)` - Track single\r\n\r\n#### Profile\r\n\r\n- `getClientProfiles()` - Get profiles\r\n- `createCDAgreement(params)` - Create COD agreement\r\n\r\n[Full API workflow guide →](https://github.com/alphabite-dev/econt-sdk/blob/main/API_WORKFLOW_GUIDE.md)\r\n\r\n## 🧪 Development\r\n\r\n```bash\r\ngit clone https://github.com/alphabite-dev/econt-sdk.git\r\ncd econt-sdk\r\nnpm install\r\ncp .env.example .env\r\n# Edit .env with credentials\r\nnpm run build\r\nnpm test\r\n```\r\n\r\n## 📊 Project Status\r\n\r\n- ✅ 26/26 endpoints implemented\r\n- ✅ 100% TypeScript (zero `any`)\r\n- ✅ 25/26 tests passing\r\n- ✅ Production ready\r\n\r\n## 📄 License\r\n\r\nMIT License - see [LICENSE](LICENSE)\r\n\r\n## 💬 Support\r\n\r\n- 🐛 [Issues](https://github.com/alphabite-dev/econt-sdk/issues)\r\n- 📖 [Documentation](https://github.com/alphabite-dev/econt-sdk)\r\n\r\n---\r\n\r\nMade with ❤️ by [Alphabite](https://alphabite.org)\r\n","readmeFilename":"README.md"}