Official TypeScript SDK for the Affonso API.
- Complete coverage of all 64 documented API operations
- Zero runtime dependencies; uses the standard
fetchand Web Crypto APIs - Node.js 18+ and modern browser support
- ESM, CommonJS, and TypeScript declarations
- Auto-pagination, retry with backoff, typed errors, and optional HMAC signing
npm install @affonso/sdkimportAffonsofrom"@affonso/sdk";constaffonso=newAffonso("sk_live_...");constpage=awaitaffonso.affiliates.list({limit: 50});forawait(constaffiliateofpage.autoPaginate()){console.log(affiliate.id);}constaffonso=newAffonso("sk_live_...",{baseUrl: "https://api.affonso.io/v1",// defaulttimeout: 30_000,// default: 30 secondsmaxRetries: 2,// retries 429 and 5xx responsessigningSecret: "your-s2s-secret",// optional conversion/event HMAC signingsourceSigningSecrets: {// optional per-source HMAC signingcustom: "your-custom-source-secret",segment: "your-segment-source-secret",},fetch: customFetch,// optional fetch implementation});When 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.
| Resource | Methods |
|---|---|
affiliates | list, retrieve, create, update, del, retrieveOnboardingResponses, submitOnboardingResponses, createPortalToken |
referrals | list, retrieve, create, update, del |
clicks | create |
signups | create |
commissions | list, retrieve, create, update, del |
conversions | create, refund |
events | create |
sources | ingest, ingestSegment |
tracking | track |
payouts | list, retrieve, update |
coupons | list, retrieve, create, del |
embedTokens | create |
marketplace | list, retrieve |
onboardingForm | retrieve, create, update, del |
program | retrieve, update |
program.paymentTerms | retrieve, update |
program.tracking | retrieve, update |
program.restrictions | retrieve, update |
program.groups | list, retrieve, create, update, del |
program.creatives | list, retrieve, create, update, del |
program.notifications | list, update |
program.portal | retrieve, update |
program.fraudRules | retrieve, update |
Create the team onboarding form:
constform=awaitaffonso.onboardingForm.create({name: "Partner application",description: "Tell us how you plan to promote our product.",questions: [{question: "What is your primary channel?",type: "single_choice",is_required: true,options: ["Content","Email","Paid media"],order: 0,},],});Submit an affiliate's answers and mark onboarding complete:
awaitaffonso.affiliates.submitOnboardingResponses("aff_123",{responses: [{question_id: form.questions[0].id,answer: "Content",},],mark_complete: true,});Configure the signing secret used by your Affonso API environment, then create an idempotent conversion:
constaffonso=newAffonso("sk_live_...",{signingSecret: process.env.AFFONSO_SIGNING_SECRET,});constconversion=awaitaffonso.conversions.create({external_user_id: "customer_123",external_event_id: "order_987",sale_amount: 99,sale_amount_currency: "USD",product_ids: ["pro_plan"],});Send a non-monetary milestone event through the same signed request path:
awaitaffonso.events.create({event_name: "demo_booked",event_type: "lead",external_user_id: "customer_123",external_event_id: "demo_456",occurred_at: newDate().toISOString(),});The authenticated signups.create() method converts an existing click into a lead:
awaitaffonso.signups.create({click_id: "ref_123",email: "customer@example.com",external_user_id: "customer_123",});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.
constclick=awaitaffonso.tracking.track({programId: "prog_123",trackingId: "partner-name",referrer: "https://example.com/pricing",userAgent: request.headers.get("user-agent")??"",hasConsent: true,});Affiliates, commissions, coupons, payouts, marketplace programs, and creatives use offset pagination:
constpage=awaitaffonso.affiliates.list({page: 1,limit: 25});constnextPage=awaitpage.getNextPage();Referrals use cursor pagination:
constpage=awaitaffonso.referrals.list({limit: 25});constnextPage=awaitpage.getNextPage();Both page types support asynchronous iteration across all remaining pages:
forawait(constitemofpage.autoPaginate()){console.log(item.id);}Pass expand and include fields as comma-separated strings matching the API:
constaffiliate=awaitaffonso.affiliates.retrieve("aff_123",{expand: "promoCodes,commissionOverrides,invoiceDetails,payoutMethod,onboardingResponses",});constreferral=awaitaffonso.referrals.retrieve("ref_123",{expand: "affiliate",include: "stats",});constcommissions=awaitaffonso.commissions.list({expand: "affiliate,referral",});import{DuplicateError,NotFoundError,RateLimitError,ValidationError,}from"@affonso/sdk";try{awaitaffonso.affiliates.retrieve("missing");}catch(error){if(errorinstanceofNotFoundError){// 404 / NOT_FOUND}elseif(errorinstanceofRateLimitError){console.log(error.retryAfter);}elseif(errorinstanceofValidationError){console.log(error.details);}elseif(errorinstanceofDuplicateError){console.log(error.field);}}All SDK errors extend AffonsoError and can include status, code, field, details, and response headers.
Version 1.0 removes program-setting fields that were not accepted by the current API. Update integrations to use the current snake_case fields, including:
track_email→email_tracking_enabledtrack_name→name_tracking_enabledpostbacks→postbacks_enabled- current payment-term, restriction, portal, fraud-rule, creative, and notification models
See CHANGELOG.md for the full breaking-change summary.
MIT