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

@bzbs/react-api-client

v2.0.0

Published

React API Client for Buzzebees

Readme

@bzbs/react-api-client

A TypeScript library providing a type-safe API client for Buzzebees loyalty and reward services. Supports authentication, campaigns, user profiles, shopping carts, notifications, stamps, consent management, and more.

Version: 1.4.15 | License: ISC | Author: Buzzebees Co., Ltd. Repository: Azure DevOps


Table of Contents


Installation

npm install @bzbs/react-api-client

Peer dependency: axios

npm install axios

Quick Start

import axios from 'axios';
import { BzbsService } from '@bzbs/react-api-client';

// 1. Create an Axios instance with default headers
const axiosClient = axios.create({
  headers: {
    'Content-Type': 'application/json',
    'App-Id': '<your-app-id>',
    'Ocp-Apim-Subscription-Key': '<your-subscription-key>',
  },
});

// 2. Define base URLs
const baseUrl = 'https://apigateway.buzzebees.com/api/';
const lineUrl = 'https://api.line.me/';       // Optional, pass "" to skip
const blobUrl = 'https://blob.buzzebees.com/'; // Blob storage URL

// 3. Create the service
const bzbsService = new BzbsService(axiosClient, baseUrl, lineUrl, blobUrl);

// 4. Use any API
const result = await bzbsService.campaignApi.campaigns({
  config: 'campaign_buzzebeesdemo',
  byConfig: true,
  skip: 0,
  top: 10,
});

if (result.type === 'success') {
  console.log(result.model); // Campaign[]
}

API Version

This library targets Buzzebees API v2. Key differences from v1:

  • All POST request bodies use JSON (application/json) — no more application/x-www-form-urlencoded
  • Profile image upload uses multipart/form-data via the dedicated updateProfileImage() method
  • Flat endpoint paths replace REST-style path parameters (e.g. campaign/detail?campaignId=123 replaces campaign/123)
  • profile/me/ prefix removed — the auth token identifies the user (e.g. profile/info replaces profile/me)
  • Address lookups moved from main/ to address/ prefix

Configuration

Constructor

new BzbsService(client: AxiosInstance, baseUrl: string, baseLineUrl: string, baseBlobUrl: string)

| Parameter | Type | Description | |---|---|---| | client | AxiosInstance | Pre-configured Axios instance with headers/interceptors | | baseUrl | string | Buzzebees API base URL | | baseLineUrl | string | LINE API base URL (pass "" to skip LINE API initialization) | | baseBlobUrl | string | Blob storage base URL |

Setting Headers

Configure your Axios instance with required headers before creating BzbsService:

const axiosClient = axios.create({});

// Set default headers
axiosClient.defaults.headers.common = {
  'Content-Type': 'application/json, multipart/form-data',
  'App-Id': '<your-app-id>',
  'Ocp-Apim-Subscription-Key': '<your-subscription-key>',
};

// Add auth token via interceptor
axiosClient.interceptors.request.use((config) => {
  const token = getStoredToken(); // your token retrieval logic
  if (token) {
    config.headers.Authorization = token;
  }
  return config;
});

Dynamic URL Updates

bzbsService.setBaseUrl('https://new-api.buzzebees.com/api/');
bzbsService.setBlobUrl('https://new-blob.buzzebees.com/');
bzbsService.setLineUrl('https://api.line.me/');

Architecture

Consumer Code
     │
     ▼
BzbsService (entry point)
 ├── AuthenticateApi     → auth/
 ├── BadgeApi            → profile/me/badges
 ├── CampaignApi         → campaign/
 ├── CartApi             → cart/
 ├── CategoryApi         → category/
 ├── ConsentApi          → consent/
 ├── CouponApi           → coupon/
 ├── DashboardApi        → dashboard/config
 ├── HistoryApi          → redeem/
 ├── LineApi             → LINE OAuth (optional)
 ├── NotificationApi     → notification/
 ├── PlaceApi            → place/
 ├── PointLogApi         → log/points
 ├── ProfileApi          → profile/
 ├── RegistrationApi     → auth/register
 ├── AddressApi          → profile/address, address/
 ├── StampApi            → stamp/
 ├── RequestHelpApi      → buzz/, profile/me/help
 ├── SettingApi          → setting/add
 └── Blob                → blob storage
          │
          ▼
     BaseService          ← Abstract HTTP layer
          │
          ▼
     AxiosInstance        ← Consumer-injected, fully configurable

All API classes extend BaseService, which provides:

  • HTTP methods: get, post, put, delete, patch
  • Automatic response normalization (handles both { Success, Data } and { success, data } formats)
  • Error handling with typed ServiceResponse<T>
  • URL construction utilities
  • FormData creation utility

Directory Structure

src/
├── api/
│   ├── base-service.ts          # Abstract base with HTTP methods
│   ├── bzbs-service.ts          # Main service aggregator
│   ├── address/address-api.ts
│   ├── auth/auth-api.ts
│   ├── badge/badge-api.ts
│   ├── blob/blob.ts
│   ├── campaign/campaign-api.ts
│   ├── cart/cart-api.ts
│   ├── category/category-api.ts
│   ├── consent/consent-api.ts
│   ├── coupon/coupon-api.ts
│   ├── dashboard/dashboard-api.ts
│   ├── history/history-api.ts
│   ├── line/line-api.ts
│   ├── notification/notification-api.ts
│   ├── place/place-api.ts
│   ├── point-log/point-log-api.ts
│   ├── profile/profile-api.ts
│   ├── registration/registration-api.ts
│   ├── request-help/request-help-api.ts
│   ├── setting/setting-api.ts
│   └── stamp/stamp-api.ts
├── models/                      # TypeScript interfaces
└── index.ts                     # Re-exports everything

BzbsService Properties

| Property | Type | Description | |---|---|---| | authApi | AuthenticateApi | Authentication, login, OTP, session management | | badgeApi | BadgeApi | User badges and missions | | campaignApi | CampaignApi | Campaigns, redemption, favorites | | cartApi | CartApi | Shopping cart | | categoryApi | CategoryApi | Campaign categories | | consentApi | ConsentApi | PDPA / privacy consent | | couponApi | CouponApi | Coupon code processing | | dashboardApi | DashboardApi | Dashboard content | | historyApi | HistoryApi | Redemption history, voucher usage | | lineApi | LineApi \| undefined | LINE OAuth (only if baseLineUrl provided) | | notificationApi | NotificationApi | Push notifications | | placeApi | PlaceApi | Locations / stores | | pointLogApi | PointLogApi | Point transaction logs | | profileApi | ProfileApi | User profile, points, account | | registerApi | RegistrationApi | User registration | | addressApi | AddressApi | Addresses, provinces, districts | | stampApi | StampApi | Stamp cards | | forumApi | RequestHelpApi | Help/support forum (Buzz) | | settingApi | SettingApi | Web landing / cart settings | | blob | Blob | Blob storage, maintenance, consent versions |


Response Handling

All API methods return Promise<ServiceResponse<T>>, a discriminated union:

type ServiceResponse<T> = SuccessResponse<T> | ErrorResponse;

type SuccessResponse<T> = {
  type: 'success';
  model: T;              // The typed response data
  response: AxiosResponse;
};

type ErrorResponse = ClientError | ServerError;

type ServerError = {
  type: 'server-error';
  error: BzbsErrorResponse;  // { requestId, error: { id, message, code, type } }
  statusCode: number;
  response: AxiosResponse;
};

type ClientError = {
  type: 'client-error';
  message: string;
  details?: any;
};

Usage Pattern

const result = await bzbsService.campaignApi.campaigns({ config: 'main' });

switch (result.type) {
  case 'success':
    console.log(result.model); // Campaign[]
    break;

  case 'server-error':
    console.error(result.error.error?.message);
    console.error('Status:', result.statusCode);
    break;

  case 'client-error':
    console.error(result.message);
    break;
}

Response Normalization

The library automatically handles both uppercase and lowercase API response formats:

  • { Success: true, Data: ... } and { success: true, data: ... } are both supported
  • HTTP 204 responses return an empty object as the model

Custom Request Headers

Pass RequestOptions as the last argument to any API method:

type RequestOptions = {
  headers?: { [key: string]: string };
  params?: { [key: string]: string };
  data?: any;
  baseUrl?: string;
};

const response = await bzbsService.profileApi.profile(undefined, {
  headers: { 'Accept-Language': 'th' },
});

Complete API Endpoint Table

All endpoints are relative to baseUrl (constructor param), except LineApi (uses baseLineUrl) and Blob (uses baseBlobUrl).

Feature Tags: #auth #campaign #cart #category #consent #coupon #dashboard #history #line #notification #place #points #profile #registration #address #stamp #forum #setting #blob

| Service | Method | HTTP | Endpoint | Key Parameters | Return Model | Tags | |---|---|---|---|---|---|---| | authApi | deviceLogin | POST | auth/device_login | appId, uuid, deviceLocale, os, platform, deviceToken, macAddress; opt: otp, refcode, contact_number | LoginResponse | #auth | | authApi | facebookLogin | POST | auth/login | accessToken, appId, uuid, deviceLocale, os, platform, deviceToken, macAddress | LoginResponse | #auth | | authApi | googleLogin | POST | auth/google_login | idToken, appId, uuid, deviceLocale, os, platform, deviceToken, macAddress | LoginResponse | #auth | | authApi | lineLogin | POST | auth/line_login | idToken, lineAccessToken, authorizationCode, appId, uuid, os, platform, deviceToken, macAddress | LoginResponse | #auth #line | | authApi | appleLogin | POST | auth/apple_login | idToken, refreshToken, appId, uuid, os, platform, deviceToken, macAddress | LoginResponse | #auth | | authApi | appleToken | POST | auth/apple_token | authorizationCode, idToken, appId, os, platform, macAddress, clientVersion | AppleToken | #auth | | authApi | usernamePasswordLogin | POST | auth/bzbs_login | username, password, appId, uuid, deviceLocale, os, platform, deviceToken, macAddress | LoginResponse | #auth | | authApi | connectLine | POST | auth/line_login | idToken, lineAccessToken, authorizationCode, appId, uuid, os, platform, deviceToken, macAddress | LoginResponse | #auth #line | | authApi | connectFacebook | POST | auth/login | accessToken, appId, uuid, os, platform, deviceToken, macAddress | LoginResponse | #auth | | authApi | connectGoogle | POST | auth/google_login | idToken, appId, uuid, os, platform, deviceToken, macAddress | LoginResponse | #auth | | authApi | connectApple | POST | auth/apple_login | idToken, refreshToken, appId, uuid, os, platform, deviceToken, macAddress | LoginResponse | #auth | | authApi | logout | POST | auth/logout | uuid | unknown | #auth | | authApi | forgetPassword | GET | profile/forget_password | contact (as id param), type (email|contact_number|email_otp) | ForgetPasswordResponse | #auth #profile | | authApi | resetPassword | POST | profile/forget_password | contact (as id), refCode, newPassword; opt: otp | StatusResponse | #auth #profile | | authApi | otp | GET | auth/otp | uuid, appId, contactNumber; opt: channel | OtpResponse | #auth | | authApi | otpV2 | POST | auth/otp | appId, contactNumber; opt: channel | OtpResponse | #auth | | authApi | otpEmail | GET | auth/otp_email | uuid, appId, email; opt: channel | OtpResponse | #auth | | authApi | confirmOtp | POST | auth/bzbs_authen | otp, refCode, contactNumber | ConfirmOtpResponse | #auth | | authApi | validateOtp | POST | auth/validate_otp | appId, otp, refCode, type; opt: contactNumber, email, use, channel | ValidateOtpResponse | #auth | | authApi | resume | POST | auth/device_resume | uuid, deviceAppId, os, platform, macAddress, deviceNotificationEnabled, clientVersion, deviceToken | ResumeResponse | #auth | | authApi | updateDevice | POST | auth/update_device | uuid, deviceAppId, os, platform, macAddress, deviceNotificationEnabled, clientVersion, deviceToken | ResumeResponse | #auth | | authApi | version | GET | auth/version | clientVersion | Version | #auth | | authApi | versionRaw | GET | auth/version | clientVersion | any | #auth | | badgeApi | badges | GET | profile/me/badges | opt: badgeId | Badge[] | #profile | | campaignApi | campaigns | GET | campaign/list | config; opt: cat, byConfig, skip, top, locale, keyword, startDate, sponsorId, maxPoints, minPoints, sortBy, center, hashTags, locationAgencyId | Campaign[] | #campaign | | campaignApi | favoriteCampaigns | GET | profile/favourite_campaign | opt: skip, top, locale | Campaign[] | #campaign #profile | | campaignApi | campaignDetails | GET | campaign/detail | id (as campaignId); opt: deviceLocale | CampaignDetail | #campaign | | campaignApi | addToFavorite | POST | campaign/favourite | id (as body id, favourite: true) | FavoriteResponse | #campaign | | campaignApi | removeFromFavorite | DELETE | campaign/favourite | id (as query param) | FavoriteResponse | #campaign | | campaignApi | redeem | POST | campaign/redeem | id (as campaignid); opt: addressKey, contactNumber, pointUnit, spPoints | RedeemResponse | #campaign #points | | campaignApi | bulkRedeem | POST | campaign/{id}/bulkredeem | id, quantity; opt: addressKey, contactNumber, pointUnit, spPoints | RedeemResponse | #campaign #points | | cartApi | addCart | POST | cart/{id}/add | id; opt: mode, qty, sideCampaignJson | CartCountResponse | #cart #campaign | | cartApi | cartCount | GET | cart/count | opt: options | CartCountResponse | #cart | | cartApi | cartAccess | POST | setting/add | errorUrl, successUrl, returnUrl, appId, appName | CartAccessResponse | #cart #setting | | categoryApi | categories | GET | category/menu | config; opt: byConfig | Category[] | #category #campaign | | consentApi | consent | GET | consent/status | opt: options | Consent | #consent | | consentApi | updateConsent | POST | consent/consent | opt: termsAndConditions, dataPrivacy, marketingOption, consentAge, email, sms, notification, line, analyticsBuzzebeesCookies, analyticsFirebaseCookies, analyticsGoogleCookies, analyticsMetaCookies, analyticsOtherCookies, functionalCookies, marketingCookies, necessaryCookies | Consent | #consent | | consentApi | unconsent | POST | consent/unconsent | opt: options | unknown | #consent | | couponApi | processCodes | POST | coupon/process | codes (string or string[], sent as JSON array) | CouponResponse | #coupon #campaign | | dashboardApi | mainDashboard | GET | dashboard/config | appName (as config), locale | Dashboard[] | #dashboard | | dashboardApi | subDashboard | GET | dashboard/config | dashboardName (as config), locale | Dashboard[] | #dashboard | | historyApi | redeemHistories | GET | redeem/list | byConfig, config, skip, top; opt: locale, startDate, endDate | Purchase[] | #history #campaign | | historyApi | use | POST | redeem/use | redeemKey (as redeemkey in body) | UseCampaignResponse | #history #campaign | | lineApi | lineAuth | POST | oauth2/v2.1/token (baseLineUrl) | grantType, code, clientId, clientSecret, redirectUrl | LineAuthResponse | #line #auth | | notificationApi | notifications | GET | notification/list | mode (new|all), sortBy (createdate_desc|createdate_asc); opt: top, skip | Notification[] | #notification | | notificationApi | read | POST | notification/read | ids (comma-separated, sent as JSON body) | unknown | #notification | | placeApi | placeList | GET | place | agencyId, center, distance, top; opt: provinceCode, category, mode, requiredCampaign, keyword, isFavourite | Place[] | #place | | placeApi | place | GET | place/{id} | id, agencyId; opt: requiredCampaign, isFavourite | Place | #place | | placeApi | addToFavourite | POST | place/{id}/favourite | id | unknown | #place | | placeApi | removeFromFavourite | POST | place/{id}/unfavourite | id | unknown | #place | | pointLogApi | getPointLog | GET | log/points | month; opt: type, lastRowKey, top | PointLog[] | #points #profile | | profileApi | profile | GET | profile/info | opt: options | ProfileResponse | #profile | | profileApi | updateProfile | POST | profile/info | opt: firstName, lastName, contactNumber, email, notification, locale, title, gender, birthDate, address, subdistrictCode, districtCode, provinceCode, countryCode, zipCode, idCard, passport, maritalStatus, displayName, latitude, longitude, income, interests, region, occupation, remark, ... (JSON body) | ProfileResponse | #profile | | profileApi | updateProfileImage | POST | profile/picture | image (File or {uri, name, type}, sent as multipart/form-data with key data) | ProfileResponse | #profile | | profileApi | changePassword | POST | profile/change_password | current, change | StatusResponse | #profile #auth | | profileApi | updateShipping | POST | profile/shipping | opt: shippingFirstName, shippingLastName, shippingProvinceCode, shippingDistrictCode, shippingSubDistrictCode, shippingZipCode, shippingAddress, shippingContactNumber, ... | unknown | #profile #address | | profileApi | changeContactNumber | POST | auth/change_authen | contactNumber, otp, refCode; opt: idCard | ConfirmOtpResponse | #profile #auth | | profileApi | changeContactNumberV2 | POST | profile/contact_number | contactNumber, otp, refCode | any | #profile #auth | | profileApi | changeContactNumberV3 | POST | profile/contact_number | userId (as userid in body), contactNumber, otp, refCode | any | #profile #auth | | profileApi | points | GET | profile/updated_points | opt: options | UpdatedPoints | #profile #points | | profileApi | expiringPoints | GET | profile/allexpiring_points | opt: options | ExpiringPoints | #profile #points | | profileApi | deactivate | POST | profile/deactivate | opt: options | unknown | #profile | | registerApi | validateRegister | POST | auth/validate_register | appId, username, email, contactNumber | OtpResponse | #registration #auth | | registerApi | register | POST | auth/register | appId, uuid, macAddress, os, platform, clientVersion, deviceNotificationEnable, username, password, confirmPassword, firstName, lastName, contactNumber, otp, refCode, options; opt: address, gender, birthdate, email, refUserCode, termAndConditionVersion, dataPrivacyVersion, marketingOptionsVersion, consentAge, emailMarketing, smsMarketing, notificationMarketing, lineMarketing, phoneMarketing | RegistrationResponse | #registration #auth | | addressApi | zipCodes | GET | address/postcode | opt: zipCode | ZipCode[] | #address | | addressApi | provinces | GET | address/province | opt: options | Province[] | #address | | addressApi | districts | GET | address/district | opt: provinceCode | District[] | #address | | addressApi | subDistricts | GET | address/subdistrict | opt: provinceCode, districtCode | SubDistrict[] | #address | | addressApi | userAddresses | GET | profile/addresses | opt: options | Address[] | #address #profile | | addressApi | updateAddress | POST | profile/address | opt: name, addressName, firstName, lastName, address, zipcode, provinceCode, provinceName, districtCode, districtName, subDistrictCode, subDistrictName, contactNumber, countryCode, countryName, latitude, longitude, landmark, isDefault, rowKey | Address | #address #profile | | addressApi | deleteAddress | DELETE | profile/address | opt: rowKey | unknown | #address #profile | | addressApi | userTaxAddresses | GET | profile/taxes | opt: options | Address[] | #address #profile | | addressApi | updateTaxAddress | POST | profile/tax | opt: rowKey, taxId, isDefault, personType, title, name, firstName, lastName, email, contactNumber, brnachId, branchName, companyName, address, addressName, floor, building, moo, road, room, soi, village, districtCode, provinceName, subDistrictCode, zipcode | Address | #address #profile | | addressApi | deleteTaxAddress | DELETE | profile/tax | opt: rowKey | unknown | #address #profile | | stampApi | createStamp | POST | stamp/create | opt: imei, issuer, os, platform | CreateStampResponse | #stamp | | stampApi | stamps | GET | stamp | options | Stamp[] | #stamp | | stampApi | stampProfile | GET | stamp/{id}/profile | id, cardId | StampProfileResponse | #stamp | | forumApi | helpCode | POST | profile/me/help | os, platform, clientVersion | RequestHelpCode | #forum #profile | | forumApi | requestHelpList | GET | buzz/{requestId}/list | requestId | ChatMessage[] | #forum | | forumApi | requestDetail | GET | buzz/{buzzKey} | buzzKey | ChatMessage | #forum | | forumApi | postRequestHelp | POST | buzz/{requestId}/buzz | requestId, message; opt: image (File) | ChatMessage | #forum | | forumApi | comments | GET | buzz/{buzzKey}/comments | buzzKey; opt: lastRowKey | ChatMessage[] | #forum | | forumApi | postComment | POST | buzz/{buzzKey}/comments | buzzKey, message; opt: image (File) | ChatMessage | #forum | | forumApi | like | POST | buzz/{buzzKey}/like | buzzKey | LikeForumResponse | #forum | | forumApi | unlike | DELETE | buzz/{buzzKey}/like | buzzKey | LikeForumResponse | #forum | | settingApi | accessKey | POST | setting/add | data (JSON: app_id, campaign_id, locale, return_url, version; opt: redeem_key) | AccessTokenResponse | #setting #campaign | | blob | consentVersion | GET | pdpaconsent/{appId}/version (baseBlobUrl) | appId | ConsentVersion | #blob #consent | | blob | maintenance | GET | config/maintenance/{appId}.json (baseBlobUrl) | appId | Maintenance | #blob | | blob | blob | GET | {path} (baseBlobUrl) | path | unknown | #blob |


API Reference

Every method accepts an optional requestOptions as the last argument for custom headers or query params.


AuthenticateApi

bzbsService.authApi — Authentication, login providers, OTP, session management.

| Method | Description | Returns | |---|---|---| | deviceLogin(params) | Login with device UUID | LoginResponse | | facebookLogin(params) | Login with Facebook access token | LoginResponse | | googleLogin(params) | Login with Google ID token | LoginResponse | | lineLogin(params) | Login with LINE credentials | LoginResponse | | appleLogin(params) | Login with Apple ID token + refresh token | LoginResponse | | appleToken(params) | Request Apple refresh token | AppleToken | | usernamePasswordLogin(params) | Login with username/password | LoginResponse | | connectLine(params) | Connect/link LINE to existing account | LoginResponse | | connectFacebook(params) | Connect/link Facebook to existing account | LoginResponse | | connectGoogle(params) | Connect/link Google to existing account | LoginResponse | | connectApple(params) | Connect/link Apple to existing account | LoginResponse | | logout(params) | Logout user | unknown | | forgetPassword(params) | Send forget password request | ForgetPasswordResponse | | resetPassword(params) | Reset user password with OTP | StatusResponse | | otp(params) | Request OTP (GET) | OtpResponse | | otpV2(params) | Request OTP (POST) | OtpResponse | | otpEmail(params) | Request OTP via email | OtpResponse | | confirmOtp(params) | Confirm OTP for authentication | ConfirmOtpResponse | | validateOtp(params) | Validate OTP (generic) | ValidateOtpResponse | | resume(params) | Resume/refresh session | ResumeResponse | | updateDevice(params) | Update device push token | ResumeResponse | | version(clientVersion) | Get app version info | Version | | versionRaw(clientVersion) | Get raw version info | any |

Examples

// Device login
const result = await bzbsService.authApi.deviceLogin({
  appId: 'your-app-id',
  uuid: 'device-uuid',
  deviceLocale: 'en',
  os: 'ios 17.0',
  platform: 'iPhone',
  deviceNotificationEnabled: true,
  clientVersion: 'ios_myapp1.0.0',
  deviceToken: 'fcm-token',
  macAddress: 'device-mac-address',
});

// OTP flow
const otpResult = await bzbsService.authApi.otpV2({
  appId: 'your-app-id',
  contactNumber: '0812345678',
});

if (otpResult.type === 'success') {
  const validated = await bzbsService.authApi.validateOtp({
    appId: 'your-app-id',
    otp: '123456',
    refCode: otpResult.model.refcode,
    type: 'contact_number',
    contactNumber: '0812345678',
  });
}

CampaignApi

bzbsService.campaignApi — Campaign listing, details, redemption, and favorites.

| Method | Description | Returns | |---|---|---| | campaigns(params) | List campaigns with filtering/sorting | Campaign[] | | favoriteCampaigns(params) | List user's favorite campaigns | Campaign[] | | campaignDetails(params) | Get campaign details by ID | CampaignDetail | | addToFavorite(id) | Add campaign to favorites | FavoriteResponse | | removeFromFavorite(params) | Remove campaign from favorites | FavoriteResponse | | redeem(params) | Redeem a campaign | RedeemResponse | | bulkRedeem(params) | Redeem a campaign in bulk | RedeemResponse |

Campaign List Parameters

| Param | Type | Required | Description | |---|---|---|---| | config | string | Yes | Campaign list configuration name | | cat | string | No | Category filter | | byConfig | boolean | No | Filter by configuration | | skip | number | No | Pagination offset | | top | number | No | Number of items to retrieve | | keyword | string | No | Search keyword | | sortBy | string | No | Sort order | | center | string | No | Geo coordinates (lat,lng) for location-based search | | hashTags | string | No | Filter by hashtags | | sponsorId | string | No | Sponsor filter | | minPoints | string | No | Minimum points filter | | maxPoints | string | No | Maximum points filter |

// List campaigns
const campaigns = await bzbsService.campaignApi.campaigns({
  config: 'campaign_buzzebeesdemo',
  byConfig: true,
  skip: 0,
  top: 20,
  keyword: 'coffee',
});

// Redeem a campaign
const redeem = await bzbsService.campaignApi.redeem({
  id: '12345',
  contactNumber: '0812345678',
});

ProfileApi

bzbsService.profileApi — User profile management, points, password, contact number.

| Method | Description | Returns | |---|---|---| | profile() | Get current user profile | ProfileResponse | | updateProfile(params) | Update user profile fields (JSON body) | ProfileResponse | | updateProfileImage(params) | Upload profile picture (multipart/form-data) | ProfileResponse | | changePassword(params) | Change user password | StatusResponse | | updateShipping(params) | Update shipping information | unknown | | changeContactNumber(params) | Change contact number (v1) | ConfirmOtpResponse | | changeContactNumberV2(params) | Change contact number (v2) | any | | changeContactNumberV3(params) | Change contact number by user ID (v3) | any | | points() | Get user's current points | UpdatedPoints | | expiringPoints() | Get user's expiring points | ExpiringPoints | | deactivate() | Deactivate user account | unknown |

// Update profile fields (JSON)
const result = await bzbsService.profileApi.updateProfile({
  firstName: 'John',
  lastName: 'Doe',
  email: '[email protected]',
  contactNumber: '0812345678',
  gender: 'male',
  birthDate: 946684800, // Unix timestamp in seconds
});

// Upload profile picture (multipart/form-data, field key: "data")
await bzbsService.profileApi.updateProfileImage({
  image: imageFile, // File | { uri: string; name: string; type: string }
});

CartApi

bzbsService.cartApi — Shopping cart management.

| Method | Description | Returns | |---|---|---| | addCart(params) | Add item to cart | CartCountResponse | | cartCount() | Get cart item count | CartCountResponse | | cartAccess(params) | Get cart access token for web landing | CartAccessResponse |

await bzbsService.cartApi.addCart({ id: 'campaign-123', qty: 2 });
const count = await bzbsService.cartApi.cartCount();

CategoryApi

bzbsService.categoryApi — Campaign categories.

| Method | Description | Returns | |---|---|---| | categories(params) | Get campaign categories | Category[] |

const categories = await bzbsService.categoryApi.categories({
  config: 'campaign_buzzebeesdemo',
  byConfig: true,
});

CouponApi

bzbsService.couponApi — Coupon code processing.

| Method | Description | Returns | |---|---|---| | processCodes(params) | Process one or more coupon codes | CouponResponse |

const result = await bzbsService.couponApi.processCodes({
  codes: 'ABCD-1234-EFGH',
});

NotificationApi

bzbsService.notificationApi — Push notification management.

| Method | Description | Returns | |---|---|---| | notifications(params) | Get notifications list | Notification[] | | read(params) | Mark notifications as read | unknown |

const notifs = await bzbsService.notificationApi.notifications({
  mode: 'new',               // 'new' | 'all'
  sortBy: 'createdate_desc',
  top: 20,
  skip: 0,
});

await bzbsService.notificationApi.read({ ids: 'rowKey1,rowKey2' });

HistoryApi

bzbsService.historyApi — Redemption history and voucher usage.

| Method | Description | Returns | |---|---|---| | redeemHistories(params) | Get redeem history | Purchase[] | | use(params) | Mark a redeemed item as used | UseCampaignResponse |

const history = await bzbsService.historyApi.redeemHistories({
  byConfig: true,
  config: 'campaign_buzzebeesdemo',
  skip: 0,
  top: 20,
});

await bzbsService.historyApi.use({ redeemKey: 'ABC123_1' });

RegistrationApi

bzbsService.registerApi — New user registration with OTP verification.

| Method | Description | Returns | |---|---|---| | validateRegister(params) | Validate registration and trigger OTP | OtpResponse | | register(params) | Register a new user | RegistrationResponse |

Validation Error Codes:

  • 2078 — Duplicate contact number
  • 2089 — Duplicate email
  • 401 — Duplicate username
// Step 1: Validate
const validation = await bzbsService.registerApi.validateRegister({
  appId: 'your-app-id',
  username: 'johndoe',
  email: '[email protected]',
  contactNumber: '0812345678',
});

// Step 2: Register (after OTP verification)
const registration = await bzbsService.registerApi.register({
  appId: 'your-app-id',
  uuid: 'device-uuid',
  macAddress: 'mac-address',
  os: 'ios 17.0',
  platform: 'iPhone',
  clientVersion: 'ios_myapp1.0.0',
  deviceNotificationEnable: true,
  username: 'johndoe',
  password: 'securepass',
  confirmPassword: 'securepass',
  firstName: 'John',
  lastName: 'Doe',
  contactNumber: '0812345678',
  otp: '123456',
  refCode: 'ABC123',
  options: {},
});

AddressApi

bzbsService.addressApi — User addresses and Thailand geographical data.

| Method | Description | Returns | |---|---|---| | zipCodes(params) | Look up zip code information | ZipCode[] | | provinces() | Get Thailand provinces | Province[] | | districts(params) | Get districts by province | District[] | | subDistricts(params) | Get sub-districts by province/district | SubDistrict[] | | userAddresses() | Get user's saved addresses | Address[] | | updateAddress(params) | Create or update a delivery address | Address | | deleteAddress(params) | Delete an address | unknown | | userTaxAddresses() | Get user's tax addresses | Address[] | | updateTaxAddress(params) | Create or update a tax address | Address | | deleteTaxAddress(params) | Delete a tax address | unknown |

const provinces = await bzbsService.addressApi.provinces();

const districts = await bzbsService.addressApi.districts({
  provinceCode: '10',
});

await bzbsService.addressApi.updateAddress({
  firstName: 'John',
  lastName: 'Doe',
  address: '123 Main St',
  provinceCode: '10',
  provinceName: 'Bangkok',
  districtCode: '1001',
  districtName: 'Phra Nakhon',
  zipcode: '10200',
  contactNumber: '0812345678',
  isDefault: true,
});

BadgeApi

bzbsService.badgeApi — User badges and mission progress.

| Method | Description | Returns | |---|---|---| | badges(params) | Get user badges (opt: filter by badgeId) | Badge[] |

const badges = await bzbsService.badgeApi.badges({});
const badge = await bzbsService.badgeApi.badges({ badgeId: '123' });

ConsentApi

bzbsService.consentApi — PDPA and marketing consent management.

v2 change: consent() now calls consent/status; updateConsent() now calls consent/consent.

| Method | Description | Returns | |---|---|---| | consent() | Get user's consent status | Consent | | updateConsent(params) | Update consent preferences | Consent | | unconsent() | Withdraw all consent | unknown |

consentAge accepts one of:

  • '0' — user has not consented to age verification
  • '1' — user has consented (age confirmed)
  • The user's actual age as a string (e.g. '25')
await bzbsService.consentApi.updateConsent({
  termsAndConditions: '1.0',
  dataPrivacy: '1.0',
  marketingOption: '1.0',
  consentAge: '25',  // '0' | '1' | actual age string
  email: '1',        // '0' or '1'
  sms: '1',
  notification: '1',
  line: '0',
});

DashboardApi

bzbsService.dashboardApi — Dashboard content configuration.

v2 change: Both mainDashboard and subDashboard now call dashboard/config. The appName/dashboardName param is sent as config.

| Method | Description | Returns | |---|---|---| | mainDashboard(params) | Get main dashboard data | Dashboard[] | | subDashboard(params) | Get sub-dashboard data | Dashboard[] |

const dashboard = await bzbsService.dashboardApi.mainDashboard({
  appName: 'buzzebeesdemo', // sent as `config` query param
  locale: 1054,
});

const sub = await bzbsService.dashboardApi.subDashboard({
  dashboardName: 'featured', // sent as `config` query param
  locale: 1054,
});

LineApi

bzbsService.lineApi — LINE OAuth token exchange. Only initialized when baseLineUrl is provided. Uses baseLineUrl as the base URL.

| Method | Description | Returns | |---|---|---| | lineAuth(params) | Authenticate with LINE OAuth | LineAuthResponse |

if (bzbsService.lineApi) {
  const lineAuth = await bzbsService.lineApi.lineAuth({
    grantType: 'authorization_code',
    code: 'auth-code-from-line',
    clientId: 'line-channel-id',
    clientSecret: 'line-channel-secret',
    redirectUrl: 'https://myapp.com/callback',
  });
}

PlaceApi

bzbsService.placeApi — Location/store management with geo-search.

| Method | Description | Returns | |---|---|---| | placeList(params) | List places with location search | Place[] | | place(params) | Get place details | Place | | addToFavourite(params) | Add place to favorites | unknown | | removeFromFavourite(params) | Remove place from favorites | unknown |

const places = await bzbsService.placeApi.placeList({
  agencyId: '123',
  center: '13.7563,100.5018', // lat,lng
  distance: 5000,
  top: 20,
  keyword: 'cafe',
});

PointLogApi

bzbsService.pointLogApi — Point transaction history.

| Method | Description | Returns | |---|---|---| | getPointLog(params) | Get point transaction log by month | PointLog[] |

const logs = await bzbsService.pointLogApi.getPointLog({
  month: '2025-01',
  type: 'earn',
  top: 50,
});

StampApi

bzbsService.stampApi — Stamp card system.

| Method | Description | Returns | |---|---|---| | createStamp(params) | Create a new stamp | CreateStampResponse | | stamps(options) | List all stamps | Stamp[] | | stampProfile(params) | Get stamp card profile/details | StampProfileResponse |

const stamps = await bzbsService.stampApi.stamps({});

const profile = await bzbsService.stampApi.stampProfile({
  id: 'stamp-123',
  cardId: 'card-456',
});

RequestHelpApi (Forum)

bzbsService.forumApi — Help/support forum (Buzz chat system).

| Method | Description | Returns | |---|---|---| | helpCode(params) | Get help request code | RequestHelpCode | | requestHelpList(params) | List messages in a help request | ChatMessage[] | | requestDetail(params) | Get a specific message | ChatMessage | | postRequestHelp(params) | Post a help message (supports image) | ChatMessage | | comments(params) | Get comments on a post | ChatMessage[] | | postComment(params) | Post a comment (supports image) | ChatMessage | | like(params) | Like a post | LikeForumResponse | | unlike(params) | Unlike a post | LikeForumResponse |

const helpCode = await bzbsService.forumApi.helpCode({
  os: 'ios 17.0',
  platform: 'iPhone',
  clientVersion: 'ios_myapp1.0.0',
});

await bzbsService.forumApi.postRequestHelp({
  requestId: 'req-123',
  message: 'I need help with my order',
  image: imageFile, // optional File
});

SettingApi

bzbsService.settingApi — Web landing page access tokens.

v2 change: Endpoint changed from setting to setting/add.

| Method | Description | Returns | |---|---|---| | accessKey(params) | Get access key for web landing pages | AccessTokenResponse |

const accessKey = await bzbsService.settingApi.accessKey({
  data: JSON.stringify({
    app_id: 'your-app-id',
    campaign_id: 12345,
    locale: 1054,
    return_url: 'myapp://callback',
    version: '2',
  }),
});

Blob

bzbsService.blob — Blob storage retrieval. Uses baseBlobUrl as base URL.

| Method | Description | Returns | |---|---|---| | consentVersion(appId) | Get PDPA consent document version | ConsentVersion | | maintenance(appId) | Get app maintenance configuration | Maintenance | | blob(path) | Fetch any blob storage path | unknown |

const consentVersion = await bzbsService.blob.consentVersion('your-app-id');
const maintenance = await bzbsService.blob.maintenance('your-app-id');

Models Reference

All TypeScript interfaces are exported from @bzbs/react-api-client:

import {
  Campaign,
  CampaignDetail,
  ProfileResponse,
  LoginResponse,
  Purchase,
  // ... etc
} from '@bzbs/react-api-client';

Authentication Models

| Model | Key Fields | |---|---| | LoginResponse | Token, UserId, UserCode, Username, Points, Consent fields, ProfileImage, Locale | | ResumeResponse | Same structure as LoginResponse | | AppleToken | refresh_token, id_token | | LineAuthResponse | access_token, token_type, refresh_token, expires_in, scope, id_token | | OtpResponse | refcode, channel, expiredate, expireinseconds | | ConfirmOtpResponse | status, token | | ValidateOtpResponse | validatecode | | ForgetPasswordResponse | status, refcode, expiredate, expireinseconds | | RegistrationResponse | Registration result with Buzzebees user account | | Version | allow_use, has_new_version, welcome_page_times |

Campaign Models

| Model | Key Fields | |---|---| | Campaign | ID, Name, Points, StartDate, EndDate, CategoryId, ImageUrl, Quantity, IsLike | | CampaignDetail | All Campaign fields + images (Picture[]), SubCampaigns, conditions, terms | | Picture | ID, Type, Sequence, ImageUrl | | SubCampaign | ID, Name, styles (SubCampaignStyle[]), quantity, points | | RedeemResponse | RedeemKey, PrivilegeMessageEN, PrivilegeMessageTH, UpdatedPoints, ExpiryDate | | UseCampaignResponse | PrivilegeMessageEN, PrivilegeMessageTH, redeemKey, points | | FavoriteResponse | totalLike, isLike | | CouponResponse | success/error results per code | | Purchase | RedeemKey, CampaignName, ExpiryDate, Status, Points, barcode, images |

Cart Models

| Model | Key Fields | |---|---| | CartCountResponse | cart_count | | CartAccessResponse | success, access key |

Profile & Points Models

| Model | Key Fields | |---|---| | ProfileResponse | UserId, Name, FirstName, LastName, Email, Contact_Number, address fields, TermAndCondition, DataPrivacy, MarketingOption, ConsentAge (0=not consented, 1=consented, or actual age), EmailMarketing, SMSMarketing, NotificationMarketing, LineMarketing, Token, Jwt, updated_points, Info1–Info10 (60+ fields) | | UpdatedPoints | points, time | | ExpiringPoints | expiringPoints, expiryDate | | Badge | badgeId, name, description, imageUrl, missions (Mission[]) | | Mission | missionId, name, current, target, isCompleted | | PointLog | UserId, Info, Detail, Points, Type, Timestamp |

Address & Location Models

| Model | Key Fields | |---|---| | Address | rowKey, name, firstName, lastName, address, zipcode, province/district/subdistrict codes and names, contactNumber, isDefault, taxId | | Province | province_code, province_name_th, province_name_en | | District | district_code, district_name_th, district_name_en, province_code | | SubDistrict | subdistrict_code, subdistrict_name_th, zip_code | | ZipCode | Hierarchical address with zone info | | Place | id, name, latitude, longitude, address, workingHours, services, isFavorite |

Consent & Settings Models

| Model | Key Fields | |---|---| | Consent | TermAndCondition, DataPrivacy, MarketingOption, SMSMarketing, NotificationMarketing, LineMarketing, cookie consent flags | | ConsentVersion | version values per consent type | | Version | allow_use, has_new_version, welcome_page_times | | Maintenance | isUnderMaintenance, message, startDate, endDate |

Stamp & Dashboard Models

| Model | Key Fields | |---|---| | Stamp | stampId, cardId, count, maxCount, rewards, expiry | | StampProfileResponse | stamp card profile with history | | CreateStampResponse | result of stamp creation | | Dashboard | id, name, menuItems, images, startDate, endDate | | Category | id, name (TH/EN), subcategories, imageUrl |

Notification & Forum Models

| Model | Key Fields | |---|---| | Notification | notiId, title, message, objectType, imageUrl, expireDate, isRead | | ChatMessage | buzzKey, message, images, sender info, likes, comments count, createdDate (65+ fields) | | LikeForumResponse | likeCount, isLiked | | RequestHelpCode | helpCode |

Error & Response Models

| Model | Key Fields | |---|---| | BzbsErrorResponse | requestId, error: { id, message, code, type } | | StatusResponse | status | | AccessTokenResponse | token key |

Common Error Codes:

| Code | Description | |---|---| | 401 | Unauthorized / Duplicate username | | 2078 | Duplicate contact number | | 2089 | Duplicate email |


BaseService Utilities

createFormData

Static method for building multipart/form-data payloads. Skips undefined, null, and empty string values — preserves 0 and false.

const formData = BaseService.createFormData(
  { name: 'John', age: 0, active: false },
  'profileImage',   // optional file field key
  imageFile         // optional File object
);

setBaseUrl / setLineUrl / setBlobUrl

Update base URLs at runtime (propagates to all sub-services):

bzbsService.setBaseUrl('https://new-api.buzzebees.com/api/');
bzbsService.setLineUrl('https://api.line.me/');
bzbsService.setBlobUrl('https://new-blob.buzzebees.com/');

Testing Guide

Tests are in the tests/ directory, mirroring src/ structure.

Test Utilities (tests/helpers/test-utils.ts)

import {
  createMockClient,
  createSuccessResponse,
  createRawSuccessResponse,
  createServerErrorResponse,
  createAxiosError,
  createDeviceParams,
} from '../helpers/test-utils';

// Create mocked Axios instance
const { client, mockRequest } = createMockClient();

// Mock a wrapped success response: { Success: true, Data: {...} }
mockRequest.mockResolvedValue(createSuccessResponse({ id: '123' }));

// Mock a raw success (no wrapper)
mockRequest.mockResolvedValue(createRawSuccessResponse({ id: '123' }));

// Mock a server error response
mockRequest.mockResolvedValue(createServerErrorResponse());

// Mock a network error (client error)
mockRequest.mockRejectedValue(createAxiosError());

// Standard device parameters (appId, uuid, os, platform, clientVersion, macAddress, deviceToken, ...)
const deviceParams = createDeviceParams();

Test Pattern

import { AuthenticateApi } from '../../src/api/auth/auth-api';
import { createMockClient, createSuccessResponse, createDeviceParams } from '../helpers/test-utils';

describe('AuthenticateApi', () => {
  let api: AuthenticateApi;
  let mockRequest: jest.Mock;

  beforeEach(() => {
    const { client, mockRequest: mock } = createMockClient();
    mockRequest = mock;
    api = new AuthenticateApi(client, 'https://api.buzzebees.com/');
  });

  it('deviceLogin returns success', async () => {
    const data = { Token: 'abc', UserId: '1' };
    mockRequest.mockResolvedValue(createSuccessResponse(data));

    const result = await api.deviceLogin(createDeviceParams());

    expect(result.type).toBe('success');
    if (result.type === 'success') {
      expect(result.model.Token).toBe('abc');
    }
    expect(mockRequest).toHaveBeenCalledWith(
      expect.objectContaining({ url: 'auth/device_login', method: 'post' })
    );
  });

  it('deviceLogin handles server error', async () => {
    mockRequest.mockResolvedValue(createServerErrorResponse());

    const result = await api.deviceLogin(createDeviceParams());

    expect(result.type).toBe('server-error');
  });
});

Run Tests

npm test                        # Watch mode with coverage
npx jest --coverage             # Single run with coverage
npx jest tests/api/auth         # Run specific folder
npx jest --testNamePattern otp  # Run tests matching pattern

Development Commands

# Install dependencies
npm install

# Build (CJS + ESM + type declarations → dist/)
npm run build

# Run tests in watch mode with coverage
npm test

# Lint source files
npm run lint

# Auto-fix lint issues
npm run lint:fix

# Format code with Prettier
npm run format

# Publish (build + version bump + npm publish)
npm run patch   # 1.4.14 → 1.4.15
npm run minor   # 1.4.14 → 1.5.0
npm run major   # 1.4.14 → 2.0.0

Adding a New API

  1. Create src/api/my-feature/my-feature-api.ts:
import { AxiosInstance } from 'axios';
import { BaseService, RequestOptions, ServiceResponse } from '../base-service';
import { MyModel } from '../../models/my-model';

export class MyFeatureApi extends BaseService {
  constructor(client: AxiosInstance, baseUrl: string) {
    super(client, baseUrl);
  }

  public async getItems(
    params: { id: string },
    requestOptions?: RequestOptions
  ): Promise<ServiceResponse<MyModel[]>> {
    return await this.get<MyModel[]>(`my-feature/${params.id}`, {}, requestOptions);
  }
}
  1. Create model interface in src/models/my-model.ts and export from src/models/index.ts
  2. Export from src/api/index.ts
  3. Add to BzbsService constructor and setBaseUrl() method in src/api/bzbs-service.ts

Build Output

| File | Format | Description | |---|---|---| | dist/index.js | CommonJS | For require() usage | | dist/index.mjs | ES Module | For import usage | | dist/index.d.ts | TypeScript | Type declarations | | dist/*.map | Source Maps | For debugging |

Package Exports

{
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts"
}