blaaiz-nodejs-sdk 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -94,6 +94,23 @@ const customers = await blaaiz.customers.list();
94
94
  console.log('Customers:', customers.data);
95
95
  ```
96
96
 
97
+ You can also pass optional filters and opt-in pagination. Supported filters
98
+ are `email`, `id_number`, `registration_number`, `verification_status`, and
99
+ `type`. Set `paginate: true` to receive a paginated response that includes
100
+ `links` and `meta` (with `current_page`, `total`, etc.) alongside `data`.
101
+
102
+ ```javascript
103
+ const verified = await blaaiz.customers.list({
104
+ email: 'john@example.com',
105
+ verification_status: 'VERIFIED',
106
+ type: 'individual',
107
+ paginate: true
108
+ });
109
+
110
+ console.log('Page:', verified.data.meta.current_page);
111
+ console.log('Customers:', verified.data.data);
112
+ ```
113
+
97
114
  #### Update Customer
98
115
 
99
116
  ```javascript
@@ -269,12 +286,17 @@ const payout = await blaaiz.payouts.initiate({
269
286
  to_currency_id: "NGN",
270
287
  bank_id: "bank-id", // Required for NGN
271
288
  account_number: "0123456789",
272
- phone_number: "+2348012345678" // Optional
289
+ phone_number: "+2348012345678", // Optional
290
+ note: "Acme Ltd" // Optional — appears in the transaction description; defaults to business name
273
291
  });
274
292
 
275
293
  console.log('Payout Status:', payout.data.transaction.status);
276
294
  ```
277
295
 
296
+ #### Passing additional fields
297
+
298
+ `payouts.initiate()` forwards the entire payload verbatim to the API, so any field documented in the [Blaaiz API reference](https://docs.business.blaaiz.com) can be included even if it isn't listed in this README. For example, `note` sets the transaction description (defaulting to the business name when omitted). This means the SDK stays compatible with new API fields without requiring an update here.
299
+
278
300
  #### Bank Transfer Payout (GBP)
279
301
 
280
302
  ```javascript
@@ -674,6 +696,8 @@ The Blaaiz API has a rate limit of 100 requests per minute. The SDK automaticall
674
696
 
675
697
  The SDK provides built-in webhook signature verification to ensure webhook authenticity. The signature is computed using HMAC-SHA256 with the format `timestamp.payload`.
676
698
 
699
+ > **Important:** `payload` must be the **raw request body string** exactly as received. Do not pass a parsed object — parsing and re-serializing (e.g. `JSON.stringify`) changes the bytes and will break signature verification. Capture the raw body with `express.raw({ type: 'application/json' })` and pass `req.body.toString()` (see the Express example below).
700
+
677
701
  ```javascript
678
702
  const { Blaaiz } = require('blaaiz-nodejs-sdk');
679
703
 
@@ -681,7 +705,7 @@ const blaaiz = new Blaaiz('your-api-key');
681
705
 
682
706
  // Method 1: Verify signature manually
683
707
  const isValid = blaaiz.webhooks.verifySignature(
684
- payload, // Raw webhook payload (string or object)
708
+ payload, // Raw request body string (do not pass a parsed object)
685
709
  signature, // Signature from webhook headers (x-blaaiz-signature)
686
710
  timestamp, // Timestamp from webhook headers (x-blaaiz-timestamp)
687
711
  webhookSecret // Your webhook secret key
@@ -696,7 +720,7 @@ if (isValid) {
696
720
  // Method 2: Construct verified event (recommended)
697
721
  try {
698
722
  const event = blaaiz.webhooks.constructEvent(
699
- payload, // Raw webhook payload
723
+ payload, // Raw request body string (do not pass a parsed object)
700
724
  signature, // Signature from webhook headers
701
725
  timestamp, // Timestamp from webhook headers
702
726
  webhookSecret // Your webhook secret key
package/index.d.ts CHANGED
@@ -35,7 +35,43 @@ export interface CustomerData {
35
35
  export interface Customer extends CustomerData {
36
36
  id: string;
37
37
  business_id: string;
38
- verification_status: 'PENDING' | 'VERIFIED' | 'REJECTED';
38
+ verification_status: 'PENDING' | 'PROCESSING' | 'VERIFIED' | 'REJECTED';
39
+ }
40
+
41
+ export interface CustomerListFilters {
42
+ email?: string;
43
+ id_number?: string;
44
+ registration_number?: string;
45
+ verification_status?: 'PENDING' | 'PROCESSING' | 'VERIFIED' | 'REJECTED';
46
+ type?: 'individual' | 'business';
47
+ paginate?: boolean;
48
+ page?: number;
49
+ per_page?: number;
50
+ [key: string]: string | number | boolean | undefined;
51
+ }
52
+
53
+ export interface PaginationLinks {
54
+ first?: string | null;
55
+ last?: string | null;
56
+ prev?: string | null;
57
+ next?: string | null;
58
+ }
59
+
60
+ export interface PaginationMeta {
61
+ current_page: number;
62
+ from?: number | null;
63
+ last_page?: number;
64
+ path?: string;
65
+ per_page?: number;
66
+ to?: number | null;
67
+ total: number;
68
+ }
69
+
70
+ export interface PaginatedCustomers {
71
+ data: Customer[];
72
+ links: PaginationLinks;
73
+ meta: PaginationMeta;
74
+ message?: string;
39
75
  }
40
76
 
41
77
  export interface CustomerKYCData {
@@ -103,6 +139,7 @@ export interface PayoutData {
103
139
  wallet_address?: string;
104
140
  wallet_network?: string;
105
141
  wallet_token?: string;
142
+ note?: string;
106
143
  }
107
144
 
108
145
  export interface PayoutResponse {
@@ -244,7 +281,7 @@ export interface WebhookEvent {
244
281
  export declare class CustomerService {
245
282
  constructor(client: any);
246
283
  create(customerData: CustomerData): Promise<BlaaizResponse<{ data: Customer }>>;
247
- list(): Promise<BlaaizResponse<Customer[]>>;
284
+ list(filters?: CustomerListFilters): Promise<BlaaizResponse<Customer[] | PaginatedCustomers>>;
248
285
  get(customerId: string): Promise<BlaaizResponse<Customer>>;
249
286
  update(customerId: string, updateData: Partial<CustomerData>): Promise<BlaaizResponse<Customer>>;
250
287
  addKYC(customerId: string, kycData: CustomerKYCData): Promise<BlaaizResponse<any>>;
@@ -311,8 +348,8 @@ export declare class WebhookService {
311
348
  get(): Promise<BlaaizResponse<WebhookData>>;
312
349
  update(webhookData: Partial<WebhookData>): Promise<BlaaizResponse<any>>;
313
350
  replay(replayData: WebhookReplayData): Promise<BlaaizResponse<any>>;
314
- verifySignature(payload: string | object, signature: string, secret: string): boolean;
315
- constructEvent(payload: string | object, signature: string, secret: string): WebhookEvent;
351
+ verifySignature(payload: string, signature: string, timestamp: string, secret: string): boolean;
352
+ constructEvent(payload: string, signature: string, timestamp: string, secret: string): WebhookEvent;
316
353
  }
317
354
 
318
355
  // Main SDK Class
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blaaiz-nodejs-sdk",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Official Node.js SDK for Blaaiz RaaS (Remittance as a Service) API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -40,10 +40,10 @@
40
40
  "license": "MIT",
41
41
  "repository": {
42
42
  "type": "git",
43
- "url": "https://github.com/blaaiz/nodejs-sdk.git"
43
+ "url": "git+https://github.com/Blaaiz/blaaiz-nodejs-sdk.git"
44
44
  },
45
45
  "bugs": {
46
- "url": "https://github.com/blaaiz/nodejs-sdk/issues"
46
+ "url": "https://github.com/Blaaiz/blaaiz-nodejs-sdk/issues"
47
47
  },
48
48
  "homepage": "https://docs.business.blaaiz.com",
49
49
  "engines": {
@@ -25,8 +25,15 @@ class CustomerService {
25
25
  return this.client.makeRequest('POST', '/api/external/customer', customerData)
26
26
  }
27
27
 
28
- async list () {
29
- return this.client.makeRequest('GET', '/api/external/customer')
28
+ async list (filters = {}) {
29
+ const params = new URLSearchParams()
30
+ for (const [key, value] of Object.entries(filters || {})) {
31
+ if (value === undefined || value === null) continue
32
+ params.append(key, typeof value === 'boolean' ? String(value) : value)
33
+ }
34
+ const query = params.toString()
35
+ const endpoint = query ? `/api/external/customer?${query}` : '/api/external/customer'
36
+ return this.client.makeRequest('GET', endpoint)
30
37
  }
31
38
 
32
39
  async get (customerId) {
@@ -54,13 +54,16 @@ class WebhookService {
54
54
  throw new Error('Webhook secret is required for signature verification')
55
55
  }
56
56
 
57
- const crypto = require('crypto')
57
+ // The payload must be the raw request body string. Parsing and
58
+ // re-serializing an object changes the bytes and breaks verification.
59
+ if (typeof payload !== 'string') {
60
+ throw new Error('Webhook payload must be the raw request body string. Do not pass a parsed object — parsing and re-serializing changes the bytes and breaks signature verification. Use the raw body (e.g. express.raw({ type: "application/json" }) then req.body.toString()).')
61
+ }
58
62
 
59
- // Convert payload to string if it's an object
60
- const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload)
63
+ const crypto = require('crypto')
61
64
 
62
65
  // Create signed payload with timestamp
63
- const signedPayload = `${timestamp}.${payloadString}`
66
+ const signedPayload = `${timestamp}.${payload}`
64
67
 
65
68
  // Create HMAC signature
66
69
  const expectedSignature = crypto