npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@raba7ni/raba7ni

v2.1.1

Published

Official SDK for the Raba7ni Platform Developer API - Loyalty, Cashback & Coins

Downloads

31

Readme

@raba7ni/raba7ni v2.1.1

Official TypeScript SDK for the Raba7ni Platform Developer API.

npm version TypeScript Node.js

What's New in v2.0

  • Product-based API structure - Separate endpoints for Loyalty, Cashback, and Coins
  • Internal member token management - Automatic token handling after authentication
  • Points & Stamps operations - Earn, redeem, balance, and history
  • Cashback operations - Full cashback earn/redeem workflow
  • Coins operations - Wallet management, issue/spend coins
  • Member authentication - OTP-based auth for customer-facing apps

Installation

npm install @raba7ni/raba7ni

Quick Start

import { Raba7niSDK } from "@raba7ni/raba7ni";

const sdk = new Raba7niSDK({
  appId: "app_your_app_id",
  apiKey: "dev_your_api_key",
});

// Test connection
const scopes = await sdk.testConnection();
console.log("Connected! Scopes:", scopes.scopes);

// Earn points for a member (identify by phone, email, or memberId)
const result = await sdk.earnPoints(5, 25.0, { phone: "+21612345678" });
console.log("Points earned:", result.points_earned);

Configuration

| Option | Type | Default | Description | | ------------ | -------- | ------------------------- | ----------------------------------- | | appId | string | required | Application ID (starts with app_) | | apiKey | string | required | API Key (starts with dev_) | | baseUrl | string | https://app.raba7ni.com | API base URL | | timeout | number | 30000 | Request timeout (ms) | | maxRetries | number | 3 | Max retry attempts | | retryDelay | number | 1000 | Initial retry delay (ms) |


Member Authentication

Many operations (redemptions, wallet access) require member authentication. The SDK handles token storage internally.

Member Management

// Check if a member exists (by email or phone)
const check = await sdk.checkMember({ email: "[email protected]" });
// or: await sdk.checkMember({ phone: "+21612345678" });
if (check.exists) {
  console.log("Member found:", check.member);
}

// Register a new member
const newMember = await sdk.registerMember({
  name: "John Doe",
  email: "[email protected]",
  phone: "+21612345678",
});

Request & Verify OTP

// Step 1: Request OTP (sent to member's email or phone)
await sdk.requestMemberOTP({ email: "[email protected]" });
// or: await sdk.requestMemberOTP({ phone: '+21612345678' });

// Step 2: Verify OTP (token stored internally)
const auth = await sdk.verifyMemberOTP({
  email: "[email protected]",
  code: "123456",
});
console.log("Authenticated as:", auth.member.name);

// Now authenticated endpoints will work automatically
const wallet = await sdk.getWallet();

Token Management

// Check if authenticated
if (sdk.isAuthenticated()) {
  // Can use authenticated endpoints
}

// Manually set token (e.g., from stored session)
sdk.setMemberToken("token_abc123", "2025-12-31T23:59:59Z");

// Clear token (logout)
sdk.clearMemberToken();
// or
await sdk.logoutMember(); // Also invalidates on server

Loyalty API

Points

// Earn points from purchase - identify member by phone, email, or memberId
const earn = await sdk.earnPoints(cardId, 25.0, { phone: "+21612345678" }, {
  staff_identifier: "staff_001",
  note: "Coffee purchase",
  reference: "ORDER-123",
});
console.log("Earned:", earn.points_earned, "New balance:", earn.new_balance);
console.log("Is new member:", earn.is_new_member);

// Identify by email instead
const earn2 = await sdk.earnPoints(cardId, 50.0, { email: "[email protected]" });

// Identify by member ID
const earn3 = await sdk.earnPoints(cardId, 30.0, { memberId: 123 });

// Get balance
const balance = await sdk.getPointsBalance(cardId, "+21612345678");
console.log("Current points:", balance.balance);

// Get history
const history = await sdk.getPointsHistory(cardId, "+21612345678", {
  limit: 20,
  offset: 0,
});

// Refund points (for returns/cancellations)
const refund = await sdk.refundPoints(cardId, 25.0, { phone: "+21612345678" }, {
  points_to_deduct: 50,
  reference: "REFUND-123",
});
console.log("Points deducted:", refund.points_deducted);

// Redeem points (requires authentication)
await sdk.verifyMemberOTP({ email: "[email protected]", code: "123456" });
const redeem = await sdk.redeemPoints(cardId, rewardId);
console.log("Redeemed reward:", redeem.reward.name);

Stamps

// Add stamps
const stamp = await sdk.addStamps(cardId, "+21612345678", 1);
console.log("Stamps:", stamp.new_balance, "/", stamp.stamps_required);

// Get balance
const balance = await sdk.getStampsBalance(cardId, "+21612345678");

// Redeem stamps (requires authentication)
const redeem = await sdk.redeemStamps(cardId, rewardId);

Cards & Rewards

// List available cards
const { cards } = await sdk.listCards();

// Get card details
const card = await sdk.getCardInfo(cardId);

// Get rewards for a card
const { rewards } = await sdk.listCardRewards(cardId);

Claims

// Request claim OTP
await sdk.requestClaimOTP("[email protected]", cardId, rewardId);

// Create claim request
const { claim_request } = await sdk.createClaimRequest({
  member_email: "[email protected]",
  card_id: cardId,
  reward_id: rewardId,
  verification_code: "123456",
  member_note: "Please deliver to office",
});

// Approve/Reject (staff operations)
await sdk.approveClaimRequest(claim_request.id, "Approved!");
await sdk.rejectClaimRequest(claim_request.id, "Out of stock");

Referrals

// Get stats
const stats = await sdk.getReferralStats(cardId);

// Validate code
const result = await sdk.validateReferralCode("REF123ABC", cardId);
if (result.is_valid) {
  console.log("Referred by:", result.referrer?.name);
}

// Apply referral
await sdk.applyReferral("REF123ABC", cardId, "[email protected]");

Cashback API

// Earn cashback from purchase - identify member by phone, email, or memberId
const earn = await sdk.earnCashback(cardId, 100.0, { phone: "+21612345678" }, {
  reference: "ORDER-123",
});
console.log(
  "Cashback earned:",
  earn.cashback_earned,
  "(",
  earn.cashback_percentage,
  "%)"
);
console.log("Is new member:", earn.is_new_member);

// Identify by email instead
const earn2 = await sdk.earnCashback(cardId, 50.0, { email: "[email protected]" });

// Get balance
const balance = await sdk.getCashbackBalance(cardId, "+21612345678");

// Get history
const history = await sdk.getCashbackHistory(cardId, "+21612345678");

// Refund cashback (for returns/cancellations)
const refund = await sdk.refundCashback(cardId, 50.0, { phone: "+21612345678" }, {
  cashback_to_deduct: 2.5,
  reference: "REFUND-123",
});
console.log("Cashback deducted:", refund.cashback_deducted);

// Redeem cashback (requires authentication + PIN)
await sdk.verifyMemberOTP({ email: "[email protected]", code: "123456" });
const redeem = await sdk.redeemCashback(cardId, 10.0, "1234");

// List cashback cards
const { cards } = await sdk.listCashbackCards();

Coins API

Wallet Operations (Authenticated)

// Must authenticate first
await sdk.verifyMemberOTP({ email: "[email protected]", code: "123456" });

// Get wallet balance
const wallet = await sdk.getWallet();
console.log("Coins:", wallet.wallet.coin_balance);
console.log("Value in TND:", wallet.wallet.balance_in_tnd);

// Get QR code for receiving coins (requires PIN setup)
const qr = await sdk.getWalletQR();
console.log("QR Data:", qr.qr_data);

// Get transaction history
const history = await sdk.getWalletHistory({ limit: 50 });

Coin Operations

// Issue coins to member (from purchase) - identify by phone, email, or memberId
const issue = await sdk.issueCoins(clubId, 50.0, { phone: "+21612345678" }, {
  campaign_id: 5,
  reference: "ORDER-123",
});
console.log("Coins issued:", issue.coins_issued);
console.log("Campaign bonus:", issue.campaign_bonus);
console.log("Is new member:", issue.is_new_member);

// Identify by email instead
const issue2 = await sdk.issueCoins(clubId, 30.0, { email: "[email protected]" });

// Refund coins (for returns/cancellations)
const refund = await sdk.refundCoins(clubId, 50.0, { phone: "+21612345678" }, {
  coins_to_deduct: 25,
  reference: "REFUND-123",
});
console.log("Coins deducted:", refund.coins_deducted);

// Spend coins (requires authentication + PIN)
await sdk.verifyMemberOTP({ email: "[email protected]", code: "123456" });
const spend = await sdk.spendCoins(clubId, 100, "1234");
console.log("Spent:", spend.coins_spent, "= TND", spend.amount_in_tnd);

// List participating clubs
const { clubs } = await sdk.listCoinsClubs();

// List active campaigns
const campaigns = await sdk.listCoinsCampaigns(clubId);

Webhook Handling

import { WebhookHandler } from "@raba7ni/raba7ni";

const handler = new WebhookHandler("your_webhook_secret");

// Express example
app.post("/webhooks", async (req, res) => {
  const signature = req.headers["x-webhook-signature"] as string;
  const payload = JSON.stringify(req.body);

  try {
    await handler.handleWebhook(payload, signature, {
      onMemberJoined: async (data) => {
        console.log("New member:", data.member.name);
      },
      onClaimRequestCreated: async (data) => {
        console.log("New claim:", data.claim_request.id);
      },
      onClaimRequestProcessed: async (data) => {
        console.log("Claim processed:", data.status);
      },
    });
    res.status(200).send("OK");
  } catch (error) {
    res.status(400).send("Invalid webhook");
  }
});

Error Handling

import {
  Raba7niError,
  AuthenticationError,
  RateLimitError,
  ValidationError,
  MemberTokenRequiredError,
} from "@raba7ni/raba7ni";

try {
  await sdk.redeemPoints(5, 10);
} catch (error) {
  if (error instanceof MemberTokenRequiredError) {
    console.error("Please authenticate first");
  } else if (error instanceof AuthenticationError) {
    console.error("Invalid credentials");
  } else if (error instanceof RateLimitError) {
    console.error("Rate limited, retry after:", error.retryAfter);
  } else if (error instanceof ValidationError) {
    console.error("Validation errors:", error.validationErrors);
  } else if (error instanceof Raba7niError) {
    console.error("API error:", error.message, error.code);
  }
}

Rate Limiting

const info = sdk.getRateLimitInfo();
console.log("Hourly remaining:", info.hourlyRemaining);
console.log("Daily remaining:", info.dailyRemaining);

Utilities

import {
  normalizePhoneNumber,
  validateEmail,
  validateCardId,
} from "@raba7ni/raba7ni";

normalizePhoneNumber("+1 (555) 123-4567"); // '+15551234567'
validateEmail("[email protected]"); // true
validateCardId("5"); // 5 (number)

TypeScript Types

All types are exported:

import type {
  Member,
  Card,
  Reward,
  EarnPointsResponse,
  WalletResponse,
  CoinCampaign,
  // ... and many more
} from "@raba7ni/raba7ni";

Migration from v1.x

Breaking Changes

  1. Legacy methods removed: getMemberDetails(), findOrCreateMember() - use product-specific endpoints
  2. New auth flow: Use requestMemberOTP() + verifyMemberOTP() for member auth
  3. Internal token storage: Token is stored in SDK after verifyMemberOTP()

Migration Examples

// v1.x
const details = await sdk.getMemberDetails(cardId, phone);

// v2.0
const balance = await sdk.getPointsBalance(cardId, phone);
// or for authenticated member data:
await sdk.verifyMemberOTP({ phone, code: "123456" });
const profile = await sdk.getMemberProfile();

Requirements

  • Node.js 18+
  • TypeScript 5.0+ (for TypeScript users)

Support

License

MIT © Raba7ni