{"_id":"@affonso/sdk","_rev":"3-e917215611796e599aeaca6e070a4e3c","name":"@affonso/sdk","dist-tags":{"latest":"1.0.1"},"versions":{"0.1.0":{"name":"@affonso/sdk","version":"0.1.0","keywords":["affonso","affiliate","sdk","api"],"license":"MIT","_id":"@affonso/sdk@0.1.0","maintainers":[{"name":"silvestro","email":"silvestro@affonso.io"}],"dist":{"shasum":"9afebf43bb2cdb019bf9dbe0189dec00e70b091b","tarball":"https://registry.npmjs.org/@affonso/sdk/-/sdk-0.1.0.tgz","fileCount":8,"integrity":"sha512-mzD3odulj7QaOCVgvCHpQq9WurwGfzeIrRb0DzbJKl9wOaWai/lk/tKDsC+sL7YX/ZrgZ56qtf13ymQ0lPVkZQ==","signatures":[{"sig":"MEYCIQDpXCVV1go91QUxM+XpWPVH2sfARxRWAPGO1TY/wC+OYQIhAMzPBy9MuPftc1LTWFcJFdOMDDzGxW52GePm8arJiiKG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":167294},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"gitHead":"2048e68ff45fe6ef79069231301983f44d01e5f5","scripts":{"lint":"biome check src __tests__","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","lint:fix":"biome check --write src __tests__","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"silvestro","email":"silvestro@affonso.io"},"_npmVersion":"10.9.2","description":"Official TypeScript SDK for the Affonso API","directories":{},"sideEffects":false,"_nodeVersion":"22.13.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.0.0","typescript":"^5.5.0","@types/node":"^25.5.2","@biomejs/biome":"^1.9.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.0_1775848587338_0.6446528650712091","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@affonso/sdk","version":"0.2.0","keywords":["affonso","affiliate","sdk","api"],"license":"MIT","_id":"@affonso/sdk@0.2.0","maintainers":[{"name":"silvestro","email":"silvestro@affonso.io"}],"dist":{"shasum":"5d9f00008c8aee694c5344a3d6cfe643d9ebae57","tarball":"https://registry.npmjs.org/@affonso/sdk/-/sdk-0.2.0.tgz","fileCount":8,"integrity":"sha512-joZK8M0ngsFQ1jWXS4SYjJoBrULJZjy9+67uxMx7AFnf4wpl7ao/iiCCB0TGzEOBhk1ZJSiNtBF93nlOhvu8aA==","signatures":[{"sig":"MEQCIER5moVpDFFOPexBRaIf2ATMypOdzsaJcVZ2tiCBCrywAiAS7IAjGnFqcxQ0VLOITPgg1bbecnORhaAs5Zj8XG2lLw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":265996},"main":"./dist/index.cjs","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"biome check src __tests__","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","lint:fix":"biome check --write src __tests__","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"silvestro","email":"silvestro@affonso.io"},"_npmVersion":"10.9.2","description":"Official TypeScript SDK for the Affonso API","directories":{},"sideEffects":false,"_nodeVersion":"22.13.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.0.0","typescript":"^5.5.0","@types/node":"^25.5.2","@biomejs/biome":"^1.9.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.2.0_1776381608491_0.40591498462210107","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@affonso/sdk","version":"1.0.1","description":"Official TypeScript SDK for the Affonso API","main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.cjs"}}},"engines":{"node":">=18"},"sideEffects":false,"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean","test":"vitest run","typecheck":"tsc --noEmit","lint":"biome check src __tests__","lint:fix":"biome check --write src __tests__","prepublishOnly":"npm run build"},"devDependencies":{"@biomejs/biome":"^1.9.0","@types/node":"^25.5.2","tsup":"^8.0.0","typescript":"^5.5.0","vitest":"^2.0.0"},"keywords":["affonso","affiliate","sdk","api"],"license":"MIT","_id":"@affonso/sdk@1.0.1","_nodeVersion":"22.13.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-PKph2IAVtUoDle7LFu6GJNd4rxXWpn8tUREMefE7wM/nPPeS+jQ66BlVqDY4Iz+p6/4YHaALAUC7vsgxrGFA8A==","shasum":"155170740a314d3738f3ee481db5d221b997e720","tarball":"https://registry.npmjs.org/@affonso/sdk/-/sdk-1.0.1.tgz","fileCount":8,"unpackedSize":337578,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDlF4KCv5QLJpE9XE7AZjg+SGI7SZIbBHYzzmuD118HSAiEAm7IquR5GQwtosFwc2ZKmo63JHBz3KgyVkg6PoSs8puY="}]},"_npmUser":{"name":"silvestro","email":"silvestro@affonso.io"},"directories":{},"maintainers":[{"name":"silvestro","email":"silvestro@affonso.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_1.0.1_1784498008619_0.2850691131234213"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-10T19:16:27.201Z","modified":"2026-07-19T21:53:28.931Z","0.1.0":"2026-04-10T19:16:27.469Z","0.2.0":"2026-04-16T23:20:08.635Z","1.0.1":"2026-07-19T21:53:28.754Z"},"license":"MIT","keywords":["affonso","affiliate","sdk","api"],"description":"Official TypeScript SDK for the Affonso API","maintainers":[{"name":"silvestro","email":"silvestro@affonso.io"}],"readme":"# @affonso/sdk\n\nOfficial TypeScript SDK for the [Affonso](https://affonso.io) API.\n\n- Complete coverage of all 64 documented API operations\n- Zero runtime dependencies; uses the standard `fetch` and Web Crypto APIs\n- Node.js 18+ and modern browser support\n- ESM, CommonJS, and TypeScript declarations\n- Auto-pagination, retry with backoff, typed errors, and optional HMAC signing\n\n## Installation\n\n```bash\nnpm install @affonso/sdk\n```\n\n## Quick start\n\n```ts\nimport Affonso from \"@affonso/sdk\";\n\nconst affonso = new Affonso(\"sk_live_...\");\n\nconst page = await affonso.affiliates.list({ limit: 50 });\n\nfor await (const affiliate of page.autoPaginate()) {\n  console.log(affiliate.id);\n}\n```\n\n## Configuration\n\n```ts\nconst affonso = new Affonso(\"sk_live_...\", {\n  baseUrl: \"https://api.affonso.io/v1\", // default\n  timeout: 30_000,                       // default: 30 seconds\n  maxRetries: 2,                         // retries 429 and 5xx responses\n  signingSecret: \"your-s2s-secret\",      // optional conversion/event HMAC signing\n  sourceSigningSecrets: {                 // optional per-source HMAC signing\n    custom: \"your-custom-source-secret\",\n    segment: \"your-segment-source-secret\",\n  },\n  fetch: customFetch,                    // optional fetch implementation\n});\n```\n\nWhen `signingSecret` is set, the SDK automatically signs conversion, refund, event, and source-ingestion requests. Use `sourceSigningSecrets` when the API configures a different secret per source adapter. The signature covers the exact JSON string sent in the request body.\n\n## Resources\n\n| Resource | Methods |\n| --- | --- |\n| `affiliates` | `list`, `retrieve`, `create`, `update`, `del`, `retrieveOnboardingResponses`, `submitOnboardingResponses`, `createPortalToken` |\n| `referrals` | `list`, `retrieve`, `create`, `update`, `del` |\n| `clicks` | `create` |\n| `signups` | `create` |\n| `commissions` | `list`, `retrieve`, `create`, `update`, `del` |\n| `conversions` | `create`, `refund` |\n| `events` | `create` |\n| `sources` | `ingest`, `ingestSegment` |\n| `tracking` | `track` |\n| `payouts` | `list`, `retrieve`, `update` |\n| `coupons` | `list`, `retrieve`, `create`, `del` |\n| `embedTokens` | `create` |\n| `marketplace` | `list`, `retrieve` |\n| `onboardingForm` | `retrieve`, `create`, `update`, `del` |\n| `program` | `retrieve`, `update` |\n| `program.paymentTerms` | `retrieve`, `update` |\n| `program.tracking` | `retrieve`, `update` |\n| `program.restrictions` | `retrieve`, `update` |\n| `program.groups` | `list`, `retrieve`, `create`, `update`, `del` |\n| `program.creatives` | `list`, `retrieve`, `create`, `update`, `del` |\n| `program.notifications` | `list`, `update` |\n| `program.portal` | `retrieve`, `update` |\n| `program.fraudRules` | `retrieve`, `update` |\n\n## Onboard an affiliate\n\nCreate the team onboarding form:\n\n```ts\nconst form = await affonso.onboardingForm.create({\n  name: \"Partner application\",\n  description: \"Tell us how you plan to promote our product.\",\n  questions: [\n    {\n      question: \"What is your primary channel?\",\n      type: \"single_choice\",\n      is_required: true,\n      options: [\"Content\", \"Email\", \"Paid media\"],\n      order: 0,\n    },\n  ],\n});\n```\n\nSubmit an affiliate's answers and mark onboarding complete:\n\n```ts\nawait affonso.affiliates.submitOnboardingResponses(\"aff_123\", {\n  responses: [\n    {\n      question_id: form.questions[0].id,\n      answer: \"Content\",\n    },\n  ],\n  mark_complete: true,\n});\n```\n\n## Track server-side activity\n\nConfigure the signing secret used by your Affonso API environment, then create an idempotent conversion:\n\n```ts\nconst affonso = new Affonso(\"sk_live_...\", {\n  signingSecret: process.env.AFFONSO_SIGNING_SECRET,\n});\n\nconst conversion = await affonso.conversions.create({\n  external_user_id: \"customer_123\",\n  external_event_id: \"order_987\",\n  sale_amount: 99,\n  sale_amount_currency: \"USD\",\n  product_ids: [\"pro_plan\"],\n});\n```\n\nSend a non-monetary milestone event through the same signed request path:\n\n```ts\nawait affonso.events.create({\n  event_name: \"demo_booked\",\n  event_type: \"lead\",\n  external_user_id: \"customer_123\",\n  external_event_id: \"demo_456\",\n  occurred_at: new Date().toISOString(),\n});\n```\n\nThe authenticated `signups.create()` method converts an existing click into a lead:\n\n```ts\nawait affonso.signups.create({\n  click_id: \"ref_123\",\n  email: \"customer@example.com\",\n  external_user_id: \"customer_123\",\n});\n```\n\n## Call the public tracking endpoint\n\n`tracking.track()` is a thin, typed wrapper around `POST /track`. It does not collect browser information and is not a replacement for Affonso's browser pixel. Pass consent, advertising identifiers, page context, and user-agent data explicitly.\n\n```ts\nconst click = await affonso.tracking.track({\n  programId: \"prog_123\",\n  trackingId: \"partner-name\",\n  referrer: \"https://example.com/pricing\",\n  userAgent: request.headers.get(\"user-agent\") ?? \"\",\n  hasConsent: true,\n});\n```\n\n## Pagination\n\nAffiliates, commissions, coupons, payouts, marketplace programs, and creatives use offset pagination:\n\n```ts\nconst page = await affonso.affiliates.list({ page: 1, limit: 25 });\nconst nextPage = await page.getNextPage();\n```\n\nReferrals use cursor pagination:\n\n```ts\nconst page = await affonso.referrals.list({ limit: 25 });\nconst nextPage = await page.getNextPage();\n```\n\nBoth page types support asynchronous iteration across all remaining pages:\n\n```ts\nfor await (const item of page.autoPaginate()) {\n  console.log(item.id);\n}\n```\n\n## Expand related data\n\nPass expand and include fields as comma-separated strings matching the API:\n\n```ts\nconst affiliate = await affonso.affiliates.retrieve(\"aff_123\", {\n  expand: \"promoCodes,commissionOverrides,invoiceDetails,payoutMethod,onboardingResponses\",\n});\n\nconst referral = await affonso.referrals.retrieve(\"ref_123\", {\n  expand: \"affiliate\",\n  include: \"stats\",\n});\n\nconst commissions = await affonso.commissions.list({\n  expand: \"affiliate,referral\",\n});\n```\n\n## Handle errors\n\n```ts\nimport {\n  DuplicateError,\n  NotFoundError,\n  RateLimitError,\n  ValidationError,\n} from \"@affonso/sdk\";\n\ntry {\n  await affonso.affiliates.retrieve(\"missing\");\n} catch (error) {\n  if (error instanceof NotFoundError) {\n    // 404 / NOT_FOUND\n  } else if (error instanceof RateLimitError) {\n    console.log(error.retryAfter);\n  } else if (error instanceof ValidationError) {\n    console.log(error.details);\n  } else if (error instanceof DuplicateError) {\n    console.log(error.field);\n  }\n}\n```\n\nAll SDK errors extend `AffonsoError` and can include `status`, `code`, `field`, `details`, and response `headers`.\n\n## Migrating from 0.2.x\n\nVersion 1.0 removes program-setting fields that were not accepted by the current API. Update integrations to use the current snake_case fields, including:\n\n- `track_email` → `email_tracking_enabled`\n- `track_name` → `name_tracking_enabled`\n- `postbacks` → `postbacks_enabled`\n- current payment-term, restriction, portal, fraud-rule, creative, and notification models\n\nSee [CHANGELOG.md](./CHANGELOG.md) for the full breaking-change summary.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}