JSPM

@cybin/client

0.1.2
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 8
    • Score
      100M100P100Q71681F
    • License MIT

    Typed client for Cybin event tracking and contact management

    Package Exports

    • @cybin/client

    Readme

    @cybin/client

    Typed Node.js client for Cybin — event tracking and contact management for transactional email funnels.

    Install

    npm install @cybin/client
    # or
    pnpm add @cybin/client
    # or
    bun add @cybin/client

    Requires Node 18+ (for native fetch).

    Quick start

    import { createCybinClient } from "@cybin/client";
    
    const cybin = createCybinClient({
      apiKey: process.env.CYBIN_API_KEY!,
    });
    
    // Fire a typed event — compile-time checked
    await cybin.track.plantSignup({
      userId: "user-123",
      email: "derek@example.com",
      firstName: "Derek",
      trialEndsAt: new Date("2026-05-08"),
      dashboardUrl: "https://plantapp.co/app",
    });

    Every typed track.* helper:

    • Enforces required merge tags at compile time. Forget firstName → red squiggle.
    • Auto-serializes Dates to ISO 8601 strings for you.
    • Uses the correct event name (plant.signup, etc.) — no typos.
    • Returns { ok: true, eventId } on success.

    Typed events

    // Trial signup
    await cybin.track.plantSignup({
      userId, email, firstName, trialEndsAt, dashboardUrl,
    });
    
    // Trial ending in 3 days
    await cybin.track.trialEndingSoon({
      userId, email, firstName, trialEndsAt, dashboardUrl,
    });
    
    // Trial expired without conversion
    await cybin.track.trialExpired({
      userId, email, firstName, dashboardUrl,
    });
    
    // One-time purchase
    await cybin.track.purchaseCompleted({
      userId, email, firstName,
      amount: 4900,          // cents
      currency: "USD",
      receiptUrl: "https://...",
    });
    
    // Subscription renewed
    await cybin.track.subscriptionRenewed({
      userId, email, firstName,
      amount: 4900,
      currency: "USD",
      nextBillingDate: new Date("2026-06-08"),
    });
    
    // Payment failed
    await cybin.track.paymentFailed({
      userId, email, firstName,
      updatePaymentUrl: "https://plantapp.co/billing",
    });
    
    // Subscription cancelled
    await cybin.track.subscriptionCancelled({
      userId, email, firstName,
      accessUntil: new Date("2026-06-08"),
    });

    Untyped / custom events

    await cybin.track.event({
      userId: "user-123",
      email: "derek@example.com",
      event: "custom.thing_happened",
      properties: { foo: "bar", count: 3 },
    });

    Identify (set user traits without firing an event)

    await cybin.identify({
      userId: "user-123",
      email: "derek@example.com",
      name: "Derek Howlett",
      traits: { plan: "pro", referredBy: "twitter" },
    });

    Newsletter subscribe

    await cybin.subscribe({
      email: "derek@example.com",
      listId: "newsletter",
      source: "homepage-footer",
    });

    Error handling

    import {
      CybinAuthError,
      CybinValidationError,
      CybinNetworkError,
    } from "@cybin/client";
    
    try {
      await cybin.track.plantSignup({ /* ... */ });
    } catch (err) {
      if (err instanceof CybinAuthError) {
        // API key is bad. Rotate it.
      } else if (err instanceof CybinValidationError) {
        // 4xx — payload problem. Check err.body for details.
      } else if (err instanceof CybinNetworkError) {
        // Retries exhausted. Queue for later or drop.
      } else {
        throw err;
      }
    }

    4xx errors are not retried (they're permanent). 5xx and network errors are retried with exponential backoff — by default up to 3 total attempts.

    Options

    createCybinClient({
      apiKey: "cyb_sk_live_...",
    
      // Optional — defaults to https://www.cybin.app
      baseUrl: "https://staging.cybin.app",
    
      // Optional — set false in tests to make every call a no-op
      enabled: process.env.NODE_ENV !== "test",
    
      // Optional — override fetch (for polyfills, tracing, etc.)
      fetch: myCustomFetch,
    
      // Optional — retry budget for 5xx / network errors. Default: 2
      maxRetries: 3,
    });

    Getting an API key

    Visit https://www.cybin.app/settings/api-keys and create one. The full key is only shown at creation — save it somewhere safe (1Password, env var, etc.).

    License

    MIT