@grabjs/superapp-sdk 2.0.0-beta.37 → 2.0.0-beta.46

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/skills/SKILL.md CHANGED
@@ -42,10 +42,11 @@ import { isSuccess, isError } from '@grabjs/superapp-sdk';
42
42
 
43
43
  #### CDN (UMD Bundle)
44
44
 
45
- If you are not using a bundler, load the SDK from a CDN and access it via the `SuperAppSDK` global:
45
+ If you are not using a bundler, load the SDK from a CDN and access it via the `SuperAppSDK` global.
46
+ **Always pin to a specific version** (e.g., `@x.y.z`) — omitting the version always fetches the latest release, which may contain breaking changes.
46
47
 
47
48
  ```html
48
- <script src="https://cdn.jsdelivr.net/npm/@grabjs/superapp-sdk/dist/index.js"></script>
49
+ <script src="https://cdn.jsdelivr.net/npm/@grabjs/superapp-sdk@x.y.z/dist/index.js"></script>
49
50
  <script>
50
51
  const { ContainerModule, ScopeModule, isSuccess, isError } = window.SuperAppSDK;
51
52
  </script>
@@ -61,25 +62,20 @@ SDK methods communicate with the native Grab SuperApp via JSBridge. They only wo
61
62
  Every SDK method returns a bridge response object with an HTTP-style `status_code`. SDK methods never throw — use type guards instead of try/catch.
62
63
 
63
64
  ```typescript
64
- import { CameraModule, isSuccess, isError } from '@grabjs/superapp-sdk';
65
+ import { ProfileModule, isSuccess, isError } from '@grabjs/superapp-sdk';
65
66
 
66
- const camera = new CameraModule();
67
- const response = await camera.scanQRCode({ title: 'Scan Payment QR' });
67
+ const profile = new ProfileModule();
68
+ const response = await profile.fetchEmail();
68
69
 
69
70
  if (isSuccess(response)) {
70
- switch (response.status_code) {
71
- case 200:
72
- console.log('QR Code scanned:', response.result.qrCode);
73
- break;
74
- case 204:
75
- // operation completed with no content
76
- break;
77
- }
71
+ console.log('Result:', response.result);
78
72
  } else if (isError(response)) {
79
- // response.error: string is guaranteed
80
73
  switch (response.status_code) {
81
74
  case 403:
82
- // call IdentityModule.authorize() then ScopeModule.reloadScopes() before retrying
75
+ // Missing OAuth scope - call IdentityModule.authorize() then ScopeModule.reloadScopes()
76
+ break;
77
+ case 426:
78
+ // Grab app version too old - prompt user to update their app
83
79
  break;
84
80
  default:
85
81
  console.error(`Error ${response.status_code}: ${response.error}`);
@@ -91,19 +87,79 @@ if (isSuccess(response)) {
91
87
 
92
88
  The SDK uses HTTP-style status codes for all responses:
93
89
 
94
- | Code | Type | Description |
95
- | ----- | ----------------- | --------------------------------------------------- |
96
- | `200` | OK | Request successful, `result` contains response data |
97
- | `204` | No Content | Request successful, no data returned |
98
- | `302` | Redirect | Redirect in progress |
99
- | `400` | Bad Request | Invalid request parameters |
100
- | `401` | Unauthorized | Authentication required |
101
- | `403` | Forbidden | Insufficient permissions for this operation |
102
- | `404` | Not Found | Resource not found |
103
- | `424` | Failed Dependency | Underlying native request failed |
104
- | `426` | Upgrade Required | Requires newer Grab app version |
105
- | `500` | Internal Error | Unexpected SDK error |
106
- | `501` | Not Implemented | Method requires Grab SuperApp environment |
90
+ | Code | Type | Description |
91
+ | :---- | :---------------- | :---------------------------------------------------------- |
92
+ | `200` | OK | Request successful, `result` contains response data |
93
+ | `204` | No Content | Request successful, no data returned |
94
+ | `302` | Redirect | Redirect in progress |
95
+ | `400` | Bad Request | Invalid request parameters |
96
+ | `401` | Unauthorized | Authentication required |
97
+ | `403` | Forbidden | Insufficient permission (see `@requiredOAuthScope` tag) |
98
+ | `404` | Not Found | Resource not found |
99
+ | `424` | Failed Dependency | Underlying native request failed |
100
+ | `426` | Upgrade Required | Grab app version too old (see `@minimumGrabAppVersion` tag) |
101
+ | `500` | Internal Error | Unexpected SDK error |
102
+ | `501` | Not Implemented | Outside Grab SuperApp environment |
103
+
104
+ ### Handling 403 Forbidden
105
+
106
+ Methods tagged with `@requiredOAuthScope` require specific permissions. If the user hasn't granted the required scope, the method returns `403`. You must request authorization and reload scopes before retrying:
107
+
108
+ 1. Call `IdentityModule.authorize()` to request the scope.
109
+ 2. Call `ScopeModule.reloadScopes()` to refresh the SDK's internal permission state.
110
+ 3. Retry the original method call.
111
+
112
+ #### Proactive Permission Checking
113
+
114
+ Proactively verify if the current session has the necessary permissions for a method using `ScopeModule.hasAccessTo()`:
115
+
116
+ ```typescript
117
+ const scope = new ScopeModule();
118
+ const hasAccess = await scope.hasAccessTo('LocationModule', 'getCoordinate');
119
+
120
+ if (isSuccess(hasAccess) && hasAccess.result) {
121
+ // Permission is available, safe to call the method
122
+ const location = await location.getCoordinate();
123
+ }
124
+ ```
125
+
126
+ ```typescript
127
+ import {
128
+ LocationModule,
129
+ IdentityModule,
130
+ ScopeModule,
131
+ isSuccess,
132
+ isError,
133
+ } from '@grabjs/superapp-sdk';
134
+
135
+ const location = new LocationModule();
136
+ const identity = new IdentityModule();
137
+ const scope = new ScopeModule();
138
+
139
+ const response = await location.getCoordinate();
140
+
141
+ if (isError(response) && response.status_code === 403) {
142
+ // 1. Request authorization for the required scope
143
+ const auth = await identity.authorize({
144
+ clientId: 'your-client-id',
145
+ redirectUri: 'https://your-app.com/callback',
146
+ scope: 'mobile.geolocation', // The scope defined in @requiredOAuthScope
147
+ environment: 'production',
148
+ responseMode: 'in_place',
149
+ });
150
+
151
+ if (isSuccess(auth)) {
152
+ // 2. Reload scopes so the new permission is available
153
+ await scope.reloadScopes();
154
+
155
+ // 3. Retry the original call
156
+ const retry = await location.getCoordinate();
157
+ if (isSuccess(retry)) {
158
+ console.log('Result:', retry.result);
159
+ }
160
+ }
161
+ }
162
+ ```
107
163
 
108
164
  ### Type Guards
109
165
 
@@ -161,6 +217,10 @@ You can also `await` a stream method directly to get its first value.
161
217
 
162
218
  This guide covers the recommended setup for a MiniApp entry point — loading scopes, configuring the container UI, signalling readiness, and handling permissions.
163
219
 
220
+ ### Demo App
221
+
222
+ The [demo](https://github.com/grab/superapp-sdk/tree/master/demo) folder contains two complete MiniApp samples demonstrating these integration patterns in action — one using CDN (vanilla HTML/JS) and one using React. Both implement the same user flow: OAuth authorization, user profile display, deferred location permissions, and checkout payment.
223
+
164
224
  ### Entry Point Setup
165
225
 
166
226
  Run these steps once when your MiniApp initialises, before rendering any content.
@@ -249,6 +309,283 @@ if (isError(response)) {
249
309
  }
250
310
  ```
251
311
 
312
+ ### Analytics Event Tracking
313
+
314
+ Implement analytics events across your user journey to enable performance tracking and reporting. Events are sent via `ContainerModule.sendAnalyticsEvent()` and categorised by journey stage using `ContainerAnalyticsEventState`.
315
+
316
+ #### Required Events
317
+
318
+ ##### Entry Point
319
+
320
+ ###### Initiate action
321
+
322
+ Send the initiate event when users click call-to-action buttons to proceed:
323
+
324
+ ```typescript
325
+ import {
326
+ ContainerModule,
327
+ ContainerAnalyticsEventState,
328
+ isSuccess,
329
+ isError,
330
+ } from '@grabjs/superapp-sdk';
331
+
332
+ // Event names are plain strings — define your own constants
333
+ const EventName = {
334
+ INITIATE: 'INITIATE',
335
+ TRANSACT: 'TRANSACT',
336
+ };
337
+
338
+ const containerModule = new ContainerModule();
339
+
340
+ // Send when the user clicks a call-to-action button
341
+ const response = await containerModule.sendAnalyticsEvent({
342
+ state: ContainerAnalyticsEventState.HOMEPAGE,
343
+ name: EventName.INITIATE,
344
+ });
345
+
346
+ if (isSuccess(response)) {
347
+ // Event sent successfully
348
+ } else if (isError(response)) {
349
+ console.error(`Failed to send event: ${response.error}`);
350
+ }
351
+ ```
352
+
353
+ ###### Custom interactions
354
+
355
+ Send custom events for additional interactions like banner clicks, category selections, or search queries. Include the `page` parameter and a descriptive event name:
356
+
357
+ ```typescript
358
+ import {
359
+ ContainerModule,
360
+ ContainerAnalyticsEventState,
361
+ isSuccess,
362
+ isError,
363
+ } from '@grabjs/superapp-sdk';
364
+
365
+ const containerModule = new ContainerModule();
366
+
367
+ // Send for custom interactions such as banner clicks or category selections
368
+ const response = await containerModule.sendAnalyticsEvent({
369
+ state: ContainerAnalyticsEventState.CUSTOM,
370
+ name: 'BANNER_CLICK',
371
+ data: {
372
+ page: 'homepage',
373
+ banner_id: 'promo-summer-2024',
374
+ banner_position: 'top',
375
+ },
376
+ });
377
+
378
+ if (isSuccess(response)) {
379
+ // Event sent successfully
380
+ } else if (isError(response)) {
381
+ console.error(`Failed to send event: ${response.error}`);
382
+ }
383
+ ```
384
+
385
+ ##### Conversion Point
386
+
387
+ ###### Transaction confirmation
388
+
389
+ Send the transaction confirmation event when users click the final confirmation button:
390
+
391
+ ```typescript
392
+ import {
393
+ ContainerModule,
394
+ ContainerAnalyticsEventState,
395
+ isSuccess,
396
+ isError,
397
+ } from '@grabjs/superapp-sdk';
398
+
399
+ // Event names are plain strings — define your own constants
400
+ const EventName = {
401
+ INITIATE: 'INITIATE',
402
+ TRANSACT: 'TRANSACT',
403
+ };
404
+
405
+ const containerModule = new ContainerModule();
406
+
407
+ // Send when the user clicks the final confirmation button
408
+ const response = await containerModule.sendAnalyticsEvent({
409
+ state: ContainerAnalyticsEventState.CHECKOUT_PAGE,
410
+ name: EventName.TRANSACT,
411
+ data: {
412
+ transaction_amount: 49.99,
413
+ transaction_currency: 'SGD',
414
+ transaction_id: 'TXN-2024-001234',
415
+ payment_method: 'grabpay',
416
+ item_count: 2,
417
+ },
418
+ });
419
+
420
+ if (isSuccess(response)) {
421
+ // Event sent successfully
422
+ } else if (isError(response)) {
423
+ console.error(`Failed to send event: ${response.error}`);
424
+ }
425
+ ```
426
+
427
+ ###### Custom interactions
428
+
429
+ Send custom events for checkout interactions like promo code applications or payment method selections:
430
+
431
+ ```typescript
432
+ import {
433
+ ContainerModule,
434
+ ContainerAnalyticsEventState,
435
+ isSuccess,
436
+ isError,
437
+ } from '@grabjs/superapp-sdk';
438
+
439
+ const containerModule = new ContainerModule();
440
+
441
+ // Send for custom checkout interactions such as promo code applications
442
+ const response = await containerModule.sendAnalyticsEvent({
443
+ state: ContainerAnalyticsEventState.CUSTOM,
444
+ name: 'PROMO_CODE_APPLIED',
445
+ data: {
446
+ page: 'checkout',
447
+ promo_code: 'SAVE20',
448
+ discount_amount: 10.0,
449
+ discount_type: 'percentage',
450
+ },
451
+ });
452
+
453
+ if (isSuccess(response)) {
454
+ // Event sent successfully
455
+ } else if (isError(response)) {
456
+ console.error(`Failed to send event: ${response.error}`);
457
+ }
458
+ ```
459
+
460
+ ##### Completion Point
461
+
462
+ ###### Follow-up actions
463
+
464
+ Send custom events for post-transaction actions like downloading receipts or tracking orders:
465
+
466
+ ```typescript
467
+ import {
468
+ ContainerModule,
469
+ ContainerAnalyticsEventState,
470
+ isSuccess,
471
+ isError,
472
+ } from '@grabjs/superapp-sdk';
473
+
474
+ const containerModule = new ContainerModule();
475
+
476
+ // Send for post-transaction actions such as downloading a receipt
477
+ const response = await containerModule.sendAnalyticsEvent({
478
+ state: ContainerAnalyticsEventState.CUSTOM,
479
+ name: 'RECEIPT_DOWNLOAD',
480
+ data: {
481
+ page: 'completion',
482
+ transaction_id: 'TXN-2024-001234',
483
+ format: 'pdf',
484
+ },
485
+ });
486
+
487
+ if (isSuccess(response)) {
488
+ // Event sent successfully
489
+ } else if (isError(response)) {
490
+ console.error(`Failed to send event: ${response.error}`);
491
+ }
492
+ ```
493
+
494
+ #### Best Practices
495
+
496
+ - Track system events automatically when users navigate to the corresponding pages.
497
+ - Always include required data fields for transaction events to enable accurate revenue tracking.
498
+ - Use descriptive names for custom events that clearly indicate the user action being tracked.
499
+ - Never include Personally Identifiable Information (PII) in event data.
500
+
501
+ ### Checkout
502
+
503
+ The checkout flow is a two-step process: your backend first initializes a transaction using your partner credentials, then your frontend triggers the native payment interface using the response from your backend.
504
+
505
+ #### Step 1 — Initialize transaction on your backend
506
+
507
+ Before calling `CheckoutModule.triggerCheckout()`, you must create a transaction on your server by calling the [GrabPay API](https://developer.grab.com/docs/partner-apps/pages/developer-resources/payment/#create-transaction). This requires your `partnerID` and `partnerSecret` to generate an HMAC-SHA256 signature.
508
+
509
+ The API returns a payload containing `partnerTxID`, `request`, and `sessionID` — all three fields are required by the frontend.
510
+
511
+ #### Step 2 — Trigger checkout from your frontend
512
+
513
+ Pass the complete response from the Initialize Transaction API to `CheckoutModule.triggerCheckout()`:
514
+
515
+ ```typescript
516
+ import {
517
+ CheckoutModule,
518
+ IdentityModule,
519
+ ScopeModule,
520
+ isSuccess,
521
+ isError,
522
+ } from '@grabjs/superapp-sdk';
523
+
524
+ const checkout = new CheckoutModule();
525
+ const identity = new IdentityModule();
526
+ const scope = new ScopeModule();
527
+
528
+ async function processPayment() {
529
+ // 1. Ensure mobile.checkout scope is authorized
530
+ const authResponse = await identity.authorize({
531
+ clientId: 'your-client-id',
532
+ redirectUri: 'https://your-miniapp.example.com/callback',
533
+ scope: 'mobile.checkout',
534
+ environment: 'production',
535
+ responseMode: 'in_place',
536
+ });
537
+
538
+ if (isSuccess(authResponse)) {
539
+ await scope.reloadScopes();
540
+ } else if (isError(authResponse)) {
541
+ console.error('Authorization failed:', authResponse.error);
542
+ return;
543
+ }
544
+
545
+ // 2. Fetch the initialized transaction payload from your backend
546
+ const response = await fetch('https://your-backend.example.com/init-transaction', {
547
+ method: 'POST',
548
+ headers: { 'Content-Type': 'application/json' },
549
+ body: JSON.stringify({ orderId: 'order-123' }),
550
+ });
551
+ const { partnerTxID, request, sessionID } = await response.json();
552
+
553
+ // 3. Trigger checkout with the backend response
554
+ const checkoutResult = await checkout.triggerCheckout({
555
+ partnerTxID,
556
+ request,
557
+ sessionID,
558
+ });
559
+
560
+ if (isSuccess(checkoutResult)) {
561
+ const { status, transactionID, errorCode, errorMessage } = checkoutResult.result;
562
+
563
+ if (status === 'success') {
564
+ console.log('Payment successful:', transactionID);
565
+ } else if (status === 'failure') {
566
+ console.error('Payment failed:', errorCode, errorMessage);
567
+ } else if (status === 'pending') {
568
+ console.log('Payment is processing:', transactionID);
569
+ } else if (status === 'userInitiatedCancel') {
570
+ console.log('User cancelled payment');
571
+ }
572
+ } else if (isError(checkoutResult)) {
573
+ console.error('Checkout error:', checkoutResult.error);
574
+ }
575
+ }
576
+ ```
577
+
578
+ #### Result status values
579
+
580
+ | Status | Description |
581
+ | :-------------------- | :----------------------------------------------------------------------------- |
582
+ | `success` | Payment completed successfully. `transactionID` is provided. |
583
+ | `failure` | Payment failed. `transactionID`, `errorCode`, and `errorMessage` are provided. |
584
+ | `pending` | Payment is still being processed. `transactionID` is provided. |
585
+ | `userInitiatedCancel` | User cancelled the payment. No other fields are present. |
586
+
587
+ For the complete API reference, see [CheckoutModule](https://grab.github.io/superapp-sdk/classes/CheckoutModule.html).
588
+
252
589
 
253
590
  ## API Reference
254
591
 
@@ -260,25 +597,25 @@ JSBridge module for accessing the device camera.
260
597
 
261
598
  #### `CheckoutModule`
262
599
  JSBridge module for triggering native payment flows.
263
- - `triggerCheckout(request: Record<string, unknown>): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: { status: "success"; transactionID: string } | { errorCode: string; errorMessage: string; status: "failure"; transactionID: string } | { status: "pending"; transactionID: string } | { status: "userInitiatedCancel" }; status_code: 200 }>` — Triggers the native checkout flow for payment processing.
600
+ - `triggerCheckout(request: Record<string, unknown>): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: { status: "success"; transactionID: string } | { errorCode: string; errorMessage: string; status: "failure"; transactionID: string } | { status: "pending"; transactionID: string } | { status: "userInitiatedCancel" }; status_code: 200 }>` — Triggers the native checkout flow for payment processing. (**OAuth Scope:** mobile.checkout)
264
601
 
265
602
  #### `ContainerModule`
266
603
  JSBridge module for controlling the WebView container.
267
- - `close(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Close the container and return to the previous screen.
604
+ - `close(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Close the container and return to the previous screen.
268
605
  - `getSessionParams(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: string; status_code: 200 }>` — Get the session parameters from the container.
269
- - `hideBackButton(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Hide the back button on the container header.
270
- - `hideLoader(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Hide the full-screen loading indicator.
271
- - `hideRefreshButton(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Hide the refresh button on the container header.
606
+ - `hideBackButton(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Hide the back button on the container header.
607
+ - `hideLoader(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Hide the full-screen loading indicator.
608
+ - `hideRefreshButton(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Hide the refresh button on the container header.
272
609
  - `isConnected(): Promise<{ result: { connected: boolean }; status_code: 200 } | { error: string; status_code: 404 }>` — Check if the web app is connected to the Grab SuperApp via JSBridge.
273
610
  - `onContentLoaded(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Notify the Grab SuperApp that the page content has loaded.
274
611
  - `onCtaTap(request: string): Promise<{ error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Notify the client that the user has tapped a call-to-action (CTA).
275
- - `openExternalLink(request: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Open a link in the external browser.
276
- - `sendAnalyticsEvent(request: { data?: Record<string, unknown>; name: string; state: string }): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Use this method to track user interactions and page transitions.
277
- - `setBackgroundColor(request: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Set the background color of the container header.
278
- - `setTitle(request: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Set the title of the container header.
279
- - `showBackButton(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Show the back button on the container header.
280
- - `showLoader(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Show the full-screen loading indicator.
281
- - `showRefreshButton(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: boolean; status_code: 200 }>` — Show the refresh button on the container header.
612
+ - `openExternalLink(request: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Open a link in the external browser.
613
+ - `sendAnalyticsEvent(request: { data?: Record<string, unknown>; name: string; state: string }): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Use this method to track user interactions and page transitions.
614
+ - `setBackgroundColor(request: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Set the background color of the container header.
615
+ - `setTitle(request: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Set the title of the container header.
616
+ - `showBackButton(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Show the back button on the container header.
617
+ - `showLoader(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Show the full-screen loading indicator.
618
+ - `showRefreshButton(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 }>` — Show the refresh button on the container header.
282
619
 
283
620
  #### `DeviceModule`
284
621
  JSBridge module for querying native device information.
@@ -304,17 +641,17 @@ JSBridge module for accessing device locale settings.
304
641
 
305
642
  #### `LocationModule`
306
643
  JSBridge module for accessing device location services.
307
- - `getCoordinate(): Promise<{ error: string; status_code: 403 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: { latitude: number; longitude: number }; status_code: 200 } | { error: string; status_code: 424 }>` — Get the current geographic coordinates of the device.
308
- - `getCountryCode(): Promise<{ status_code: 204 } | { error: string; status_code: 403 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: string; status_code: 200 } | { error: string; status_code: 424 }>` — Get the country code based on the device's current location.
309
- - `observeLocationChange(): ObserveLocationChangeResponse` — Subscribe to location change updates from the device.
644
+ - `getCoordinate(): Promise<{ error: string; status_code: 403 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: { latitude: number; longitude: number }; status_code: 200 } | { error: string; status_code: 424 }>` — Get the current geographic coordinates of the device. (**OAuth Scope:** mobile.geolocation)
645
+ - `getCountryCode(): Promise<{ status_code: 204 } | { error: string; status_code: 403 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { result: string; status_code: 200 } | { error: string; status_code: 424 }>` — Get the country code based on the device's current location. (**OAuth Scope:** mobile.geolocation)
646
+ - `observeLocationChange(): ObserveLocationChangeResponse` — Subscribe to location change updates from the device. (**OAuth Scope:** mobile.geolocation)
310
647
 
311
648
  #### `Logger`
312
649
  Provides scoped logging for SDK modules.
313
650
 
314
651
  #### `MediaModule`
315
652
  JSBridge module for playing DRM-protected media content.
316
- - `observePlayDRMContent(data: DRMContentConfig): ObserveDRMPlaybackResponse` — Observes DRM-protected media content playback events.
317
- - `playDRMContent(data: DRMContentConfig): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { length: number; position: number; titleId: string; type: "START_PLAYBACK" | "PROGRESS_PLAYBACK" | "START_SEEK" | "STOP_SEEK" | "STOP_PLAYBACK" | "CLOSE_PLAYBACK" | "PAUSE_PLAYBACK" | "RESUME_PLAYBACK" | "FAST_FORWARD_PLAYBACK" | "REWIND_PLAYBACK" | "ERROR_PLAYBACK" | "CHANGE_VOLUME" }; status_code: 200 }>` — Plays DRM-protected media content in the native media player.
653
+ - `observePlayDRMContent(data: DRMContentConfig): ObserveDRMPlaybackResponse` — Observes DRM-protected media content playback events. (**OAuth Scope:** mobile.media)
654
+ - `playDRMContent(data: DRMContentConfig): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { length: number; position: number; titleId: string; type: "START_PLAYBACK" | "PROGRESS_PLAYBACK" | "START_SEEK" | "STOP_SEEK" | "STOP_PLAYBACK" | "CLOSE_PLAYBACK" | "PAUSE_PLAYBACK" | "RESUME_PLAYBACK" | "FAST_FORWARD_PLAYBACK" | "REWIND_PLAYBACK" | "ERROR_PLAYBACK" | "CHANGE_VOLUME" }; status_code: 200 }>` — Plays DRM-protected media content in the native media player. (**OAuth Scope:** mobile.media)
318
655
 
319
656
  #### `NetworkModule`
320
657
  JSBridge module for making network requests via the native bridge.
@@ -327,8 +664,8 @@ This navigates back in the native navigation stack.
327
664
 
328
665
  #### `ProfileModule`
329
666
  JSBridge module for accessing user profile information.
330
- - `fetchEmail(): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 403 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 426 } | { result: { email: string }; status_code: 200 }>` — Fetches the user's email address from their Grab profile.
331
- - `verifyEmail(request?: { email?: string; skipUserInput?: boolean }): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 403 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 426 } | { result: { email: string }; status_code: 200 }>` — Verifies the user's email address by triggering email capture bottom sheet and OTP verification.
667
+ - `fetchEmail(): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 403 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 426 } | { result: { email: string }; status_code: 200 }>` — Fetches the user's email address from their Grab profile. (**OAuth Scope:** mobile.profile | **Minimum Grab App Version:** Android: 5.399.0, iOS: 5.399.0)
668
+ - `verifyEmail(request?: { email?: string; skipUserInput?: boolean }): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 403 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 426 } | { result: { email: string }; status_code: 200 }>` — Verifies the user's email address by triggering email capture bottom sheet and OTP verification. (**OAuth Scope:** mobile.profile | **Minimum Grab App Version:** Android: 5.399.0, iOS: 5.399.0)
332
669
 
333
670
  #### `ScopeModule`
334
671
  JSBridge module for checking and refreshing API access permissions.
@@ -342,16 +679,16 @@ JSBridge module for controlling the native splash / Lottie loading screen.
342
679
 
343
680
  #### `StorageModule`
344
681
  JSBridge module for persisting key-value data to native storage.
345
- - `getBoolean(key: string): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { value: boolean | null }; status_code: 200 }>` — Retrieves a boolean value from the native storage.
346
- - `getDouble(key: string): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { value: number | null }; status_code: 200 }>` — Retrieves a double (floating point) value from the native storage.
347
- - `getInt(key: string): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { value: number | null }; status_code: 200 }>` — Retrieves an integer value from the native storage.
348
- - `getString(key: string): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { value: string | null }; status_code: 200 }>` — Retrieves a string value from the native storage.
349
- - `remove(key: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Removes a single value from the native storage by key.
350
- - `removeAll(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Removes all values from the native storage.
351
- - `setBoolean(key: string, value: boolean): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Stores a boolean value in the native storage.
352
- - `setDouble(key: string, value: number): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Stores a double (floating point) value in the native storage.
353
- - `setInt(key: string, value: number): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Stores an integer value in the native storage.
354
- - `setString(key: string, value: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Stores a string value in the native storage.
682
+ - `getBoolean(key: string): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { value: boolean | null }; status_code: 200 }>` — Retrieves a boolean value from the native storage. (**OAuth Scope:** mobile.storage)
683
+ - `getDouble(key: string): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { value: number | null }; status_code: 200 }>` — Retrieves a double (floating point) value from the native storage. (**OAuth Scope:** mobile.storage)
684
+ - `getInt(key: string): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { value: number | null }; status_code: 200 }>` — Retrieves an integer value from the native storage. (**OAuth Scope:** mobile.storage)
685
+ - `getString(key: string): Promise<{ error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 } | { result: { value: string | null }; status_code: 200 }>` — Retrieves a string value from the native storage. (**OAuth Scope:** mobile.storage)
686
+ - `remove(key: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Removes a single value from the native storage by key. (**OAuth Scope:** mobile.storage)
687
+ - `removeAll(): Promise<{ status_code: 204 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Removes all values from the native storage. (**OAuth Scope:** mobile.storage)
688
+ - `setBoolean(key: string, value: boolean): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Stores a boolean value in the native storage. (**OAuth Scope:** mobile.storage)
689
+ - `setDouble(key: string, value: number): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Stores a double (floating point) value in the native storage. (**OAuth Scope:** mobile.storage)
690
+ - `setInt(key: string, value: number): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Stores an integer value in the native storage. (**OAuth Scope:** mobile.storage)
691
+ - `setString(key: string, value: string): Promise<{ status_code: 204 } | { error: string; status_code: 400 } | { error: string; status_code: 500 } | { error: string; status_code: 501 } | { error: string; status_code: 424 }>` — Stores a string value in the native storage. (**OAuth Scope:** mobile.storage)
355
692
 
356
693
  #### `SystemWebViewKitModule`
357
694
  JSBridge module for opening URLs in the device's system browser.