@bzbs/react-api-client
v2.0.0
Published
React API Client for Buzzebees
Keywords
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
- Quick Start
- API Version
- Configuration
- Architecture
- BzbsService Properties
- Response Handling
- Complete API Endpoint Table
- API Reference
- Models Reference
- BaseService Utilities
- Testing Guide
- Development Commands
- Adding a New API
- Build Output
Installation
npm install @bzbs/react-api-clientPeer dependency: axios
npm install axiosQuick 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 moreapplication/x-www-form-urlencoded - Profile image upload uses
multipart/form-datavia the dedicatedupdateProfileImage()method - Flat endpoint paths replace REST-style path parameters (e.g.
campaign/detail?campaignId=123replacescampaign/123) profile/me/prefix removed — the auth token identifies the user (e.g.profile/inforeplacesprofile/me)- Address lookups moved from
main/toaddress/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 configurableAll 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 everythingBzbsService 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), exceptLineApi(usesbaseLineUrl) andBlob(usesbaseBlobUrl).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 number2089— Duplicate email401— 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 callsconsent/status;updateConsent()now callsconsent/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
mainDashboardandsubDashboardnow calldashboard/config. TheappName/dashboardNameparam is sent asconfig.
| 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
settingtosetting/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 patternDevelopment 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.0Adding a New API
- 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);
}
}- Create model interface in
src/models/my-model.tsand export fromsrc/models/index.ts - Export from
src/api/index.ts - Add to
BzbsServiceconstructor andsetBaseUrl()method insrc/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"
}