diff --git a/docs/guides/share/index.mdx b/docs/guides/share/index.mdx
index 5e47c77e..fdfa38af 100644
--- a/docs/guides/share/index.mdx
+++ b/docs/guides/share/index.mdx
@@ -39,12 +39,22 @@ import { Card } from "@site/src/components/shared/Card";
>
Use custom masks to securely display sensitive information.
- }
href="/docs/guides/share/reveal-tokenized-data"
heading="Reveal Tokenized Data"
>
- Use Basis Theory Elements to reveal sensitive data back to customers without touching it.
+ Use Basis Theory Elements to reveal tokenized data back to customers without touching it.
+
+
+ }
+ href="/docs/guides/share/reveal-data-from-third-party"
+ heading="Reveal Data From 3rd Party"
+ >
+ Use Basis Theory Elements to reveal sensitive data from a third party back to customers without touching it.
diff --git a/docs/guides/share/reveal-data-from-third-party.mdx b/docs/guides/share/reveal-data-from-third-party.mdx
new file mode 100644
index 00000000..9dbc0f4c
--- /dev/null
+++ b/docs/guides/share/reveal-data-from-third-party.mdx
@@ -0,0 +1,1025 @@
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+
+import { Alert, Alerts } from "@site/src/components/shared/Alert";
+import { AuthButtons } from "@site/src/components/docs/AuthButtons";
+import { Card } from "@site/src/components/shared/Card"
+
+import styles from "@site/src/pages/index.module.css";
+import ThemedImage from "@theme/ThemedImage";
+
+import Android from "@site/static/img/sdk/logos/android.svg";
+import JavaScript from "@site/static/img/sdk/logos/javascript.svg";
+import ReactSvg from "@site/static/img/sdk/logos/react.svg";
+
+
+# Reveal Data from 3rd Party
+
+This guide will show you how to reveal sensitive data from a third party back to a customer without your frontend or backend code ever needing to touch the actual raw data.
+
+Key concepts in this guide:
+
+- [Applications](/docs/api/applications)
+- [Sessions](/docs/api/applications/sessions)
+- [Proxies](/docs/api/proxies/)
+
+## Getting Started
+
+To get started, you will need a Basis Theory account.
+
+
+
+### Creating a Public Application
+Next you will need a [Public Application](/docs/api/applications#application-types) in order to create tokens, sessions and initialize our Elements libraries.
+
+[Click here](https://portal.basistheory.com/applications/create?permissions=token%3Acreate&type=public&name=Public%20App) to create a Public Application or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings:
+
+- Name - Public App
+- Application Type - Public
+- Permissions - `token:create`
+
+
+ Save the API Key from the created Public Application as it will be used later in this guide.
+
+
+
+## Configuring Basis Theory Elements
+
+[Basis Theory Elements](/docs/concepts/elements) is available for the following technologies. Click below for detailed instructions on how to install and configure it.
+
+
+}
+className={styles.sdk}
+openInNewWindow={true}
+>
+Javascript
+
+
+}
+className={styles.sdk}
+openInNewWindow={true}
+>
+React
+
+
+
+
+
+}
+className={styles.sdk}
+openInNewWindow={true}
+>
+iOS
+
+
+}
+className={styles.sdk}
+openInNewWindow={true}
+>
+Android
+
+
+
+## Creating a Text Element
+
+To safely reveal data back to a customer, we must create an Element that will hold and display the data.
+In this example we'll create a Text Element, which can hold any `string` value.
+
+
+
+
+```javascript showLineNumbers
+import { BasisTheory } from '@basis-theory/basis-theory-js';
+
+let bt;
+//highlight-start
+let textElement;
+//highlight-end
+
+(async () => {
+ bt = await new BasisTheory().init('test_1234567890', { elements: true });
+
+ //highlight-start
+ textElement = bt.createElement('text', {
+ targetId: 'exampleTextElement',
+ });
+
+ // here #exampleTextElement is a DOM selector
+ // example:
+ await textElement.mount('#exampleTextElement');
+ //highlight-end
+})();
+```
+
+
+
+```tsx showLineNumbers
+// highlight-next-line
+import { useRef } from 'react';
+
+import {
+ BasisTheoryProvider,
+ // highlight-next-line
+ TextElement,
+ useBasisTheory,
+} from '@basis-theory/basis-theory-react';
+
+function App() {
+ const { bt } = useBasisTheory('test_1234567890', { elements: true });
+ // highlight-next-line
+ const textRef = useRef(null);
+
+ return (
+
+ // highlight-start
+
+ // highlight-end
+
+ );
+}
+
+export default App;
+```
+
+
+
+```text
+To add a Text Element to your iOS app, you just have to follow these three steps:
+
+1. Drop a UITextField onto your Main.storyboard file and select it.
+2. Select TextElementUITextField as the class for the UITextField.
+3. Add an outlet for your text field to your ViewController.
+```
+
+```swift showLineNumbers title="ViewController.swift"
+import UIKit
+import BasisTheoryElements
+
+class ViewController: UIViewController {
+ // highlight-next-line
+ @IBOutlet weak var exampleTextElement: TextElementUITextField!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+}
+```
+
+
+
+```text
+To add a Text Element to your Android app, you just have to follow these two steps:
+
+1. Add the XML below to your MainActivity layout.
+2. Reference your XML element in the MainActivity class.
+````
+
+```xml title="res/layout/activity_main.xml"
+
+```
+
+```kotlin showLineNumbers title="MainActivity.kt"
+import com.basistheory.android.view.TextElement
+
+class MainActivity : AppCompatActivity() {
+ // highlight-next-line
+ private lateinit var exampleTextElement: TextElement
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ // highlight-next-line
+ exampleTextElement = findViewById(R.id.exampleTextElement)
+ }
+}
+```
+
+
+
+
+
+ Be sure to replace test_1234567890
with the Public API Key you
+ created in Getting Started.
+
+
+## Creating a Session
+
+Next, we'll create a [Session](/docs/api/applications/sessions). Sessions provide temporary elevated access to your public applications,
+and we'll will use it to safely authenticate the request to the third party. Add the following code to create a session:
+
+
+
+
+
+```javascript showLineNumbers
+import { BasisTheory } from '@basis-theory/basis-theory-js';
+
+let bt;
+let textElement;
+
+(async () => {
+ bt = await new BasisTheory().init('test_1234567890', { elements: true });
+
+ textElement = bt.createElement('text', {
+ targetId: 'exampleTextElement',
+ });
+
+ // here #exampleTextElement is a DOM selector
+ // example:
+ await textElement.mount('#exampleTextElement');
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ const reveal = async () => {
+ // highlight-next-line
+ const session = await bt.sessions.create();
+ }
+
+})();
+```
+
+
+
+```tsx showLineNumbers
+
+import { useRef } from 'react';
+
+import {
+ BasisTheoryProvider,
+ TextElement,
+ useBasisTheory,
+} from '@basis-theory/basis-theory-react';
+
+function App() {
+ const { bt } = useBasisTheory('test_1234567890', { elements: true });
+ const textRef = useRef(null);
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ const reveal = async () => {
+ // highlight-next-line
+ const session = await bt.sessions.create();
+ }
+
+ return (
+
+
+
+ );
+}
+
+export default App;
+```
+
+
+
+```swift showLineNumbers
+import UIKit
+import BasisTheoryElements
+
+class ViewController: UIViewController {
+ @IBOutlet weak var exampleTextElement: TextElementUITextField!
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ func reveal() {
+ //highlight-start
+ BasisTheoryElements.createSession(apiKey: btPublicKey) { data, error in
+ let sessionKey = data!.sessionKey!
+ let nonce = data!.nonce!
+
+ }
+ //highlight-end
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+}
+```
+
+
+
+```kotlin showLineNumbers
+import com.basistheory.android.view.TextElement
+//highlight-next-line
+import com.basistheory.android.service.BasisTheoryElements
+
+class MainActivity : AppCompatActivity() {
+
+ private lateinit var exampleTextElement: TextElement
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ exampleTextElement = findViewById(R.id.example_text_element)
+ }
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ private fun reveal() {
+ //highlight-start
+ val bt = BasisTheoryElements.builder()
+ .apiKey("test_1234567890")
+ .build()
+ //highlight-end
+
+ // highlight-next-line
+ val session = bt.createSession()
+ }
+}
+```
+
+
+
+## Creating a Pre-Configured Proxy
+
+To retrieve data from a third party URL without touching it, we will create a [Pre-Configured Proxy](/docs/api/proxies/pre-configured-proxies)
+
+### Creating a Management Application
+
+To create a proxy, you will need a [Management Application](docs/api/applications#application-types).
+
+[Click here](https://portal.basistheory.com/applications/create?permissions=proxy%3Acreate&type=management&name=Management%20App) to create a Management Application or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings:
+
+- Name - Create Proxy
+- Application Type - Management
+- Permissions: `proxy: create`
+
+
+### Creating the Proxy in the Backend
+
+In this guide, we'll use [Express.js](https://expressjs.com/) as our backend but [docs](docs/api/) are available for different technologies.
+We'll create a `backend.js` file and add the following code to start the Express.js backend and create a proxy to the third party:
+
+```javascript showLineNumbers title="backend.js"
+const express = require("express");
+const { BasisTheory } = require("@basis-theory/basis-theory-js");
+
+const app = express();
+const port = 4242;
+
+let bt = await new BasisTheory().init();
+
+app.post("/create-proxy", async (request, response) => {
+ const proxy = await bt.proxies.create(
+ {
+ name: "Proxy to Third Party",
+ destinationUrl: "http://third_party_url.com",
+ requestTransform: {
+ code: `module.exports = async function (req) {
+ let { args: { body, headers }, bt } = req;
+
+ return {
+ body,
+ headers: {
+ ...headers,
+ "Authorization": req.configuration.Credentials
+ },
+ }
+ };`,
+ },
+ configuration: {
+ Credentials: "credential_1234567890"
+ },
+ requireAuth: true,
+ },
+ { apiKey: "test_mgmt_1234567890" } // management application
+ );
+
+ response.send(proxy);
+});
+
+app.listen(port, () => {
+ console.log(`Example app listening on port ${port}`);
+});
+```
+
+Notice that we are using a [request transform](/docs/api/proxies/pre-configured-proxies#request-transforms) to add the third party credentials to the `Authorization` header before making the request to the third party.
+These kind of values can be safely stored in the `configuration` object and re-use them for every proxy execution.
+
+
+Start the server with the following command (from the same directory as `backend.js`).
+
+``` bash
+node backend.js
+```
+
+You can now use your favorite API client or just run the following `curl` command from your terminal:
+
+```shell
+curl -X POST http://localhost:4242/create-proxy
+```
+
+
+ Be sure to replace test_mgmt_1234567890
with the Management API Key you
+ created in Creating a Management Application, http://third_party_url.com
with the third party URL and credential_1234567890
with the third party credentials (optionally).
+
+
+
+ Write down the key
value returned from the proxy as its going to be used in the next steps.
+
+
+
+## Authorizing a Session
+
+In order to use the session to securely invoke our proxy, we need to authorize it with a Private Application.
+
+### Creating a Private Application
+
+First, lets create the [Private Application](docs/api/applications#application-types). To do so [Click here](https://portal.basistheory.com/applications/create?permissions=token%3Ause&type=private&name=Invoke%20Proxy) or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings:
+
+- Name - Invoke Proxy
+- Application Type - Private
+- Permissions - `token:use`
+
+
+ The Private Application must be in the same Tenant as Public Application used to create the Session.
+
+
+
+ Save the API Key from the created Private Application as it will be used later in this guide.
+
+
+### Authorizing In the Backend
+
+Using the Private Application API Key and the `nonce` from our session we can grant temporary authorization to invoke the proxy.
+
+
+The only way to ensure your private API keys are not publically accessible is for this step to execute in your backend service.
+
+
+```javascript showLineNumbers title="backend.js"
+const express = require("express");
+const { BasisTheory } = require("@basis-theory/basis-theory-js");
+
+const app = express();
+const port = 4242;
+
+let bt = await new BasisTheory().init();
+
+app.post("/create-proxy", async (request, response) => {
+ const proxy = await bt.proxies.create(
+ {
+ name: "Proxy to Third Party",
+ destinationUrl: "http://third_party_url.com",
+ requestTransform: {
+ code: `module.exports = async function (req) {
+ let { args: { body, headers }, bt } = req;
+
+ return {
+ body,
+ headers: {
+ ...headers,
+ "Authorization": req.configuration.Credentials
+ },
+ }
+ };`,
+ },
+ configuration: {
+ Credentials: "credential_1234567890"
+ },
+ requireAuth: true,
+ },
+ { apiKey: "test_mgmt_1234567890" } // management application
+ );
+
+ response.send(proxy);
+});
+
+//highlight-start
+app.post("/authorize", async (request, response) => {
+ const { nonce } = request.body;
+
+ // authorizing a session returns an empty 200 response
+ await bt.sessions.authorize({
+ nonce: nonce,
+ permissions: ['token:use']
+ }, { apiKey: "test_priv_1234567890" }); // private application
+
+ // this response is arbitrary and not required
+ response.json({
+ result: "success",
+ });
+});
+//highlight-end
+
+app.listen(port, () => {
+ console.log(`Example app listening on port ${port}`);
+});
+```
+
+
+ Be sure to replace test_priv_1234567890
with the Private API Key you
+ created in the Creating a Private Application step.
+
+
+
+ In a real world scenario, make sure to include your own form of authentication between your frontend and backend for this request.
+
+
+### Calling the Authorization Endpoint
+
+Next, from our client application, we'll call the authorization endpoint created on the [Authorizing in the Backend](docs/guides/share/reveal-data-from-third-party#authorizing-in-the-backend) step, passing our created session `nonce`:
+
+
+
+
+
+```javascript showLineNumbers
+import { BasisTheory } from '@basis-theory/basis-theory-js';
+
+let bt;
+let textElement;
+
+(async () => {
+ bt = await new BasisTheory().init('test_1234567890', { elements: true });
+
+ textElement = bt.createElement('text', {
+ targetId: 'exampleTextElement',
+ });
+
+ // here #exampleTextElement is a DOM selector
+ // example:
+ await textElement.mount('#exampleTextElement');
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ const reveal = async () => {
+ const session = await bt.sessions.create();
+
+ // highlight-start
+ await fetch('http://localhost:4242/authorize', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({ nonce: session.nonce }),
+ });
+ // highlight-end
+ }
+})();
+```
+
+
+
+```tsx showLineNumbers
+
+import { useRef } from 'react';
+
+import {
+ BasisTheoryProvider,
+ TextElement,
+ useBasisTheory,
+} from '@basis-theory/basis-theory-react';
+
+function App() {
+ const { bt } = useBasisTheory('test_1234567890', { elements: true });
+ const textRef = useRef(null);
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ const reveal = async () => {
+ const session = await bt.sessions.create();
+
+ // highlight-start
+ await fetch('http://localhost:4242/authorize', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({ nonce: session.nonce }),
+ });
+ // highlight-end
+ }
+
+ return (
+
+
+
+ );
+}
+
+export default App;
+```
+
+
+
+```swift showLineNumbers
+import UIKit
+import BasisTheoryElements
+
+class ViewController: UIViewController {
+ @IBOutlet weak var exampleTextElement: TextElementUITextField!
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ func reveal() {
+ BasisTheoryElements.createSession(apiKey: btPublicKey) { data, error in
+ let sessionKey = data!.sessionKey!
+ let nonce = data!.nonce!
+
+ //highlight-start
+ self.authorizeSession(nonce: nonce) { result, error in
+ //
+ }
+ //highlight-end
+ }
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+
+ //highlight-start
+ func authorizeSession(nonce: String, completion: @escaping ([String: Any]?, Error?) -> Void) {
+ let parameters = ["nonce": nonce]
+
+ let url = URL(string: "http://localhost:4242/authorize")!
+ let session = URLSession.shared
+
+ var request = URLRequest(url: url)
+ request.httpMethod = "POST"
+
+ do {
+ request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
+ } catch let error {
+ completion(nil, error)
+ }
+
+ request.addValue("application/json", forHTTPHeaderField: "Content-Type")
+ request.addValue("application/json", forHTTPHeaderField: "Accept")
+
+ let task = session.dataTask(with: request, completionHandler: { data, response, error in
+ guard error == nil else {
+ completion(nil, error)
+ return
+ }
+
+ do {
+ let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any]
+ completion(json, nil)
+ } catch let error {
+ completion(nil, error)
+ }
+ })
+
+ task.resume()
+ }
+ //highlight-end
+}
+```
+
+
+
+```kotlin showLineNumbers
+import com.basistheory.android.view.TextElement
+import com.basistheory.android.service.BasisTheoryElements
+//highlight-start
+import java.net.HttpURLConnection
+import java.net.URL
+//highlight-end
+
+class MainActivity : AppCompatActivity() {
+
+ private lateinit var exampleTextElement: TextElement
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ exampleTextElement = findViewById(R.id.example_text_element)
+ }
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ private fun reveal() {
+ val bt = BasisTheoryElements.builder()
+ .apiKey("test_1234567890")
+ .build()
+
+ val session = bt.createSession()
+
+ //highlight-next-line
+ authorizeSession(session.sessionKey)
+ }
+
+ //highlight-start
+ private fun authorizeSession(nonce: String) {
+ val url = URL("http://localhost:4242/authorize")
+ val con = url.openConnection() as HttpURLConnection
+
+ con.requestMethod = "POST"
+ con.doOutput = true
+ con.setRequestProperty("Content-Type", "application/json")
+ con.setRequestProperty("Accept", "application/json");
+
+ val body = String.format("{\"nonce\": \"%s\"}", nonce)
+
+ con.outputStream.use { os ->
+ val input: ByteArray = body.toByteArray(Charsets.UTF_8)
+ os.write(input, 0, input.size)
+ }
+
+ if (con.responseCode == 200) {
+ return
+ }
+ }
+ //highlight-end
+}
+```
+
+
+
+## Invoking the Proxy and Revealing the Data
+
+With the authorized session, we can now use the `sessionKey` to invoke our created proxy.
+We'll add the following code to retrieve the data and set its value to the text element.
+
+
+
+
+
+```javascript showLineNumbers
+import { BasisTheory } from "@basis-theory/basis-theory-js";
+
+let bt;
+let textElement;
+
+(async () => {
+ bt = await new BasisTheory().init("test_1234567890", { elements: true });
+
+ textElement = bt.createElement("text", {
+ targetId: "exampleTextElement",
+ });
+
+ // here #exampleTextElement is a DOM selector
+ // example:
+ await textElement.mount("#exampleTextElement");
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ const reveal = async () => {
+ const session = await bt.sessions.create();
+
+ await fetch("http://localhost:4242/authorize", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ nonce: session.nonce }),
+ });
+
+ // highlight-start
+ const data = await bt.proxy.get({
+ headers: {
+ "BT-PROXY-KEY": "proxy_key_1234567890"
+ },
+ apiKey: session.sessionKey,
+ });
+ // highlight-end
+
+ //highlight-next-line
+ textElement.setValue(data);
+ };
+})();
+```
+
+
+
+```tsx showLineNumbers
+
+import { useRef } from 'react';
+
+import {
+ BasisTheoryProvider,
+ TextElement,
+ useBasisTheory,
+} from '@basis-theory/basis-theory-react';
+
+function App() {
+ const { bt } = useBasisTheory('test_1234567890', { elements: true });
+ const textRef = useRef(null);
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ const reveal = async () => {
+ const session = await bt.sessions.create();
+
+ await fetch('http://localhost:4242/authorize', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({ nonce: session.nonce }),
+ });
+
+ // highlight-start
+ const data = await bt.proxy.get({
+ headers: {
+ "BT-PROXY-KEY": "proxy_key_1234567890"
+ },
+ apiKey: session.sessionKey,
+ });
+ // highlight-end
+
+ //highlight-next-line
+ textElement.setValue(data);
+ }
+
+ return (
+
+
+
+ );
+}
+
+export default App;
+```
+
+
+
+```swift showLineNumbers
+import UIKit
+import BasisTheoryElements
+
+class ViewController: UIViewController {
+ @IBOutlet weak var exampleTextElement: TextElementUITextField!
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ func reveal() {
+ BasisTheoryElements.createSession(apiKey: btPublicKey) { data, error in
+ let sessionKey = data!.sessionKey!
+ let nonce = data!.nonce!
+
+
+ self.authorizeSession(nonce: nonce) { result, error in
+ //highlight-start
+ let proxyHttpRequest = ProxyHttpRequest(method: .get, path: String("/" + issuerCardId))
+ BasisTheoryElements.proxy(apiKey: sessionKey, proxyKey: "proxy_key_1234567890", proxyHttpRequest: proxyHttpRequest)
+ { response, data, error in
+ DispatchQueue.main.async {
+ self.cardVerificationCodeElement.setValue(elementValueReference: data!.cvv!.elementValueReference)
+ }
+ }
+ //highlight-end
+ }
+ }
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+
+ func authorizeSession(nonce: String, completion: @escaping ([String: Any]?, Error?) -> Void) {
+ let parameters = ["nonce": nonce]
+
+ let url = URL(string: "http://localhost:4242/authorize")!
+ let session = URLSession.shared
+
+ var request = URLRequest(url: url)
+ request.httpMethod = "POST"
+
+ do {
+ request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
+ } catch let error {
+ completion(nil, error)
+ }
+
+ request.addValue("application/json", forHTTPHeaderField: "Content-Type")
+ request.addValue("application/json", forHTTPHeaderField: "Accept")
+
+ let task = session.dataTask(with: request, completionHandler: { data, response, error in
+ guard error == nil else {
+ completion(nil, error)
+ return
+ }
+
+ do {
+ let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: Any]
+ completion(json, nil)
+ } catch let error {
+ completion(nil, error)
+ }
+ })
+
+ task.resume()
+ }
+}
+```
+
+
+
+```kotlin showLineNumbers
+import com.basistheory.android.view.TextElement
+import com.basistheory.android.service.BasisTheoryElements
+import java.net.HttpURLConnection
+import java.net.URL
+//highlight-next-line
+import com.basistheory.android.service.ProxyRequest
+
+class MainActivity : AppCompatActivity() {
+
+ private lateinit var exampleTextElement: TextElement
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ exampleTextElement = findViewById(R.id.example_text_element)
+ }
+
+ // this is just an example method that'll have the full lifecycle for revealing
+ private fun reveal() {
+ val bt = BasisTheoryElements.builder()
+ .apiKey("test_1234567890")
+ .build()
+
+ val session = bt.createSession()
+
+ authorizeSession(session.nonce)
+
+ //highlight-start
+ val proxyRequest: ProxyRequest = ProxyRequest().apply {
+ headers = mapOf(
+ "BT-PROXY-KEY" to "proxy_key_1234567890",
+ "Content-Type" to "application/json"
+ )
+ }
+ val data = bt.proxy.get(proxyRequest, session.sessionKey)
+ //highlight-end
+
+ //highlight-next-line
+ exampleTextElement.setValueRef(data)
+ }
+
+ private fun authorizeSession(nonce: String) {
+ val url = URL("http://localhost:4242/authorize")
+ val con = url.openConnection() as HttpURLConnection
+
+ con.requestMethod = "POST"
+ con.doOutput = true
+ con.setRequestProperty("Content-Type", "application/json")
+ con.setRequestProperty("Accept", "application/json");
+
+ val body = String.format("{\"nonce\": \"%s\"}", nonce)
+
+ con.outputStream.use { os ->
+ val input: ByteArray = body.toByteArray(Charsets.UTF_8)
+ os.write(input, 0, input.size)
+ }
+
+ if (con.responseCode == 200) {
+ return
+ }
+ }
+}
+```
+
+
+
+🎉 The code above is the last bit that we need to reveal data from a third party!
+
+
+
+ The data
you receive as response from the proxy is not the raw data, but a synthetic reference to it that can only be used with setValue
to display it.
+
+
+## Conclusion
+
+You can now reveal any data to a customer without your application accessing the underlying value, reducing compliance and regulatory scope.
+Just execute the `reveal` method in whichever way you desire (like with the click of a button) and watch the response value from the proxy appear on your Text Element.
+
+## Learn More
+
+- [Customize your web form](/docs/guides/collect/customize-web-form)
+- [Access data using sessions](/docs/guides/govern/sessions)
+- [Reveal tokenized data](/docs/guides/share/reveal-tokenized-data)
diff --git a/docs/guides/share/reveal-tokenized-data.mdx b/docs/guides/share/reveal-tokenized-data.mdx
index 76401b31..efdb83ed 100644
--- a/docs/guides/share/reveal-tokenized-data.mdx
+++ b/docs/guides/share/reveal-tokenized-data.mdx
@@ -33,7 +33,7 @@ To get started, you will need a Basis Theory account.
### Creating a Public Application
Next you will need a [Public Application](/docs/api/applications#application-types) in order to create tokens, sessions and initialize our Elements libraries.
-[Click here](https://portal.basistheory.com/applications/create?permissions=token%3Acreate&type=public&name=Collect%20Data%20from%20Web%20Guide) to create a Public Application or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings:
+[Click here](https://portal.basistheory.com/applications/create?permissions=token%3Acreate&type=public&name=Public%20App) to create a Public Application or [login to your Basis Theory account](https://portal.basistheory.com/applications) and create a new application with the following settings:
- Name - Public App
- Application Type - Public
@@ -203,6 +203,8 @@ To add a Text Element to your Android app, you just have to follow these two ste
```
```kotlin showLineNumbers title="MainActivity.kt"
+import com.basistheory.android.view.TextElement
+
class MainActivity : AppCompatActivity() {
// highlight-next-line
private lateinit var exampleTextElement: TextElement
@@ -325,6 +327,9 @@ class ViewController: UIViewController {
```kotlin showLineNumbers
+import com.basistheory.android.view.TextElement
+//highlight-next-line
+import com.basistheory.android.service.BasisTheoryElements
class MainActivity : AppCompatActivity() {
private lateinit var exampleTextElement: TextElement
@@ -338,6 +343,12 @@ class MainActivity : AppCompatActivity() {
// this is just an example method that'll have the full lifecycle for revealing
private fun reveal() {
+ //highlight-start
+ val bt = BasisTheoryElements.builder()
+ .apiKey("test_1234567890")
+ .build()
+ //highlight-end
+
// highlight-next-line
val session = bt.createSession()
}
@@ -591,6 +602,8 @@ class ViewController: UIViewController {
```kotlin showLineNumbers
+import com.basistheory.android.view.TextElement
+import com.basistheory.android.service.BasisTheoryElements
//highlight-start
import java.net.HttpURLConnection
import java.net.URL
@@ -609,6 +622,10 @@ class MainActivity : AppCompatActivity() {
// this is just an example method that'll have the full lifecycle for revealing
private fun reveal() {
+ val bt = BasisTheoryElements.builder()
+ .apiKey("test_1234567890")
+ .build()
+
val session = bt.createSession()
//highlight-next-line
@@ -816,6 +833,8 @@ class ViewController: UIViewController {
```kotlin showLineNumbers
+import com.basistheory.android.view.TextElement
+import com.basistheory.android.service.BasisTheoryElements
import java.net.HttpURLConnection
import java.net.URL
@@ -832,6 +851,10 @@ class MainActivity : AppCompatActivity() {
// this is just an example method that'll have the full lifecycle for revealing
private fun reveal() {
+ val bt = BasisTheoryElements.builder()
+ .apiKey("test_1234567890")
+ .build()
+
val session = bt.createSession()
authorizeSession(session.nonce)
@@ -874,6 +897,7 @@ class MainActivity : AppCompatActivity() {
You can now reveal any data to a customer without your application accessing the underlying value, reducing compliance and regulatory scope.
Just execute the `reveal` method in whichever way you desire (like with the click of a button) and watch the token value appear on your Text Element.
+If you need to reveal data stored outside of Basis Theory in a similar manner, check our [Reveal Data from 3rd Party](/docs/guides/share/reveal-data-from-third-party) guide.
## Learn More
diff --git a/sidebars.js b/sidebars.js
index d03ac6e3..4e53f5d0 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -62,7 +62,8 @@ const sidebars = {
items: [
"guides/share/send-data-to-third-party",
"guides/share/display-masked-data",
- "guides/share/reveal-tokenized-data"
+ "guides/share/reveal-tokenized-data",
+ "guides/share/reveal-data-from-third-party"
],
},
{
diff --git a/src/components/shared/Card.tsx b/src/components/shared/Card.tsx
index 22ade09e..8f0afb23 100644
--- a/src/components/shared/Card.tsx
+++ b/src/components/shared/Card.tsx
@@ -30,6 +30,7 @@ interface Card {
hoverable?: boolean;
cta?: React.ReactNode;
column?: boolean;
+ openInNewWindow: boolean;
}
const Card = ({
@@ -42,6 +43,7 @@ const Card = ({
cta,
hoverable = true,
column = false,
+ openInNewWindow = false,
...otherProps
}: PropsWithChildren<
DetailedHTMLProps, HTMLDivElement> & Card
@@ -53,7 +55,7 @@ const Card = ({
? (e) => {
e.preventDefault();
- if (href.startsWith("https")) {
+ if (href.startsWith("https") || openInNewWindow) {
window.open(href, "_blank");
} else {
history.push(href);