{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Widget Integration","description":"Tilia Wallet Developer Documentation","siteUrl":"https://thunes-tilia-docs.redocly.app/","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"widget-integration","__idx":0},"children":["Widget Integration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["With the widget style of integration, you retrieve and inject a Tilia-supplied script into your page, which provides an API to interact with our widget. You then “execute” the desired flow, passing an element id to indicate where the Tilia UI will appear in your page and callback functions to handle specific messages returned from the widget."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The diagram below illustrates the flow of information within a widget integration."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"img","attributes":{"src":"/assets/widget-flow.3a32b66e0f98742b5f961d08fd6201c4aa8d094028e911be35e2deb94c1179a3.9c1bb791.png","alt":"General Widget Flow"},"children":[]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"to-integrate-the-tilia-widget","__idx":1},"children":["To integrate the Tilia widget"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Widget integration involves the following steps:"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#step-1-user-authorization"},"children":["Step 1: User authorization"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#step-2-add-the-widget-script-to-your-page"},"children":["Step 2: Add the widget script to your page"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#step-3-retrieve-redirect-url-and-execute-the-flow"},"children":["Step 3: Retrieve redirect url and execute the flow"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"#step-4-handle-the-flow-result"},"children":["Step 4: Handle the flow result"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The rest of this document walks you through the basics of integrating a flow using the widget method."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-user-authorization","__idx":2},"children":["Step 1: User authorization"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All flows start with an OAuth2 authorization of the end user by passing an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["account_id"]},". The response will include a redirect URL with a generated nonce that authorizes the user to interact with the Tilia UIs."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Your server should contain an api endpoint that passes the 'redirect' payload to your frontend."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Creating the nonce requires an Access Token with the scope ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["write_user_tokens"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"curl --location --request POST https://auth.tilia-inc.com/authorize/user \\\n--header 'Authorization: Bearer <Access_Token>' \\\n--header 'Content-Type: application/json' \\\n"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"request-body","__idx":3},"children":["Request body"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n\t\"account_id\": \"<tilia_account_id>\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"sample-response","__idx":4},"children":["Sample response"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n    \"status\": \"Success\",\n    \"message\": [],\n    \"codes\": [],\n    \"payload\": {\n        \"redirect\": \"https://web.tilia-inc.com/ui/appauth/ed8ff1e9-9256-4205-918a-b9ca23ec00ec\"\n    }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The response includes a redirect URL that is used in the next step."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The nonce is valid for 24 hours. We recommend generating a nonce immediately before sending the user to a Tilia UI. Each nonce may only be used once."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-add-the-widget-script-to-your-page","__idx":5},"children":["Step 2: Add the widget script to your page"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"/**\n * Load widget script in your page.\n * This should happen early within the page load so it is ready when needed.\n */\nconst widget = document.createElement(\"script\");\nwidget.src = `https://web.tilia-inc.com/ui/v1/widget`;\nwidget.onload = () => {\n    // Use this to ensure the widget is\n    // loaded before using it.\n};\ndocument.body.appendChild(widget);\n\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-3-retrieve-redirect-url-and-execute-the-flow","__idx":6},"children":["Step 3: Retrieve redirect url and execute the flow"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Next, you will retrieve the redirect url ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["(from Step 1)"]}," and pass that with the desired flow name to the Tilia widget."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"/**\n * 1: Setup your callback functions\n * 2: Call your endpoint to retrieve redirect payload\n * 3: Execute widget with your desired Flow\n */\nfunction handleWidgetReady(e) {\n    console.log('handleWidgetReady:', e);\n    // handle the ‘ready’ message\n}\n\nfunction handleWidgetError(e) {\n    console.error('handleWidgetError', e);\n    // handle error\n}\n\nfunction handleWidgetComplete(e) {\n    console.log('handleWidgetComplete:', e);\n    // handle the ‘complete’ message\n}\n\nfunction triggerTiliaWidgetFlow() {\n    const yourEndpointThatReturnsRedirectPayload = \"/PATH/TO/YOUR/API/ENDPOINT/THAT/RETURNS/REDIRECT/PAYLOAD\";\n    fetch(yourEndpointThatReturnsRedirectPayload)\n        .then(response => {\n            /**\n             * For this example we will assume your endpoint is\n             * passing back the full payload from step one:\n             * {\n             *      \"status\": \"Success\",\n             *      \"message\": [],\n             *      \"codes\": [],\n             *      \"payload\": {\n             *          \"redirect\": \"https://web.tilia-inc.com/ui/appauth/ed8ff1e9-9256-4205-918a-b9ca23ec00ec\"\n             *      }\n             *  }\n             */\n            window.Tilia.execute({\n                //required parameters\n                rootId: < your.element.id > ,\n                flow: < flow.name > , // for example: \"tos\", \"kyc\", \"purchase\", \"payout\"\n                redirect: response.payload.redirect, // this could be different based on what your server is sending as a response.  Expects a URL string.\n                onComplete: handleWidgetComplete,\n                onError: handleWidgetError,\n                // optional parameters\n                debug: true, \n                onReady: handleWidgetReady,\n                flowConfig: {} // see specific flow documentation for supported config values\n            });\n        })\n        .catch(e => {\n            console.error('error retrieving redirect payload', e);\n            // handle error\n        });\n}\n\ntriggerTiliaWidgetFlow(); // call when ready.\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onComplete"]}," handler function will be called when the user completes the flow. The function will pass results specific to the flow."]},{"$$mdtype":"Tag","name":"details","attributes":{},"children":[{"$$mdtype":"Tag","name":"summary","attributes":{},"children":["Full HTML Example..."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Document</title>\n    <style type=\"text/css\">\n        html, body { width: 100%; height: 100%; }\n        body {\n            margin: 0;\n            padding: 0;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n        }\n\n        #my-widget-wrapper {\n            width: 480px;\n            height: 700px;\n            padding: 4px;\n            border: 1px solid black;\n            border-radius: 8px;\n        } \n    </style>\n    <script type=\"text/javascript\">\n        var widgetLoaded = false;\n        var callTriggerFlowAfterWidgetLoaded = false;\n\n        function loadWidget() {\n            /**\n             * Load widget script in your page.\n             * This should happen early within the page load so it is ready when needed.\n             */\n            var widget = document.createElement(\"script\");\n            widget.src = \"https://web.tilia-inc.com/ui/v1/widget\"; // if using the staging environment, you will want to change this to match staging URL\n            widget.onload = () => {\n                // Use this to ensure the widget is\n                // loaded before using it.\n                widgetLoaded = true;\n                console.log('widget loaded');\n                if (callTriggerFlowAfterWidgetLoaded) {\n                    triggerTiliaWidgetFlow();\n                }\n            };\n            document.body.appendChild(widget);\n        }\n\n        /**\n         * Your callback handlers\n        */\n        function handleWidgetReady(e) {\n            console.log('handleWidgetReady:', e);\n            // handle the ‘ready’ message\n        }\n\n        function handleWidgetError(e) {\n            console.error('handleWidgetError', e);\n            // handle error\n        }\n\n        function handleWidgetComplete(e) {\n            console.log('handleWidgetComplete:', e);\n            // handle the ‘complete’ message\n        }\n        /* ----------------- */\n\n        function triggerTiliaWidgetFlow() {\n            if (!widgetLoaded) {\n                // in this basic example, we are likely calling this function before the widget is ready.\n                // to get around this, we are setting a variable to re-call this function when the widget has loaded. \n                callTriggerFlowAfterWidgetLoaded = true;\n                return;\n            }\n            const yourEndpointThatReturnsRedirectPayload = \"/PATH/TO/YOUR/API/ENDPOINT/THAT/RETURNS/REDIRECT/PAYLOAD\";\n            fetch(yourEndpointThatReturnsRedirectPayload)\n                .then(response => {\n                    /**\n                     * For this example we will assume your endpoint is\n                     * passing back the full payload from step one:\n                     * {\n                     *      \"status\": \"Success\",\n                     *      \"message\": [],\n                     *      \"codes\": [],\n                     *      \"payload\": {\n                     *          \"redirect\": \"https://web.tilia-inc.com/ui/appauth/ed8ff1e9-9256-4205-918a-b9ca23ec00ec\"\n                     *      }\n                     *  }\n                     */\n                    window.Tilia.execute({\n                        //required parameters\n                        rootId: \"my-widget-wrapper\",\n                        flow: \"purchase\", // for example: \"tos\", \"kyc\", \"purchase\", \"payout\"\n                        redirect: response.payload.redirect, // this could be different based on what your server is sending as a response.  Expects a URL string.\n                        onComplete: handleWidgetComplete,\n                        onError: handleWidgetError,\n                        // optional parameters\n                        debug: true, \n                        onReady: handleWidgetReady,\n                        flowConfig: {} // see specific flow documentation for supported config values\n                    });\n                })\n                .catch(e => {\n                    console.error('error retrieving redirect payload', e);\n                    // handle error\n                });\n        }\n    \n        window.addEventListener('load', function() {\n            loadWidget();\n            triggerTiliaWidgetFlow();\n        }, false);\n    </script>\n</head>\n<body>\n    <div id=\"my-widget-wrapper\"></div>\n</body>\n</html>\n","lang":"javascript"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-4-handle-the-flow-result","__idx":7},"children":["Step 4: Handle the flow result"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Upon completing the flow, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onComplete"]}," function returns a result. Refer to the flow-specific documentation for details."]}]},"headings":[{"value":"Widget Integration","id":"widget-integration","depth":1},{"value":"To integrate the Tilia widget","id":"to-integrate-the-tilia-widget","depth":2},{"value":"Step 1: User authorization","id":"step-1-user-authorization","depth":3},{"value":"Request body","id":"request-body","depth":4},{"value":"Sample response","id":"sample-response","depth":4},{"value":"Step 2: Add the widget script to your page","id":"step-2-add-the-widget-script-to-your-page","depth":3},{"value":"Step 3: Retrieve redirect url and execute the flow","id":"step-3-retrieve-redirect-url-and-execute-the-flow","depth":3},{"value":"Step 4: Handle the flow result","id":"step-4-handle-the-flow-result","depth":3}],"frontmatter":{"enableToc":false,"seo":{"title":"Widget Integration"}},"lastModified":"2026-02-05T18:12:30.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/web-uis/widget-overview","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}