Mobile App

You can use the Widget embedded using a WebView in your mobile application and listen to the events.

Settings

ParameterExampleDescriptionRequired
widget_ida64fef80-42ec-4d5b-bd38-c918e0071663The unique widget_idYes

Optional Parameters

Configuration parameters

Parameter

Example

Description

is_sandbox

true

If set to true, sandbox mode is enabled.

  • false by default for production widgets
  • true by default for sandbox widgets

platforms

uber,rappi,didi

User-selectable comma-separated platform codes.
Available platforms .

lang

es

Replaces the language automatically detected by the browser. Available languages: es, en, and pt. null by default

countries

mx,br

User-selectable comma-separated alpha-2 country codes

country

mx

Single country code to be used for the widget (can be used instead of countries).

redirect_url

https://domain.com/step-2

URL to which the user should be redirected after successfully connecting their account

hide_redirect_url

true

If set to true, the user won't be redirected after completing the connection.
true by default

custom_privacy_url

https://domain.com/privacy

Allows you to add a custom privacy terms link, useful if you need custom consent

hide_privacy_url

true

If set to true, the custom privacy terms link won't be displayed.
true by default

hide_consent

false

If set to true, the Consent page is hidden.
false by default

Appearance parameters

ParameterExampleDescription
primary_color#1F5BC0Hexadecimal Color
border_radius10pxThe border radius for buttons and inputs

Events

📘

Consider using Webhooks

While Widget events can be useful, we recommend using Webhooks for a more reliable and scalable integration. Webhooks provide real-time updates without requiring the user to stay active, leading to a more efficient experience.

The only way to communicate with the Widget is by listening to an event. All events have a payload with the API envelope.

The following table shows all the Palenca Link events:

EventDescription
readyIndicates that your public API key and Widget are correct and that the widget has been initialized
user_createdThe user was created successfully
connection_successThe user successfully connected to the platform
connection_errorAn error occurred while trying to connect a user to the platform

Response for events

The envelope is always the same with the following structure:

{
     "signal": string,
     "response": {
         "success": bool,
         "data": Data Object,
         "error": Error Object
     }
}

Example for events

ready

{
     "signal": "ready"
}

user_created

{
     "signal": "user_created",
     "response": {
         "success": true,
         "data": {
             "user_id": "054d0a9d-38ec-40cb-a31c-09b483242e4a",
             "external_id": "4a0e32bd-c3df-4172-a89d-f173d6816926",
             "widget_id": "feecb679-a3cc-47ef-8fd4-600799f12a39"
         },
         "error": null
     }
}

connection_success

{
     "signal": "connection_success",
     "response": {
         "success": true,
         "data": {
             "user_id": "054d0a9d-38ec-40cb-a31c-09b483242e4a",
             "country": "mx",
             "platform": "imss",
             "account_id": "472f02e8-6b24-43a7-b529-3f71d6ecc81c"
         },
         "error": null
     }
}

connection_error


{
     "signal": "connection_error",
     "response": {
         "success": false,
         "mistake": {
             "code": "invalid_credentials",
             "message": "The username/password combination is wrong",
             "errors": null
         },
         "data": null
     }
}

Examples

React Native

To listen to the events you can use postMessage.

import React from 'react';
import { Alert } from 'react-native';
import { WebView } from 'react-native-webview';

const App = () => {
   const handleEvent = (event: any) => {
     Alert.alert(event.nativeEvent.data);
   }

   const widgetId: string = 'YOUR_WIDGET_ID';
   const baseUrl: string = 'https://connect.palenca.com';
   const uri: string = `${baseUrl}?widget_id=${widgetId}&primary_color=ea4c89`;

   return <WebView
   onMessage={handleEvent}
   source={{ uri }}
   />;
};

export default App;

Android Kotlin

activity_main.xml

     <WebView
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:id="@+id/webView"
         android:layout_gravity="center_horizontal"/>

MainActivity.kt

import android.content.Context
import android.os.Bundle
import android.webkit.JavascriptInterface
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.palenca.connect.databinding.ActivityMainBinding
import org.json.JSONObject

class MainActivity : AppCompatActivity() {

     private lateinit var binding: ActivityMainBinding
     private val baseUrl = "https://connect.palenca.com"
     private val widgetId = "YOUR_WIDGET"
     private val widgetUrl = "$baseUrl?widget_id=$widgetId&primary_color=ea4c89"

     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         binding = ActivityMainBinding.inflate(layoutInflater)
         setContentView(binding.root)
         binding.webView.webViewClient = WebViewClient()
         binding.webView.settings.javaScriptEnabled = true
         binding.webView.addJavascriptInterface(JSBridge(this), "JSBridge")
         binding.webView.loadUrl(widgetUrl)
     }

     /**
      * Receive messages from the Webview and pass into native
      */
     class JSBridge(private val context: Context) {
         @JavascriptInterface
         fun onEvent(event: String) {
             val jsonObject = JSONObject(event)
             println(jsonObject)
             Toast.makeText(context, event, Toast.LENGTH_LONG).show()
         }
     }
}

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>

Flutter

import 'package:flutter/material.dart';
import 'package:gibb_flutter/utils/flavors.dart';
import 'package:webview_flutter/webview_flutter.dart';

class PalencaScreen extends StatefulWidget {
  const PalencaScreen({super.key});

  @override
  State<PalencaScreen> createState() => _PalencaScreenState();
}

class _PalencaScreenState extends State<PalencaScreen> {
  late final WebViewController controller;

  void _handlePalencaEvent(String eventData) {
    if (eventData == 'user_created') {
      //handle data
    }
  }

  @override
  void initState() {
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageFinished: (String url) {
            controller.runJavaScript(
                "window.addEventListener('message', message =>{ Channel.postMessage(message.data['signal'])});");
          },
          onNavigationRequest: (NavigationRequest request) {
            return NavigationDecision.navigate;
          },
        ),
      )
      ..addJavaScriptChannel(
        'Channel',
        onMessageReceived: (message) {
          _handlePalencaEvent(message.message);
        },
      )
      ..loadRequest(Uri.parse(Flavor.palencaWidgetUrl));
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return WebViewWidget(
      controller: controller,
    );
  }
}