{"_id":"@coobird-ai/sdk","_rev":"8-e76c78006ef56570415099cf6a657958","name":"@coobird-ai/sdk","dist-tags":{"latest":"2.0.1"},"versions":{"1.0.0":{"name":"@coobird-ai/sdk","version":"1.0.0","_id":"@coobird-ai/sdk@1.0.0","maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"dist":{"shasum":"b94e4d70b14413c0b21bc4838459b6d1cb90f56c","tarball":"https://registry.npmjs.org/@coobird-ai/sdk/-/sdk-1.0.0.tgz","fileCount":8,"integrity":"sha512-a42TCllXmXDZydNdgwNMRixn4DOv1YslY3BckCRdqIs30KVwxROfy1bzOGvnLuF/KsKkFwZq1ux8x8htqZRHmg==","signatures":[{"sig":"MEYCIQDxPmZwEFRhR1Yg7x1lOhZcm1NqiY+1w1dIYduvv4Wh1QIhAKE5xUofsbRjoXEs8VGotV5flJxuoOvXlcLUzJh4UmEz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47306},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"ec4db02d8f4e2fd04c1e2919b3ff3a0c1918ea0e","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","test:watch":"vitest","test:integration":"INTEGRATION_TEST=true vitest run src/__tests__/integration.test.ts"},"_npmUser":{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"},"_npmVersion":"10.8.1","description":"Coomon agent usage tracking SDK","directories":{},"_nodeVersion":"22.4.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.5.4","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.0.0_1774826894903_0.9149734790510504","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@coobird-ai/sdk","version":"1.0.1","keywords":["ai","agent","billing","metering","usage-tracking","monetization","sdk","coobird","llm","credits","wallet"],"author":{"url":"https://coobird.ai","name":"Coobird AI","email":"hello@coobird.ai"},"license":"MIT","_id":"@coobird-ai/sdk@1.0.1","maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"homepage":"https://coobird.ai","bugs":{"url":"https://github.com/coobirdai/coomon/issues"},"dist":{"shasum":"ba1aa5419389324a97de01acec5d15527a1529df","tarball":"https://registry.npmjs.org/@coobird-ai/sdk/-/sdk-1.0.1.tgz","fileCount":8,"integrity":"sha512-7i6S4MeDsaRKKi2N6G1X14TT6I2C59V/sAuHK1qyrTfIHImujTwczIWKkkpLNXLH2qopSaAdvXJXu7jjwGcpnQ==","signatures":[{"sig":"MEYCIQC06mMN/ZhIUlDxm2msByh0oy2TdVlPZG+jGgEQx+S/dQIhALzzrg+vFxk/F50P05mnyDfLRgWVOKq7YVth2/Wa+h4X","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":51583},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a7468ef1b9fbc81c35086b1a6c35db85fa31bfb4","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","test:watch":"vitest","test:integration":"INTEGRATION_TEST=true vitest run src/__tests__/integration.test.ts"},"_npmUser":{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"},"repository":{"url":"git+https://github.com/coobirdai/coomon.git","type":"git","directory":"packages/sdk"},"_npmVersion":"10.8.1","description":"Official Node.js SDK for Coobird — agent usage tracking, metered billing, and wallet management for AI agents.","directories":{},"_nodeVersion":"22.4.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.5.4","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.0.1_1774827107308_0.5463823400408836","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@coobird-ai/sdk","version":"1.0.2","keywords":["ai","agent","billing","metering","usage-tracking","monetization","sdk","coobird","llm","credits","wallet"],"author":{"url":"https://coobird.ai","name":"Coobird AI","email":"hello@coobird.ai"},"license":"MIT","_id":"@coobird-ai/sdk@1.0.2","maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"homepage":"https://coobird.ai","bugs":{"url":"https://github.com/coobirdai/coomon/issues"},"dist":{"shasum":"15508359bda11df781784dd0ce32a8c8c2d857b8","tarball":"https://registry.npmjs.org/@coobird-ai/sdk/-/sdk-1.0.2.tgz","fileCount":8,"integrity":"sha512-8m6RSKqfMjyQfHYUBtJ5uTdXeYdOMqKXkW03uYtZJaUa8+taqxXZrN/V3wQUHV4H3uaTozUSYLTcreBwGzONBA==","signatures":[{"sig":"MEUCIGwUBnt+NWG/yZh4h6D/3XMGu7Mlcb2VmVn/zjobEzNAAiEAhzoB5XwXlzGzfyfxNsW3CzQVhKN3MokqQq+CQXT9aWc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":57185},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"c9b879ea4e80cd0ae9a207eb97fa1be224ddb7f2","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","test:watch":"vitest","test:integration":"INTEGRATION_TEST=true vitest run src/__tests__/integration.test.ts"},"_npmUser":{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"},"repository":{"url":"git+https://github.com/coobirdai/coomon.git","type":"git","directory":"packages/sdk"},"_npmVersion":"10.8.1","description":"Official Node.js SDK for Coobird — agent usage tracking, metered billing, and wallet management for AI agents.","directories":{},"_nodeVersion":"22.4.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.5.4","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.0.2_1774827480660_0.381718276670618","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@coobird-ai/sdk","version":"1.1.0","keywords":["ai","agent","billing","metering","usage-tracking","monetization","sdk","coobird","llm","credits","wallet"],"author":{"url":"https://coobird.ai","name":"Coobird AI","email":"hello@coobird.ai"},"license":"MIT","_id":"@coobird-ai/sdk@1.1.0","maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"homepage":"https://coobird.ai","bugs":{"url":"https://github.com/coobirdai/coomon/issues"},"dist":{"shasum":"5f5aef63cbd6c31299bf392ef73fd50fb44755e3","tarball":"https://registry.npmjs.org/@coobird-ai/sdk/-/sdk-1.1.0.tgz","fileCount":8,"integrity":"sha512-6nYsXicNgfBU53xA4sHWTCPOGq8KJys2YdPHEIBechoixFtN99nI2S6dzqXADnpqc8MY9y2Egw5bsP0/oIIMsA==","signatures":[{"sig":"MEYCIQDrfXhwp/pK2cSxInO4dyYEm+1rN/bTarbVZGAb4IE0WAIhAJkMcsM7kxm9IGAhlfE8dCbuu74FXk7qRTKtyVLhhZo3","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":57683},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"989e2ee11a6a2e5063ff8406cf0f97e699f5f591","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","test:watch":"vitest","test:integration":"INTEGRATION_TEST=true vitest run src/__tests__/integration.test.ts"},"_npmUser":{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"},"repository":{"url":"git+https://github.com/coobirdai/coomon.git","type":"git","directory":"packages/sdk"},"_npmVersion":"10.8.1","description":"Official Node.js SDK for Coobird — agent usage tracking, metered billing, and wallet management for AI agents.","directories":{},"_nodeVersion":"22.4.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.5.4","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.1.0_1775078599284_0.9014381376584619","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@coobird-ai/sdk","version":"1.1.1","keywords":["ai","agent","billing","metering","usage-tracking","monetization","sdk","coobird","llm","credits","wallet"],"author":{"url":"https://coobird.ai","name":"Coobird AI","email":"hello@coobird.ai"},"license":"MIT","_id":"@coobird-ai/sdk@1.1.1","maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"homepage":"https://coobird.ai","bugs":{"url":"https://github.com/coobirdai/coomon/issues"},"dist":{"shasum":"f4176f31c6ea1cfc2dba4d670ba0384bb422ee0e","tarball":"https://registry.npmjs.org/@coobird-ai/sdk/-/sdk-1.1.1.tgz","fileCount":8,"integrity":"sha512-2ldlzkCtc7PvrPjRai/eUPkWH+h1HqiX3nAXJP+pGVFyeSO/AboUVG7nKNuAXZZpaYlaBAIj375kqqDC1fr3/A==","signatures":[{"sig":"MEQCIGBOIjrq1NLp1f8u7fnl7bg+TWdViLjxaPxOS+uKzdhIAiA82blh3ytEY8dG2Slv533fCQV5/vtPYazVNNCKRfA3ZQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58562},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"1ab70ba6efd08cfdd6c043b76b80460dc3a5952d","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","test:watch":"vitest","test:integration":"INTEGRATION_TEST=true vitest run src/__tests__/integration.test.ts"},"_npmUser":{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"},"repository":{"url":"git+https://github.com/coobirdai/coomon.git","type":"git","directory":"packages/sdk"},"_npmVersion":"10.8.1","description":"Official Node.js SDK for Coobird — agent usage tracking, metered billing, and wallet management for AI agents.","directories":{},"_nodeVersion":"22.4.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.5.4","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.1.1_1775079772380_0.5373293444939187","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"@coobird-ai/sdk","version":"1.1.2","keywords":["ai","agent","billing","metering","usage-tracking","monetization","sdk","coobird","llm","credits","wallet"],"author":{"url":"https://coobird.ai","name":"Coobird AI","email":"hello@coobird.ai"},"license":"MIT","_id":"@coobird-ai/sdk@1.1.2","maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"homepage":"https://coobird.ai","bugs":{"url":"https://github.com/coobirdai/coomon/issues"},"dist":{"shasum":"d4e4ac7673b3fe810935af86aa9098561f619baa","tarball":"https://registry.npmjs.org/@coobird-ai/sdk/-/sdk-1.1.2.tgz","fileCount":8,"integrity":"sha512-7jJm9QhZ3GrmD8JFGIMCC1kBTIQyysCTqzkGwO5dMioyn4M87L1o0EQwTPIDGYFpbiDteF3qGHi+pIBcJ4rVTg==","signatures":[{"sig":"MEYCIQD32FQ61AxcyIp114H7Fkvuj+SBnu3Fby4TYRu/snOjRAIhAOSi1614h3uuoitNwPP6gaW69CFnJ3ejt9fJayU5GOfd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58562},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"4517146c95e8ef0d778e33668df94bf927648cc1","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","test:watch":"vitest","test:integration":"INTEGRATION_TEST=true vitest run src/__tests__/integration.test.ts"},"_npmUser":{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"},"repository":{"url":"git+https://github.com/coobirdai/coomon.git","type":"git","directory":"packages/sdk"},"_npmVersion":"10.8.1","description":"Official Node.js SDK for Coobird — agent usage tracking, metered billing, and wallet management for AI agents.","directories":{},"_nodeVersion":"22.4.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.5.4","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.1.2_1775164307098_0.206738880200529","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@coobird-ai/sdk","version":"2.0.0","keywords":["ai","agent","billing","metering","usage-tracking","monetization","sdk","coobird","llm","credits","wallet"],"author":{"url":"https://coobird.ai","name":"Coobird AI","email":"hello@coobird.ai"},"license":"MIT","_id":"@coobird-ai/sdk@2.0.0","maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"homepage":"https://coobird.ai","bugs":{"url":"https://github.com/coobirdai/coomon/issues"},"dist":{"shasum":"005581cf2d2c2cd3580ffdfc1bbabc45d56b30af","tarball":"https://registry.npmjs.org/@coobird-ai/sdk/-/sdk-2.0.0.tgz","fileCount":8,"integrity":"sha512-UA/AQJMiJEEwfGh8sVzxKfA7V/pkbxzNbmSR7VyyzSVs/rKJOUxNHqZ4/8rs7GqOvp+Ishu80hRIBHiAOhK5lQ==","signatures":[{"sig":"MEYCIQC9brfhQylCDW5qQGfBZkY+TA2pR4THjrlSaZCIq1YMKAIhAIgWHTRdiOSdVoplBPrHF5zaBCjAIsEZk/j0TL3E8KoN","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":193796},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"b17423237f0797ed5c3c4ffaca5bf8105cca47a6","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","test:watch":"vitest","test:integration":"INTEGRATION_TEST=true vitest run src/__tests__/integration.test.ts"},"_npmUser":{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"},"repository":{"url":"git+https://github.com/coobirdai/coomon.git","type":"git","directory":"packages/sdk"},"_npmVersion":"10.8.1","description":"Official Node.js SDK for Coobird — agent usage tracking, metered billing, and wallet management for AI agents.","directories":{},"_nodeVersion":"22.4.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.5.4","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_2.0.0_1775325303248_0.8108220586090187","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@coobird-ai/sdk","version":"2.0.1","description":"Official Node.js SDK for Coobird — agent usage tracking, metered billing, and wallet management for AI agents.","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"publishConfig":{"access":"public"},"keywords":["ai","agent","billing","metering","usage-tracking","monetization","sdk","coobird","llm","credits","wallet"],"homepage":"https://coobird.ai","repository":{"type":"git","url":"git+https://github.com/coobirdai/coomon.git","directory":"packages/sdk"},"bugs":{"url":"https://github.com/coobirdai/coomon/issues"},"license":"MIT","author":{"name":"Coobird AI","email":"hello@coobird.ai","url":"https://coobird.ai"},"engines":{"node":">=18"},"scripts":{"build":"tsc","dev":"tsc --watch","test":"vitest run","test:watch":"vitest","test:integration":"INTEGRATION_TEST=true vitest run src/__tests__/integration.test.ts"},"devDependencies":{"@coobird-ai/sdk":"2.0.0","@types/node":"^22.0.0","typescript":"^5.5.4","vitest":"^3.0.0"},"_id":"@coobird-ai/sdk@2.0.1","gitHead":"e4dd68c5d7ad02a702585fbd4e34c9a260401795","_nodeVersion":"22.4.1","_npmVersion":"10.8.1","dist":{"integrity":"sha512-ofiR6I2/6hOwgalvCEWlCaKpmzdZbVI3m7Vh2rF/R8bVdyKhq4YnrlREj25XMjbJVi+hcGYLcR1qGao8eOiMHA==","shasum":"6fd39b880b4e134e725e1b74623a7ef8148d2204","tarball":"https://registry.npmjs.org/@coobird-ai/sdk/-/sdk-2.0.1.tgz","fileCount":8,"unpackedSize":194671,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC+L3xMiu2hxQMGdJEBeYu62qSrktUuQDwm30/8EMpfzwIhAKAbzJOwhCe/7Fg+bNXwduSKRAEbAeGkIU2/S17sk1CT"}]},"_npmUser":{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"},"directories":{},"maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_2.0.1_1775376542706_0.35957892075941866"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-29T23:28:14.816Z","modified":"2026-04-05T08:09:03.028Z","1.0.0":"2026-03-29T23:28:15.027Z","1.0.1":"2026-03-29T23:31:47.447Z","1.0.2":"2026-03-29T23:38:00.796Z","1.1.0":"2026-04-01T21:23:19.407Z","1.1.1":"2026-04-01T21:42:52.622Z","1.1.2":"2026-04-02T21:11:47.248Z","2.0.0":"2026-04-04T17:55:03.389Z","2.0.1":"2026-04-05T08:09:02.903Z"},"bugs":{"url":"https://github.com/coobirdai/coomon/issues"},"author":{"name":"Coobird AI","email":"hello@coobird.ai","url":"https://coobird.ai"},"license":"MIT","homepage":"https://coobird.ai","keywords":["ai","agent","billing","metering","usage-tracking","monetization","sdk","coobird","llm","credits","wallet"],"repository":{"type":"git","url":"git+https://github.com/coobirdai/coomon.git","directory":"packages/sdk"},"description":"Official Node.js SDK for Coobird — agent usage tracking, metered billing, and wallet management for AI agents.","maintainers":[{"name":"afsal.marattil","email":"afsal.marattil@gmail.com"}],"readme":"# @coobird-ai/sdk\n\n[![npm version](https://img.shields.io/npm/v/@coobird-ai/sdk.svg)](https://www.npmjs.com/package/@coobird-ai/sdk)\n[![npm downloads](https://img.shields.io/npm/dm/@coobird-ai/sdk.svg)](https://www.npmjs.com/package/@coobird-ai/sdk)\n\nOfficial Node.js SDK for [Coobird](https://coobird.ai) — agent usage tracking, metered billing, and wallet management.\n\nTrack what your AI agents do, attribute costs to customers, and power your billing pipeline with a few lines of code.\n\n## Installation\n\n```bash\nnpm install @coobird-ai/sdk\n# or\npnpm add @coobird-ai/sdk\n# or\nyarn add @coobird-ai/sdk\n```\n\n**Requirements:** Node.js 18+\n\n## Quick Start\n\n```typescript\nimport { Coomon } from '@coobird-ai/sdk'\n\nconst coomon = new Coomon('sk_live_abc123', {\n  host: 'https://api.coobird.ai',\n})\n\n// Track an agent task\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  signalCode: 'api_call',\n  quantity: 1,\n  attributes: {\n    model: 'claude-3-5-sonnet',\n    input_tokens: 1200,\n    output_tokens: 340,\n  },\n})\n\n// Flush before process exit\nawait coomon.shutdown()\n```\n\n## Connecting to Your Deployment\n\nThe SDK needs two things: an **API key** and a **host** URL.\n\n### API Key\n\nCreate an API key from the Coobird dashboard (Settings > API Keys). The key is scoped to your tenant.\n\n### Host URL\n\nBy default, the SDK points to the **dev** environment at `https://api.dev.coobird.ai`. For production, use `https://api.coobird.ai`:\n\n```typescript\n// Local development\nconst coomon = new Coomon('sk_live_abc123', {\n  host: 'http://localhost:4444',\n})\n\n// Dev (default)\nconst coomon = new Coomon('sk_live_abc123')\n// → uses https://api.dev.coobird.ai\n\n// Production\nconst coomon = new Coomon('sk_live_abc123', {\n  host: 'https://api.coobird.ai',\n})\n```\n\nThe SDK appends `/api/v1/` to the host internally, so just pass the base domain — no trailing slash, no path.\n\n## Event Tracking\n\n### `track()` — Queued (Default)\n\nEvents are queued in memory and sent in batches. This is the fastest path — `track()` returns immediately and never throws.\n\n```typescript\ncoomon.track({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  actionType: 'task',        // 'task' | 'workflow' | 'outcome'\n  signalCode: 'api_call',    // maps to your billing signal\n  quantity: 1,\n  attributes: {\n    model: 'claude-3-5-sonnet',\n    input_tokens: 1200,\n    output_tokens: 340,\n    cost_usd: 0.0042,\n  },\n})\n```\n\nThe queue auto-flushes when it reaches `flushAt` events (default: 20) or every `flushInterval` ms (default: 10s).\n\n### `trackImmediate()` — Awaited (Serverless)\n\nIn serverless environments (AWS Lambda, Vercel Edge, Cloudflare Workers), the process can die before the queue flushes. Use `trackImmediate()` to send the event and await the HTTP response:\n\n```typescript\n// AWS Lambda handler\nexport async function handler(event) {\n  await coomon.trackImmediate({\n    customerId: 'cust_123',\n    agentId: 'agent_xxx',\n    actionType: 'task',\n    signalCode: 'api_call',\n  })\n\n  return { statusCode: 200 }\n}\n```\n\n### Typed Wrappers\n\nConvenience methods that set `actionType` for you:\n\n```typescript\n// Queued (fire-and-forget)\ncoomon.trackTask({ customerId: 'cust_123', agentId: 'agent_xxx', signalCode: 'api_call' })\ncoomon.trackWorkflow({ customerId: 'cust_123', agentId: 'agent_xxx', signalCode: 'pipeline_run' })\ncoomon.trackOutcome({ customerId: 'cust_123', agentId: 'agent_xxx', signalCode: 'report_generated' })\n\n// Immediate (serverless-safe)\nawait coomon.trackTaskImmediate({ customerId: 'cust_123', agentId: 'agent_xxx', signalCode: 'api_call' })\nawait coomon.trackWorkflowImmediate({ customerId: 'cust_123', agentId: 'agent_xxx', signalCode: 'pipeline_run' })\nawait coomon.trackOutcomeImmediate({ customerId: 'cust_123', agentId: 'agent_xxx', signalCode: 'report_generated' })\n```\n\n### Track Options\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `customerId` | `string` | Yes | The customer this event belongs to |\n| `agentId` | `string` | Yes | The agent performing this action |\n| `actionType` | `'task' \\| 'workflow' \\| 'outcome'` | Yes | Event category (set automatically by typed wrappers) |\n| `signalCode` | `string` | No | Maps to a billing signal in your plan |\n| `quantity` | `number` | No | Defaults to `1` |\n| `attributes` | `Record<string, unknown>` | No | Arbitrary key-value data (model, tokens, cost, etc.) |\n| `metadata` | `Record<string, unknown>` | No | Additional metadata |\n| `eventId` | `string` | No | Auto-generated UUID for idempotency. Pass your own to deduplicate. |\n| `timestamp` | `Date` | No | Defaults to `new Date()` |\n\n### Global Attributes\n\nSet attributes that are merged into every event. Event-level attributes override globals.\n\n```typescript\n// Set once at startup\ncoomon.register({\n  model: 'claude-3-5-sonnet',\n  region: 'us-east-1',\n  service: 'my-agent',\n})\n\n// All subsequent events include these attributes\ncoomon.track({ customerId: 'cust_123', agentId: 'agent_xxx', actionType: 'task' })\n// -> attributes: { model: 'claude-3-5-sonnet', region: 'us-east-1', service: 'my-agent' }\n\n// Override per-event\ncoomon.track({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  actionType: 'task',\n  attributes: { model: 'gpt-4o' },  // overrides global 'model'\n})\n\n// Remove a global attribute\ncoomon.unregister('region')\n```\n\n## Cost Tracking\n\nCoobird supports two ways to track costs — choose the one that fits your use case.\n\n### Direct Cost (Fast Path)\n\nIf you already know the cost (e.g., from your LLM provider's response), pass `cost_usd` directly in `attributes` along with a `signalCode`. The enricher reads the cost as-is — no server-side lookups needed.\n\n```typescript\n// OpenAI call — you know the cost from the API response\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  signalCode: 'openai_llm_cost',\n  attributes: {\n    cost_usd: 0.0069,\n    provider: 'openai',\n    model: 'gpt-4o',\n    input_tokens: 1900,\n    output_tokens: 414,\n  },\n})\n\n// Anthropic call\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  signalCode: 'anthropic_llm_cost',\n  attributes: {\n    cost_usd: 0.0042,\n    provider: 'anthropic',\n    model: 'claude-3-5-sonnet',\n    input_tokens: 1200,\n    output_tokens: 340,\n  },\n})\n\n// External API call with known cost\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  signalCode: 'serp_api_cost',\n  attributes: {\n    cost_usd: 0.005,\n    provider: 'serpapi',\n    query: 'competitor analysis',\n  },\n})\n```\n\n**When to use:** You have the exact cost from the provider (LLM API responses, third-party billing APIs).\n\n### Derived Cost (Agent Lookup)\n\nIf you don't know the cost at event time, omit `signalCode` and let Coobird calculate it. The enricher looks up the agent's configured cost signals from the dashboard and applies fixed or variable pricing automatically.\n\n```typescript\n// Simple task — cost is derived from agent config in the dashboard\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  quantity: 1,\n  attributes: {\n    action: 'email_sent',\n  },\n})\n\n// Token-based pricing — enricher reads 'tokens' from attributes\n// and multiplies by the configured cost_per_unit\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  quantity: 1,\n  attributes: {\n    model: 'gpt-4o',\n    tokens: 2500,\n  },\n})\n\n// Multi-quantity — fixed cost is multiplied by quantity\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  quantity: 5,\n  attributes: {\n    action: 'sms_sent',\n    recipient_count: 5,\n  },\n})\n```\n\n**When to use:** Costs are configured in the Coobird dashboard (fixed per-action pricing, variable per-unit pricing). You don't need to calculate costs in your code.\n\n### Cost Categories\n\nCosts are categorized for reporting and margin analysis:\n\n| Category | Use for |\n|---|---|\n| `compute` | Infrastructure, GPU, serverless invocations |\n| `llm` | LLM API costs (OpenAI, Anthropic, etc.) |\n| `api` | Third-party API calls (search, email, SMS) |\n| `storage` | Data storage, file uploads |\n| `bandwidth` | Network egress, CDN |\n| `other` | Miscellaneous costs |\n\nCategories are configured per signal in the Coobird dashboard — the SDK doesn't need to specify them.\n\n### How Cost Derivation Works\n\n```\nSDK event → API → Kafka → Enricher Worker\n                              │\n                              ├─ signalCode provided?\n                              │   ├─ YES → Fast path: read cost_usd from attributes\n                              │   └─ NO  → Agent lookup: find cost signals from dashboard config\n                              │               ├─ Fixed cost: cost_per_unit × quantity\n                              │               └─ Variable cost: attributes[value_field] × cost_per_unit\n                              │\n                              └─ Store enriched event → ClickHouse (analytics) + Postgres (API)\n```\n\n### Billing Quantity\n\nThe billing quantity depends on the signal's aggregation type (configured in the dashboard):\n\n| Aggregation | Billing Quantity | Example |\n|---|---|---|\n| `count` | `event.quantity` (default: 1) | 3 emails sent → quantity = 3 |\n| `sum` | `attributes[quantity_field]` | 1500 tokens used → quantity = 1500 |\n| `max` | `attributes[quantity_field]` | Peak concurrent users |\n| `min` | `attributes[quantity_field]` | Minimum threshold |\n| `average` | `attributes[quantity_field]` | Average response time |\n| `unique_count` | `attributes[quantity_field]` | Unique users served |\n\n### Real-World Examples\n\n#### AI Agent with Multiple Cost Sources\n\n```typescript\n// 1. Track the LLM cost (direct — you know the cost)\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_research',\n  signalCode: 'openai_llm_cost',\n  attributes: {\n    cost_usd: 0.032,\n    model: 'gpt-4o',\n    input_tokens: 5000,\n    output_tokens: 1200,\n  },\n})\n\n// 2. Track a search API call (direct — fixed price per call)\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_research',\n  signalCode: 'search_api_cost',\n  attributes: {\n    cost_usd: 0.01,\n    provider: 'tavily',\n  },\n})\n\n// 3. Track the overall workflow completion (derived — priced in dashboard)\ncoomon.trackWorkflow({\n  customerId: 'cust_123',\n  agentId: 'agent_research',\n  quantity: 1,\n  attributes: {\n    workflow: 'research_report',\n    steps_completed: 5,\n    duration_ms: 45000,\n  },\n})\n\n// 4. Track the business outcome (derived — outcome-based pricing)\ncoomon.trackOutcome({\n  customerId: 'cust_123',\n  agentId: 'agent_research',\n  attributes: {\n    outcome_type: 'report_generated',\n    quality_score: 0.92,\n    pages: 12,\n  },\n})\n```\n\n#### SaaS with Per-Customer Metering\n\n```typescript\n// Track API calls per customer (count-based billing)\ncoomon.trackTask({\n  customerId: req.headers['x-customer-id'],\n  agentId: 'agent_analyzer',\n  signalCode: 'api_request',\n  quantity: 1,\n  attributes: {\n    endpoint: '/v1/analyze',\n    response_time_ms: 230,\n  },\n})\n\n// Track storage usage (sum-based billing)\ncoomon.trackTask({\n  customerId: 'cust_123',\n  agentId: 'agent_storage',\n  signalCode: 'storage_usage',\n  attributes: {\n    bytes_stored: 1_048_576,  // 1 MB\n    file_type: 'pdf',\n  },\n})\n```\n\n### Idempotency\n\nPass an `eventId` to prevent duplicate billing:\n\n```typescript\nconst eventId = crypto.randomUUID()\n\n// Safe to retry — same eventId won't be billed twice\ncoomon.track({\n  customerId: 'cust_123',\n  agentId: 'agent_xxx',\n  actionType: 'task',\n  signalCode: 'api_call',\n  eventId,\n})\n```\n\n## Customer Management\n\nCreate, retrieve, update, list, and delete customers.\n\n```typescript\n// Create\nconst customer = await coomon.createCustomer({\n  name: 'Acme Corp',\n  type: 'company',\n  email: 'billing@acme.com',\n  externalId: 'acme-001',\n  metadata: { tier: 'enterprise' },\n})\n\n// Get by ID\nconst fetched = await coomon.getCustomer(customer.id)\n\n// List with filters\nconst { data, pagination } = await coomon.listCustomers({\n  status: 'active',\n  type: 'company',\n  search: 'acme',\n  page: 1,\n  limit: 25,\n})\n\n// Update\nconst updated = await coomon.updateCustomer(customer.id, {\n  name: 'Acme Corporation',\n  email: 'finance@acme.com',\n  metadata: { tier: 'enterprise', renewed: true },\n})\n\n// Delete\nawait coomon.deleteCustomer(customer.id)\n```\n\n### CreateCustomerOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `name` | `string` | Yes | Customer display name |\n| `type` | `'agent' \\| 'individual' \\| 'company'` | Yes | Customer type |\n| `status` | `'active' \\| 'inactive' \\| 'suspended'` | No | Defaults to `'active'` |\n| `email` | `string` | No | Billing email |\n| `phone` | `string` | No | Phone number |\n| `externalId` | `string` | No | Your system's ID for idempotent lookups |\n| `currency` | `string` | No | Preferred currency (e.g. `'USD'`) |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### UpdateCustomerOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `name` | `string` | No | Customer display name |\n| `type` | `'agent' \\| 'individual' \\| 'company'` | No | Customer type |\n| `status` | `'active' \\| 'inactive' \\| 'suspended'` | No | Customer status |\n| `email` | `string \\| null` | No | Billing email (set `null` to clear) |\n| `phone` | `string \\| null` | No | Phone number (set `null` to clear) |\n| `externalId` | `string \\| null` | No | External ID (set `null` to clear) |\n| `currency` | `string` | No | Preferred currency |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### ListCustomersQuery\n\n| Field | Type | Description |\n|---|---|---|\n| `status` | `string` | Filter by status |\n| `type` | `string` | Filter by customer type |\n| `search` | `string` | Search by name |\n| `page` | `number` | Page number |\n| `limit` | `number` | Results per page |\n| `sort` | `string` | Sort field |\n| `order` | `'asc' \\| 'desc'` | Sort direction |\n\n## Contract Management\n\nContracts link a customer to a pricing plan. All pricing, agent actions, and charges are copied from the plan server-side.\n\n```typescript\n// Create\nconst contract = await coomon.createContract({\n  planId: 'plan_abc',\n  customerId: 'cust_123',\n  name: 'Acme Enterprise Contract',\n  startDate: '2026-04-01',\n  billingInterval: 'monthly',\n})\n\n// Get by ID\nconst fetched = await coomon.getContract(contract.id)\n\n// List with filters\nconst { data, pagination } = await coomon.listContracts({\n  status: 'active',\n  customerId: 'cust_123',\n  planId: 'plan_abc',\n})\n\n// Update\nconst updated = await coomon.updateContract(contract.id, {\n  name: 'Acme Enterprise Contract (Renewed)',\n  endDate: '2027-04-01',\n  paymentTerms: 30,\n})\n\n// Activate\nconst activated = await coomon.activateContract(contract.id, {\n  activationDate: '2026-04-01',\n  skipValidation: false,\n})\n\n// Suspend\nconst suspended = await coomon.suspendContract(contract.id, {\n  suspendReason: 'Payment overdue',\n  resumeDate: '2026-05-01',\n})\n\n// Cancel\nconst cancelled = await coomon.cancelContract(contract.id, {\n  cancellationType: 'end_of_period',\n  refundType: 'prorated',\n  reason: 'Customer churned',\n})\n```\n\n### CreateContractOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `planId` | `string` | Yes | The plan to replicate pricing from |\n| `customerId` | `string` | Yes | The customer to attach the contract to |\n| `name` | `string` | Yes | Contract name |\n| `startDate` | `string` | Yes | Start date (`YYYY-MM-DD`) |\n| `description` | `string` | No | Contract description |\n| `endDate` | `string` | No | End date (`YYYY-MM-DD`) |\n| `billingInterval` | `'daily' \\| 'weekly' \\| 'monthly' \\| 'quarterly' \\| 'annual'` | No | Overrides plan default |\n| `currency` | `string` | No | Currency code |\n| `collectionMethod` | `'charge_automatically' \\| 'send_invoice'` | No | How to collect payment |\n| `paymentTerms` | `number` | No | Net days for invoice payment |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### UpdateContractOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `name` | `string` | No | Contract name |\n| `description` | `string \\| null` | No | Description (set `null` to clear) |\n| `endDate` | `string \\| null` | No | End date (set `null` to clear) |\n| `billingInterval` | `'daily' \\| 'weekly' \\| 'monthly' \\| 'quarterly' \\| 'annual'` | No | Billing interval |\n| `currency` | `string` | No | Currency code |\n| `collectionMethod` | `'charge_automatically' \\| 'send_invoice'` | No | Collection method |\n| `paymentTerms` | `number` | No | Net days for payment |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### ListContractsQuery\n\n| Field | Type | Description |\n|---|---|---|\n| `status` | `string` | Filter by status |\n| `customerId` | `string` | Filter by customer |\n| `planId` | `string` | Filter by plan |\n| `page` | `number` | Page number |\n| `limit` | `number` | Results per page |\n| `sort` | `string` | Sort field |\n| `order` | `'asc' \\| 'desc'` | Sort direction |\n\n### ActivateContractOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `activationDate` | `string` | No | Activation date (`YYYY-MM-DD`) |\n| `skipValidation` | `boolean` | No | Skip validation checks |\n\n### SuspendContractOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `suspendReason` | `string` | No | Reason for suspension |\n| `resumeDate` | `string` | No | Planned resume date (`YYYY-MM-DD`) |\n\n### CancelContractOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `cancellationType` | `'immediate' \\| 'end_of_period'` | Yes | When cancellation takes effect |\n| `refundType` | `'none' \\| 'prorated' \\| 'full'` | No | Refund policy |\n| `reason` | `string` | No | Cancellation reason |\n| `cancellationDate` | `string` | No | Specific cancellation date |\n\n## Agent Management\n\nAgents represent the AI agents you're billing for. Each agent can have multiple actions with associated billing signals.\n\n```typescript\n// Create\nconst agent = await coomon.createAgent({\n  name: 'Research Agent',\n  description: 'Performs web research and generates reports',\n  status: 'active',\n  tags: ['research', 'reports'],\n  metadata: { version: '2.0' },\n})\n\n// Get by ID\nconst fetched = await coomon.getAgent(agent.id)\n\n// List with filters\nconst { data, pagination } = await coomon.listAgents({\n  status: 'active',\n  search: 'research',\n  page: 1,\n  limit: 25,\n})\n\n// Update\nconst updated = await coomon.updateAgent(agent.id, {\n  description: 'Updated description',\n  tags: ['research', 'reports', 'analysis'],\n})\n\n// Delete\nawait coomon.deleteAgent(agent.id)\n```\n\n### CreateAgentOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `name` | `string` | Yes | Agent display name |\n| `description` | `string` | No | Agent description |\n| `externalId` | `string` | No | Your system's ID |\n| `status` | `'draft' \\| 'active' \\| 'inactive' \\| 'archived'` | No | Defaults to `'draft'` |\n| `tags` | `string[]` | No | Tags for filtering |\n| `config` | `Record<string, unknown>` | No | Agent configuration |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### UpdateAgentOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `name` | `string` | No | Agent display name |\n| `description` | `string \\| null` | No | Description (set `null` to clear) |\n| `externalId` | `string \\| null` | No | External ID (set `null` to clear) |\n| `status` | `'draft' \\| 'active' \\| 'inactive' \\| 'archived'` | No | Agent status |\n| `tags` | `string[]` | No | Tags for filtering |\n| `config` | `Record<string, unknown>` | No | Agent configuration |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### ListAgentsQuery\n\n| Field | Type | Description |\n|---|---|---|\n| `status` | `string` | Filter by status |\n| `search` | `string` | Search by name |\n| `has_external_id` | `boolean` | Filter agents with/without external ID |\n| `page` | `number` | Page number |\n| `limit` | `number` | Results per page |\n| `sort` | `string` | Sort field |\n| `order` | `'asc' \\| 'desc'` | Sort direction |\n\n## Agent Actions\n\nActions define the billable operations an agent can perform. Each action has a billable signal that maps to your pricing.\n\n```typescript\n// Create an action for an agent\nconst action = await coomon.createAgentAction(agent.id, {\n  actionName: 'Web Search',\n  actionType: 'task',\n  description: 'Performs a web search query',\n  billableSignal: {\n    signalName: 'Web Search Query',\n    signalCode: 'web_search',\n    aggregationType: 'count',\n    unitLabel: 'queries',\n  },\n  costSignalIds: ['signal_cost_1'],\n  value: {\n    fteEquivalent: 0.1,\n    revenuePerUnit: 0.05,\n    defaultPriceCents: 5,\n  },\n})\n\n// List actions for an agent\nconst { data } = await coomon.listAgentActions(agent.id, {\n  action_type: 'task',\n  search: 'search',\n})\n\n// Update an action\nconst updated = await coomon.updateAgentAction(agent.id, action.id, {\n  description: 'Updated description',\n  billableSignal: {\n    unitLabel: 'searches',\n  },\n  addCostSignalIds: ['signal_cost_2'],\n  removeCostSignalIds: ['signal_cost_1'],\n})\n\n// Delete an action\nawait coomon.deleteAgentAction(agent.id, action.id)\n```\n\n### CreateAgentActionOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `actionName` | `string` | Yes | Action display name |\n| `actionType` | `'task' \\| 'workflow' \\| 'outcome'` | Yes | Action category |\n| `description` | `string` | No | Action description |\n| `billableSignal` | `object` | Yes | The billing signal for this action (see below) |\n| `costSignalIds` | `string[]` | No | IDs of cost signals to associate |\n| `value` | `object` | No | Value metrics (see below) |\n\n**`billableSignal` fields:**\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `signalName` | `string` | Yes | Signal display name |\n| `signalCode` | `string` | Yes | Unique code used in `track()` calls |\n| `aggregationType` | `'count' \\| 'sum' \\| 'max' \\| 'min' \\| 'average' \\| 'unique_count'` | Yes | How to aggregate usage |\n| `unitLabel` | `string` | No | Display label for units (e.g. \"queries\") |\n| `valueField` | `string` | No | Attribute key for value-based aggregation |\n| `description` | `string` | No | Signal description |\n\n**`value` fields:**\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `fteEquivalent` | `number` | No | Full-time-equivalent labor this action replaces |\n| `revenuePerUnit` | `number` | No | Expected revenue per unit |\n| `defaultPriceCents` | `number` | No | Default price in cents |\n\n### UpdateAgentActionOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `actionName` | `string` | No | Action display name |\n| `actionType` | `'task' \\| 'workflow' \\| 'outcome'` | No | Action category |\n| `description` | `string \\| null` | No | Description (set `null` to clear) |\n| `billableSignal` | `object` | No | Partial update to billing signal fields |\n| `costSignalIds` | `string[]` | No | Replace all cost signal IDs |\n| `addCostSignalIds` | `string[]` | No | Add cost signal IDs |\n| `removeCostSignalIds` | `string[]` | No | Remove cost signal IDs |\n| `value` | `object` | No | Value metrics (fields can be set to `null`) |\n\n### ListAgentActionsQuery\n\n| Field | Type | Description |\n|---|---|---|\n| `action_type` | `string` | Filter by action type |\n| `search` | `string` | Search by name |\n| `page` | `number` | Page number |\n| `limit` | `number` | Results per page |\n| `sort` | `string` | Sort field |\n| `order` | `'asc' \\| 'desc'` | Sort direction |\n\n## Create Agent with Actions\n\nCreate an agent and all its actions in a single request.\n\n```typescript\nconst agent = await coomon.createAgentWithActions({\n  agent: {\n    name: 'Customer Support Agent',\n    description: 'Handles customer inquiries',\n    status: 'active',\n  },\n  actions: [\n    {\n      actionName: 'Answer Question',\n      actionType: 'task',\n      billableSignal: {\n        signalName: 'Support Query',\n        signalCode: 'support_query',\n        aggregationType: 'count',\n        unitLabel: 'queries',\n      },\n    },\n    {\n      actionName: 'Generate Report',\n      actionType: 'outcome',\n      billableSignal: {\n        signalName: 'Report Generated',\n        signalCode: 'report_gen',\n        aggregationType: 'count',\n        unitLabel: 'reports',\n      },\n    },\n  ],\n})\n```\n\n### CreateAgentWithActionsOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `agent` | `CreateAgentOptions` | Yes | Agent configuration (see [CreateAgentOptions](#createagentoptions)) |\n| `actions` | `CreateAgentActionOptions[]` | Yes | Array of actions (see [CreateAgentActionOptions](#createagentactionoptions)) |\n\n## Plan Management\n\nPlans define pricing structures that are applied to customers via contracts.\n\n```typescript\n// Create\nconst plan = await coomon.createPlan({\n  name: 'Pro Plan',\n  code: 'pro-2026',\n  description: 'Professional tier with usage-based pricing',\n  planType: 'usage_based',\n  billingPeriod: 'monthly',\n  currency: 'USD',\n  category: 'plan',\n  targetAudience: 'both',\n  trialAvailable: true,\n  trialDays: 14,\n})\n\n// Get by ID\nconst fetched = await coomon.getPlan(plan.id)\n\n// List with filters\nconst { data, pagination } = await coomon.listPlans({\n  status: 'active',\n  search: 'pro',\n  type: 'usage_based',\n})\n\n// Update\nconst updated = await coomon.updatePlan(plan.id, {\n  description: 'Updated pro plan description',\n  trialDays: 30,\n})\n\n// Delete\nawait coomon.deletePlan(plan.id)\n```\n\n### CreatePlanOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `name` | `string` | Yes | Plan display name |\n| `code` | `string` | Yes | Unique plan code |\n| `description` | `string` | No | Plan description |\n| `targetAudience` | `'both' \\| 'human' \\| 'agent'` | No | Target audience |\n| `currency` | `string` | No | Currency code (e.g. `'USD'`) |\n| `category` | `'plan' \\| 'addon'` | No | Plan or add-on |\n| `planType` | `'standard' \\| 'enterprise' \\| 'trial' \\| 'freemium' \\| 'usage_based' \\| 'hybrid'` | No | Plan type |\n| `billingPeriod` | `'daily' \\| 'weekly' \\| 'monthly' \\| 'quarterly' \\| 'semi_annual' \\| 'annual'` | No | Billing period |\n| `trialAvailable` | `boolean` | No | Whether trial is available |\n| `trialDays` | `number` | No | Number of trial days |\n| `status` | `string` | No | Plan status |\n| `parentPlanId` | `string` | No | Parent plan ID (for add-ons) |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### UpdatePlanOptions\n\nAll fields from `CreatePlanOptions` are available but optional. Set `description` to `null` to clear it.\n\n### ListPlansQuery\n\n| Field | Type | Description |\n|---|---|---|\n| `status` | `string` | Filter by status |\n| `search` | `string` | Search by name |\n| `type` | `string` | Filter by plan type |\n| `page` | `number` | Page number |\n| `limit` | `number` | Results per page |\n| `sort` | `string` | Sort field |\n| `order` | `'asc' \\| 'desc'` | Sort direction |\n\n## Plan Charges\n\nFixed or recurring charges attached to a plan (e.g. platform fees, seat licenses).\n\n```typescript\n// Create\nconst charge = await coomon.createPlanCharge(plan.id, {\n  chargeName: 'Platform Fee',\n  chargeCode: 'platform-fee',\n  chargeType: 'recurring',\n  amount: 9900, // cents\n  billingFrequency: 'monthly',\n  description: 'Monthly platform access fee',\n})\n\n// List all charges for a plan\nconst charges = await coomon.listPlanCharges(plan.id)\n\n// Update\nconst updated = await coomon.updatePlanCharge(plan.id, charge.id, {\n  amount: 14900,\n  description: 'Updated platform fee',\n})\n\n// Delete\nawait coomon.deletePlanCharge(plan.id, charge.id)\n```\n\n### CreatePlanChargeOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `chargeName` | `string` | Yes | Charge display name |\n| `chargeCode` | `string` | Yes | Unique charge code |\n| `chargeType` | `'recurring' \\| 'one_time' \\| 'usage_based' \\| 'seat_based'` | Yes | Charge type |\n| `amount` | `number` | Yes | Amount in cents |\n| `description` | `string \\| null` | No | Charge description |\n| `billingFrequency` | `string \\| null` | No | Billing frequency (e.g. `'monthly'`) |\n\n### UpdatePlanChargeOptions\n\nAll fields from `CreatePlanChargeOptions` are available but optional.\n\n## Plan Agent Actions\n\nConfigure pricing for specific agent actions within a plan. This is where you set per-unit pricing, tiered pricing, package pricing, etc.\n\n```typescript\n// Create with per-unit pricing\nconst planAction = await coomon.createPlanAgentAction(plan.id, {\n  agentActionId: action.id,\n  pricingModel: 'per_unit',\n  unitPrice: 50, // cents per unit\n  includedUnits: 100,\n  overageAllowed: true,\n})\n\n// Create with tiered pricing\nconst tieredAction = await coomon.createPlanAgentAction(plan.id, {\n  agentActionId: action.id,\n  pricingModel: 'tiered',\n  tiers: [\n    { tierOrder: 1, startUnit: 0, endUnit: 100, pricePerUnit: 10 },\n    { tierOrder: 2, startUnit: 101, endUnit: 1000, pricePerUnit: 5 },\n    { tierOrder: 3, startUnit: 1001, pricePerUnit: 2 },\n  ],\n})\n\n// List all plan agent actions\nconst actions = await coomon.listPlanAgentActions(plan.id)\n\n// Get a specific plan agent action\nconst fetched = await coomon.getPlanAgentAction(plan.id, planAction.id)\n\n// Update\nconst updated = await coomon.updatePlanAgentAction(plan.id, planAction.id, {\n  unitPrice: 75,\n  includedUnits: 200,\n})\n\n// Delete\nawait coomon.deletePlanAgentAction(plan.id, planAction.id)\n```\n\n### CreatePlanAgentActionOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `agentActionId` | `string` | Yes | The agent action to price |\n| `pricingModel` | `string` | Yes | Pricing model (e.g. `'per_unit'`, `'tiered'`, `'package'`) |\n| `billableSignalId` | `string` | No | Override billable signal |\n| `unitPrice` | `number` | No | Price per unit in cents |\n| `packageSize` | `number` | No | Units per package |\n| `packagePrice` | `number` | No | Price per package in cents |\n| `includedUnits` | `number` | No | Free units included |\n| `minimumCommitment` | `number` | No | Minimum commitment amount |\n| `overageAllowed` | `boolean` | No | Allow usage beyond included units |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n| `tiers` | `array` | No | Pricing tiers (see below) |\n\n**Tier fields:**\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `tierOrder` | `number` | Yes | Tier sequence (1, 2, 3…) |\n| `startUnit` | `number` | Yes | First unit in this tier |\n| `endUnit` | `number \\| null` | No | Last unit (omit for unlimited) |\n| `pricePerUnit` | `number` | Yes | Price per unit in cents |\n| `flatFee` | `number` | No | Flat fee for this tier |\n\n### UpdatePlanAgentActionOptions\n\nAll fields from `CreatePlanAgentActionOptions` are available but optional.\n\n## Pricing Tiers\n\nManage individual pricing tiers on plan agent actions.\n\n```typescript\n// Add a tier\nconst tier = await coomon.createPlanAgentActionTier(plan.id, actionId, {\n  tierOrder: 4,\n  startUnit: 5001,\n  pricePerUnit: 1,\n  flatFee: 0,\n})\n\n// Update a tier\nconst updated = await coomon.updatePlanAgentActionTier(plan.id, actionId, tier.id, {\n  pricePerUnit: 0.5,\n})\n\n// Delete a tier\nawait coomon.deletePlanAgentActionTier(plan.id, actionId, tier.id)\n```\n\n### CreatePricingTierOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `tierOrder` | `number` | Yes | Tier sequence (1, 2, 3…) |\n| `startUnit` | `number` | Yes | First unit in this tier |\n| `endUnit` | `number \\| null` | No | Last unit (omit for unlimited) |\n| `pricePerUnit` | `number` | Yes | Price per unit in cents |\n| `flatFee` | `number` | No | Flat fee for this tier |\n\n### UpdatePricingTierOptions\n\nAll fields from `CreatePricingTierOptions` are available but optional.\n\n## Signal Management\n\nSignals define the billable and cost metrics used across your plans and agent actions.\n\n```typescript\n// Create a billable signal\nconst signal = await coomon.createSignal({\n  signalName: 'API Requests',\n  signalCode: 'api_requests',\n  signalType: 'billable',\n  aggregationType: 'count',\n  unitLabel: 'requests',\n  description: 'Number of API requests made',\n})\n\n// Create a cost signal\nconst costSignal = await coomon.createSignal({\n  signalName: 'LLM Token Cost',\n  signalCode: 'llm_token_cost',\n  signalType: 'cost',\n  aggregationType: 'sum',\n  unitLabel: 'tokens',\n  valueField: 'total_tokens',\n})\n\n// Get by ID\nconst fetched = await coomon.getSignal(signal.id)\n\n// List with filters\nconst { data, pagination } = await coomon.listSignals({\n  signalType: 'billable',\n  status: 'active',\n  search: 'api',\n})\n\n// Update\nconst updated = await coomon.updateSignal(signal.id, {\n  description: 'Updated description',\n  unitLabel: 'calls',\n})\n\n// Delete\nawait coomon.deleteSignal(signal.id)\n```\n\n### CreateSignalOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `signalName` | `string` | Yes | Signal display name |\n| `signalCode` | `string` | Yes | Unique code (used in `track()` calls) |\n| `signalType` | `'billable' \\| 'cost'` | Yes | Whether this signal tracks revenue or cost |\n| `aggregationType` | `'count' \\| 'sum' \\| 'max' \\| 'min' \\| 'average' \\| 'unique_count'` | No | How to aggregate usage |\n| `unitLabel` | `string` | No | Display label for units |\n| `valueField` | `string` | No | Attribute key for value-based aggregation |\n| `description` | `string` | No | Signal description |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### UpdateSignalOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `signalName` | `string` | No | Signal display name |\n| `signalCode` | `string` | No | Unique code |\n| `signalType` | `'billable' \\| 'cost'` | No | Signal type |\n| `aggregationType` | `'count' \\| 'sum' \\| 'max' \\| 'min' \\| 'average' \\| 'unique_count'` | No | Aggregation type |\n| `unitLabel` | `string` | No | Unit label |\n| `valueField` | `string \\| null` | No | Value field (set `null` to clear) |\n| `description` | `string \\| null` | No | Description (set `null` to clear) |\n| `status` | `string` | No | Signal status |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### ListSignalsQuery\n\n| Field | Type | Description |\n|---|---|---|\n| `signalType` | `string` | Filter by signal type |\n| `status` | `string` | Filter by status |\n| `search` | `string` | Search by name |\n| `page` | `number` | Page number |\n| `limit` | `number` | Results per page |\n| `sort` | `string` | Sort field |\n| `order` | `'asc' \\| 'desc'` | Sort direction |\n\n## Payment Management\n\nRecord and manage payments from customers.\n\n```typescript\n// Create a payment\nconst payment = await coomon.createPayment({\n  customerId: 'cust_123',\n  amount: 9900,\n  currency: 'USD',\n  paymentMethod: 'credit_card',\n  invoiceId: 'inv_abc',\n  paymentDate: '2026-04-01',\n  externalTransactionId: 'ch_stripe_123',\n  description: 'April invoice payment',\n})\n\n// Get by ID\nconst fetched = await coomon.getPayment(payment.id)\n\n// List with filters\nconst { data, pagination } = await coomon.listPayments({\n  customerId: 'cust_123',\n  status: 'completed',\n})\n\n// Update\nconst updated = await coomon.updatePayment(payment.id, {\n  status: 'completed',\n  notes: 'Confirmed by bank',\n})\n\n// Refund (full)\nconst refund = await coomon.refundPayment(payment.id)\n\n// Refund (partial)\nconst partialRefund = await coomon.refundPayment(payment.id, {\n  amount: 5000,\n  reason: 'Partial service credit',\n  externalRefundId: 're_stripe_456',\n})\n\n// Delete\nawait coomon.deletePayment(payment.id)\n```\n\n### CreatePaymentOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `customerId` | `string` | Yes | Customer making the payment |\n| `amount` | `number` | Yes | Amount in cents |\n| `invoiceId` | `string` | No | Invoice this payment covers |\n| `currency` | `string` | No | Currency code (e.g. `'USD'`) |\n| `paymentMethod` | `'credit_card' \\| 'debit_card' \\| 'bank_transfer' \\| 'ach' \\| 'wire' \\| 'check' \\| 'cash' \\| 'crypto' \\| 'wallet' \\| 'other'` | No | Payment method |\n| `paymentDate` | `string` | No | Payment date (`YYYY-MM-DD`) |\n| `description` | `string` | No | Payment description |\n| `externalTransactionId` | `string` | No | External payment provider ID |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### UpdatePaymentOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `status` | `string` | No | Payment status |\n| `paymentMethod` | `string` | No | Payment method |\n| `externalTransactionId` | `string` | No | External ID |\n| `failureReason` | `string` | No | Failure reason |\n| `notes` | `string` | No | Notes |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### RefundPaymentOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `amount` | `number` | No | Refund amount in cents (omit for full refund) |\n| `reason` | `string` | No | Refund reason |\n| `externalRefundId` | `string` | No | External refund provider ID |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### ListPaymentsQuery\n\n| Field | Type | Description |\n|---|---|---|\n| `status` | `string` | Filter by status |\n| `customerId` | `string` | Filter by customer |\n| `contractId` | `string` | Filter by contract |\n| `page` | `number` | Page number |\n| `limit` | `number` | Results per page |\n| `sort` | `string` | Sort field |\n| `order` | `'asc' \\| 'desc'` | Sort direction |\n\n## Invoice Management\n\nCreate, manage, and finalize invoices for customers.\n\n```typescript\n// Create an invoice with line items\nconst invoice = await coomon.createInvoice({\n  customerId: 'cust_123',\n  contractId: 'contract_abc',\n  issueDate: '2026-04-01',\n  dueDate: '2026-04-30',\n  billingPeriodFrom: '2026-03-01',\n  billingPeriodTo: '2026-03-31',\n  currency: 'USD',\n  lineItems: [\n    {\n      description: 'API Requests (1,000 units)',\n      quantity: 1000,\n      unitPriceCents: 5,\n      subtotalCents: 5000,\n      totalCents: 5000,\n      pricingModel: 'per_unit',\n      periodFrom: '2026-03-01',\n      periodTo: '2026-03-31',\n    },\n    {\n      description: 'Platform Fee',\n      quantity: 1,\n      unitPriceCents: 9900,\n      subtotalCents: 9900,\n      totalCents: 9900,\n    },\n  ],\n  taxRate: 0.08,\n  notes: 'March 2026 usage',\n  autoFinalize: false,\n})\n\n// Get by ID\nconst fetched = await coomon.getInvoice(invoice.id)\n\n// List with filters\nconst { data, pagination } = await coomon.listInvoices({\n  customerId: 'cust_123',\n  status: 'draft',\n})\n\n// Update\nconst updated = await coomon.updateInvoice(invoice.id, {\n  notes: 'Updated notes',\n  dueDate: '2026-05-15',\n})\n\n// Finalize (lock for payment)\nconst finalized = await coomon.finalizeInvoice(invoice.id, {\n  sendEmail: true,\n})\n\n// Void (cancel a finalized invoice)\nconst voided = await coomon.voidInvoice(invoice.id, {\n  reason: 'Issued in error',\n})\n\n// Preview (calculate without creating)\nconst preview = await coomon.previewInvoice({\n  customerId: 'cust_123',\n  contractId: 'contract_abc',\n})\nconsole.log(preview.amount, preview.line_items)\n```\n\n### CreateInvoiceOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `customerId` | `string` | Yes | Customer to invoice |\n| `issueDate` | `string` | Yes | Issue date (`YYYY-MM-DD`) |\n| `lineItems` | `CreateInvoiceLineItemOptions[]` | Yes | Line items (see below) |\n| `contractId` | `string` | No | Contract this invoice covers |\n| `dueDate` | `string` | No | Due date (`YYYY-MM-DD`) |\n| `billingPeriodFrom` | `string` | No | Billing period start |\n| `billingPeriodTo` | `string` | No | Billing period end |\n| `currency` | `string` | No | Currency code |\n| `taxRate` | `number` | No | Tax rate (e.g. `0.08` for 8%) |\n| `notes` | `string` | No | Invoice notes |\n| `taxes` | `CreateInvoiceTaxOptions[]` | No | Tax line items (see below) |\n| `autoFinalize` | `boolean` | No | Finalize immediately after creation |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### CreateInvoiceLineItemOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `description` | `string` | Yes | Line item description |\n| `quantity` | `number` | Yes | Quantity |\n| `unitPriceCents` | `number` | Yes | Price per unit in cents |\n| `subtotalCents` | `number` | Yes | Subtotal in cents |\n| `totalCents` | `number` | Yes | Total in cents |\n| `contractId` | `string` | No | Source contract |\n| `sourceType` | `string` | No | Source type (e.g. `'agent_action'`) |\n| `sourceId` | `string` | No | Source ID |\n| `agentId` | `string` | No | Agent ID |\n| `featureId` | `string` | No | Feature ID |\n| `signalId` | `string` | No | Signal ID |\n| `pricingModel` | `string` | No | Pricing model used |\n| `periodFrom` | `string` | No | Line item period start |\n| `periodTo` | `string` | No | Line item period end |\n| `includedUnitsUsed` | `number` | No | Included units consumed |\n| `billableUnits` | `number` | No | Billable units beyond included |\n| `tierNumber` | `number` | No | Pricing tier number |\n| `discountCents` | `number` | No | Discount in cents |\n| `taxCents` | `number` | No | Tax in cents |\n| `sortOrder` | `number` | No | Display order |\n\n### CreateInvoiceTaxOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `taxName` | `string` | Yes | Tax name (e.g. \"Sales Tax\") |\n| `taxRate` | `number` | Yes | Tax rate |\n| `taxableAmount` | `number` | Yes | Taxable amount |\n| `taxAmount` | `number` | Yes | Calculated tax amount |\n\n### UpdateInvoiceOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `issueDate` | `string` | No | Issue date |\n| `dueDate` | `string` | No | Due date |\n| `billingPeriodFrom` | `string` | No | Billing period start |\n| `billingPeriodTo` | `string` | No | Billing period end |\n| `currency` | `string` | No | Currency code |\n| `taxRate` | `number` | No | Tax rate |\n| `notes` | `string` | No | Invoice notes |\n| `lineItems` | `CreateInvoiceLineItemOptions[]` | No | Replace line items |\n| `taxes` | `CreateInvoiceTaxOptions[]` | No | Replace tax items |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### FinalizeInvoiceOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `sendEmail` | `boolean` | No | Send invoice email to customer |\n\n### VoidInvoiceOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `reason` | `string` | Yes | Reason for voiding |\n\n### PreviewInvoiceOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `customerId` | `string` | Yes | Customer to preview for |\n| `contractId` | `string` | No | Contract to preview |\n\n## Wallet Management\n\nPrepaid credit wallets for your customers.\n\n```typescript\n// Create wallet\nconst wallet = await coomon.createWallet({\n  customerId: 'cust_123',\n  name: 'Main Credits',\n  currency: 'USD',\n})\n\n// Add credits\nconst topUp = await coomon.topUpWallet(wallet.id, {\n  amount: 100,\n  creditType: 'purchased',\n  idempotencyKey: 'topup-001',  // prevents double-charging\n})\n\n// Check balance\nconst balance = await coomon.getWalletBalance(wallet.id)\nconsole.log(balance.credits_balance) // 100\n\n// Deduct credits\nconst deduction = await coomon.deductWallet(wallet.id, {\n  amount: 30,\n  description: 'Agent API usage',\n  idempotencyKey: 'debit-001',\n})\n\n// Get wallet details\nconst details = await coomon.getWallet(wallet.id)\n```\n\n### CreateWalletOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `customerId` | `string` | Yes | Owner customer ID |\n| `name` | `string` | Yes | Wallet display name |\n| `description` | `string` | No | Wallet description |\n| `currency` | `string` | No | Currency code (e.g. `'USD'`) |\n| `conversionRate` | `number` | No | 1 monetary unit = N credits |\n| `initialCredits` | `number` | No | Seed balance on creation |\n| `autoRechargeEnabled` | `boolean` | No | Enable auto top-up |\n| `autoRechargeThreshold` | `number` | No | Top up when balance drops below this |\n| `autoRechargeAmount` | `number` | No | Credits to add on each recharge |\n| `allowNegativeBalance` | `boolean` | No | Allow balance to go negative |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### TopUpWalletOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `amount` | `number` | Yes | Amount to credit |\n| `creditAmount` | `number` | No | Override credit amount (if different from amount) |\n| `creditType` | `'free' \\| 'purchased' \\| 'promotional' \\| 'bonus'` | No | Type of credit |\n| `description` | `string` | No | Transaction description |\n| `idempotencyKey` | `string` | No | Prevents duplicate transactions |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n### DeductWalletOptions\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `amount` | `number` | Yes | Amount to debit |\n| `description` | `string` | No | Transaction description |\n| `idempotencyKey` | `string` | No | Prevents duplicate transactions |\n| `metadata` | `Record<string, unknown>` | No | Arbitrary key-value data |\n\n## Configuration\n\n```typescript\nconst coomon = new Coomon('sk_live_abc123', {\n  host: 'https://api.coobird.ai',\n  flushAt: 20,\n  flushInterval: 10_000,\n  maxRetries: 3,\n  maxBatchSize: 100,\n  maxQueueSize: 1000,\n  requestTimeout: 10_000,\n  shutdownTimeoutMs: 30_000,\n  debug: false,\n  disabled: false,\n  onError: (err) => console.error('Coobird SDK error:', err),\n})\n```\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `host` | `string` | `'https://api.dev.coobird.ai'` | API host URL. Use `https://api.coobird.ai` for production. |\n| `flushAt` | `number` | `20` | Auto-flush when queue reaches this many events |\n| `flushInterval` | `number` | `10000` | Auto-flush every N ms. Set `0` to disable timer. |\n| `maxRetries` | `number` | `3` | Retry attempts on retriable failures (5xx, 429, network errors) |\n| `maxBatchSize` | `number` | `100` | Max events per HTTP request |\n| `maxQueueSize` | `number` | `1000` | Max events in memory. Oldest dropped when exceeded. |\n| `requestTimeout` | `number` | `10000` | Per-request timeout in ms. Uses `AbortController`. |\n| `shutdownTimeoutMs` | `number` | `30000` | Max time to wait during `shutdown()` |\n| `debug` | `boolean` | `false` | Enable verbose `[coomon]` logging to console |\n| `disabled` | `boolean` | `false` | Disable all tracking (useful in tests/CI) |\n| `onError` | `(err) => void` | `console.error` | Called on unrecoverable send errors |\n\n## Environments\n\n### Long-Running Servers (Express, Fastify, NestJS)\n\nUse the queued `track()` methods for best performance. Call `shutdown()` on process exit:\n\n```typescript\nimport { Coomon } from '@coobird-ai/sdk'\n\nconst coomon = new Coomon(process.env.COOBIRD_API_KEY, {\n  host: 'https://api.coobird.ai',\n})\n\n// In your route handler\napp.post('/run-agent', async (req, res) => {\n  const result = await runAgent(req.body)\n\n  coomon.trackTask({\n    customerId: req.body.customerId,\n    agentId: 'agent_xxx',\n    signalCode: 'agent_run',\n    attributes: { model: result.model, tokens: result.tokens },\n  })\n\n  res.json(result)\n})\n\n// Graceful shutdown\nprocess.on('SIGTERM', async () => {\n  await coomon.shutdown()\n  process.exit(0)\n})\n```\n\n### Serverless (AWS Lambda, Vercel, Cloudflare Workers)\n\nUse `trackImmediate()` to ensure events are sent before the function returns:\n\n```typescript\nimport { Coomon } from '@coobird-ai/sdk'\n\nconst coomon = new Coomon(process.env.COOBIRD_API_KEY, {\n  host: 'https://api.coobird.ai',\n  flushInterval: 0,  // disable background timer (not useful in serverless)\n})\n\nexport async function handler(event) {\n  const result = await runAgent(event.body)\n\n  await coomon.trackTaskImmediate({\n    customerId: event.body.customerId,\n    agentId: 'agent_xxx',\n    signalCode: 'agent_run',\n    attributes: { model: result.model },\n  })\n\n  return { statusCode: 200, body: JSON.stringify(result) }\n}\n```\n\n### Tests & CI\n\nDisable the SDK to avoid sending real events:\n\n```typescript\nconst coomon = new Coomon('sk_test_key', { disabled: true })\n\ncoomon.track({ ... })  // no-op\nawait coomon.trackImmediate({ ... })  // returns { accepted: 0, ... }\nawait coomon.createCustomer({ ... })  // throws '[coomon] SDK is disabled'\n```\n\n## Retry Behavior\n\nThe SDK retries intelligently based on error type:\n\n| Error | Retried? | Why |\n|---|---|---|\n| Network error | Yes | Transient connectivity issue |\n| 429 Too Many Requests | Yes | Rate limited, back off and retry |\n| 500, 502, 503, 504 | Yes | Server error, likely transient |\n| 400 Bad Request | No | Client error, won't succeed on retry |\n| 401 Unauthorized | No | Invalid API key |\n| 403 Forbidden | No | Permission denied |\n| 404 Not Found | No | Resource doesn't exist |\n\nRetries use exponential backoff: 1s, 2s, 4s, etc.\n\nFor **queued events** (`track()`), errors are reported via `onError` and the event is dropped. For **direct calls** (`createCustomer()`, `trackImmediate()`), errors are thrown to the caller.\n\n## TypeScript\n\nFull TypeScript support with all types exported:\n\n```typescript\nimport type {\n  // Configuration\n  CoomonOptions,\n\n  // Event tracking\n  TrackOptions,\n  TrackTaskOptions,\n  TrackWorkflowOptions,\n  TrackOutcomeOptions,\n  BatchTrackResponse,\n  TrackEventResponse,\n\n  // Common\n  PaginatedResponse,\n  ListQuery,\n\n  // Customers\n  CreateCustomerOptions,\n  UpdateCustomerOptions,\n  CustomerResponse,\n  ListCustomersQuery,\n\n  // Contracts\n  CreateContractOptions,\n  UpdateContractOptions,\n  ActivateContractOptions,\n  SuspendContractOptions,\n  CancelContractOptions,\n  ContractResponse,\n  ListContractsQuery,\n\n  // Agents\n  CreateAgentOptions,\n  UpdateAgentOptions,\n  AgentResponse,\n  ListAgentsQuery,\n  CreateAgentWithActionsOptions,\n\n  // Agent Actions\n  CreateAgentActionOptions,\n  UpdateAgentActionOptions,\n  AgentActionResponse,\n  ListAgentActionsQuery,\n\n  // Plans\n  CreatePlanOptions,\n  UpdatePlanOptions,\n  PlanResponse,\n  ListPlansQuery,\n\n  // Plan Charges\n  CreatePlanChargeOptions,\n  UpdatePlanChargeOptions,\n  PlanChargeResponse,\n\n  // Plan Agent Actions\n  CreatePlanAgentActionOptions,\n  UpdatePlanAgentActionOptions,\n  PlanAgentActionResponse,\n\n  // Pricing Tiers\n  CreatePricingTierOptions,\n  UpdatePricingTierOptions,\n  PricingTierResponse,\n\n  // Signals\n  CreateSignalOptions,\n  UpdateSignalOptions,\n  SignalResponse,\n  ListSignalsQuery,\n\n  // Payments\n  CreatePaymentOptions,\n  UpdatePaymentOptions,\n  RefundPaymentOptions,\n  PaymentResponse,\n  PaymentListResponse,\n  RefundResponse,\n  ListPaymentsQuery,\n\n  // Invoices\n  CreateInvoiceOptions,\n  CreateInvoiceLineItemOptions,\n  CreateInvoiceTaxOptions,\n  UpdateInvoiceOptions,\n  FinalizeInvoiceOptions,\n  VoidInvoiceOptions,\n  PreviewInvoiceOptions,\n  InvoiceResponse,\n  InvoiceActionResponse,\n  InvoicePreviewResponse,\n  ListInvoicesQuery,\n\n  // Wallets\n  CreateWalletOptions,\n  WalletResponse,\n  WalletBalanceResponse,\n  TopUpWalletOptions,\n  DeductWalletOptions,\n  WalletTransactionResponse,\n} from '@coobird-ai/sdk'\n```\n\n## API Reference\n\n### Constructor\n\n```typescript\nnew Coomon(apiKey: string, options?: CoomonOptions)\n```\n\nThrows if `apiKey` is empty or missing.\n\n### Event Tracking\n\n| Method | Returns | Description |\n|---|---|---|\n| `track(options)` | `void` | Queue event for batch delivery |\n| `trackTask(options)` | `void` | Queue task event |\n| `trackWorkflow(options)` | `void` | Queue workflow event |\n| `trackOutcome(options)` | `void` | Queue outcome event |\n| `trackImmediate(options)` | `Promise<BatchTrackResponse>` | Send event immediately |\n| `trackTaskImmediate(options)` | `Promise<BatchTrackResponse>` | Send task event immediately |\n| `trackWorkflowImmediate(options)` | `Promise<BatchTrackResponse>` | Send workflow event immediately |\n| `trackOutcomeImmediate(options)` | `Promise<BatchTrackResponse>` | Send outcome event immediately |\n\n### Global Attributes\n\n| Method | Returns | Description |\n|---|---|---|\n| `register(attributes)` | `void` | Set attributes merged into every event |\n| `unregister(key)` | `void` | Remove a global attribute |\n\n### Customers\n\n| Method | Returns | Description |\n|---|---|---|\n| `createCustomer(options)` | `Promise<CustomerResponse>` | Create a customer |\n| `getCustomer(id)` | `Promise<CustomerResponse>` | Get customer by ID |\n| `listCustomers(query?)` | `Promise<PaginatedResponse<CustomerResponse>>` | List customers |\n| `updateCustomer(id, options)` | `Promise<CustomerResponse>` | Update a customer |\n| `deleteCustomer(id)` | `Promise<void>` | Delete a customer |\n\n### Contracts\n\n| Method | Returns | Description |\n|---|---|---|\n| `createContract(options)` | `Promise<ContractResponse>` | Create a contract |\n| `getContract(id)` | `Promise<ContractResponse>` | Get contract by ID |\n| `listContracts(query?)` | `Promise<PaginatedResponse<ContractResponse>>` | List contracts |\n| `updateContract(id, options)` | `Promise<ContractResponse>` | Update a contract |\n| `activateContract(id, options?)` | `Promise<ContractResponse>` | Activate a draft contract |\n| `suspendContract(id, options?)` | `Promise<ContractResponse>` | Suspend an active contract |\n| `cancelContract(id, options)` | `Promise<ContractResponse>` | Cancel a contract |\n\n### Agents\n\n| Method | Returns | Description |\n|---|---|---|\n| `createAgent(options)` | `Promise<AgentResponse>` | Create an agent |\n| `getAgent(id)` | `Promise<AgentResponse>` | Get agent by ID |\n| `listAgents(query?)` | `Promise<PaginatedResponse<AgentResponse>>` | List agents |\n| `updateAgent(id, options)` | `Promise<AgentResponse>` | Update an agent |\n| `deleteAgent(id)` | `Promise<void>` | Delete an agent |\n| `createAgentWithActions(options)` | `Promise<AgentResponse>` | Create agent with actions in one call |\n\n### Agent Actions\n\n| Method | Returns | Description |\n|---|---|---|\n| `createAgentAction(agentId, options)` | `Promise<AgentActionResponse>` | Create an agent action |\n| `listAgentActions(agentId, query?)` | `Promise<PaginatedResponse<AgentActionResponse>>` | List agent actions |\n| `updateAgentAction(agentId, actionId, options)` | `Promise<AgentActionResponse>` | Update an agent action |\n| `deleteAgentAction(agentId, actionId)` | `Promise<void>` | Delete an agent action |\n\n### Plans\n\n| Method | Returns | Description |\n|---|---|---|\n| `createPlan(options)` | `Promise<PlanResponse>` | Create a plan |\n| `getPlan(id)` | `Promise<PlanResponse>` | Get plan by ID |\n| `listPlans(query?)` | `Promise<PaginatedResponse<PlanResponse>>` | List plans |\n| `updatePlan(id, options)` | `Promise<PlanResponse>` | Update a plan |\n| `deletePlan(id)` | `Promise<void>` | Delete a plan |\n\n### Plan Charges\n\n| Method | Returns | Description |\n|---|---|---|\n| `createPlanCharge(planId, options)` | `Promise<PlanChargeResponse>` | Create a plan charge |\n| `listPlanCharges(planId)` | `Promise<PlanChargeResponse[]>` | List plan charges |\n| `updatePlanCharge(planId, chargeId, options)` | `Promise<PlanChargeResponse>` | Update a plan charge |\n| `deletePlanCharge(planId, chargeId)` | `Promise<void>` | Delete a plan charge |\n\n### Plan Agent Actions\n\n| Method | Returns | Description |\n|---|---|---|\n| `createPlanAgentAction(planId, options)` | `Promise<PlanAgentActionResponse>` | Create a plan agent action |\n| `listPlanAgentActions(planId)` | `Promise<PlanAgentActionResponse[]>` | List plan agent actions |\n| `getPlanAgentAction(planId, actionId)` | `Promise<PlanAgentActionResponse>` | Get a plan agent action |\n| `updatePlanAgentAction(planId, actionId, options)` | `Promise<PlanAgentActionResponse>` | Update a plan agent action |\n| `deletePlanAgentAction(planId, actionId)` | `Promise<void>` | Delete a plan agent action |\n\n### Pricing Tiers (Plan Agent Actions)\n\n| Method | Returns | Description |\n|---|---|---|\n| `createPlanAgentActionTier(planId, actionId, options)` | `Promise<PricingTierResponse>` | Add a pricing tier |\n| `updatePlanAgentActionTier(planId, actionId, tierId, options)` | `Promise<PricingTierResponse>` | Update a pricing tier |\n| `deletePlanAgentActionTier(planId, actionId, tierId)` | `Promise<void>` | Delete a pricing tier |\n\n### Signals\n\n| Method | Returns | Description |\n|---|---|---|\n| `createSignal(options)` | `Promise<SignalResponse>` | Create a signal |\n| `getSignal(id)` | `Promise<SignalResponse>` | Get signal by ID |\n| `listSignals(query?)` | `Promise<PaginatedResponse<SignalResponse>>` | List signals |\n| `updateSignal(id, options)` | `Promise<SignalResponse>` | Update a signal |\n| `deleteSignal(id)` | `Promise<void>` | Delete a signal |\n\n### Payments\n\n| Method | Returns | Description |\n|---|---|---|\n| `createPayment(options)` | `Promise<PaymentResponse>` | Create a payment |\n| `getPayment(id)` | `Promise<PaymentResponse>` | Get payment by ID |\n| `listPayments(query?)` | `Promise<PaginatedResponse<PaymentResponse>>` | List payments |\n| `updatePayment(id, options)` | `Promise<PaymentResponse>` | Update a payment |\n| `refundPayment(id, options?)` | `Promise<RefundResponse>` | Refund a payment |\n| `deletePayment(id)` | `Promise<void>` | Delete a payment |\n\n### Invoices\n\n| Method | Returns | Description |\n|---|---|---|\n| `createInvoice(options)` | `Promise<InvoiceResponse>` | Create an invoice |\n| `getInvoice(id)` | `Promise<InvoiceResponse>` | Get invoice by ID |\n| `listInvoices(query?)` | `Promise<PaginatedResponse<InvoiceResponse>>` | List invoices |\n| `updateInvoice(id, options)` | `Promise<InvoiceResponse>` | Update an invoice |\n| `finalizeInvoice(id, options?)` | `Promise<InvoiceActionResponse>` | Finalize an invoice |\n| `voidInvoice(id, options)` | `Promise<InvoiceActionResponse>` | Void an invoice |\n| `previewInvoice(options)` | `Promise<InvoicePreviewResponse>` | Preview invoice calculation |\n\n### Wallets\n\n| Method | Returns | Description |\n|---|---|---|\n| `createWallet(options)` | `Promise<WalletResponse>` | Create a prepaid wallet |\n| `getWallet(walletId)` | `Promise<WalletResponse>` | Get wallet details |\n| `getWalletBalance(walletId)` | `Promise<WalletBalanceResponse>` | Get current balance |\n| `topUpWallet(walletId, options)` | `Promise<WalletTransactionResponse>` | Add credits |\n| `deductWallet(walletId, options)` | `Promise<WalletTransactionResponse>` | Deduct credits |\n\n### Lifecycle\n\n| Method | Returns | Description |\n|---|---|---|\n| `flush()` | `Promise<BatchTrackResponse \\| null>` | Drain the queue manually |\n| `shutdown()` | `Promise<void>` | Flush + stop timer. Call before process exit. |\n\n## License\n\nMIT\n","readmeFilename":"README.md"}