> ## Documentation Index
> Fetch the complete documentation index at: https://docs.synctera.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Card Widgets

> With the Card Widgets, your customers can view and interact with sensitive card information inside the application.

Since these widgets communicate directly between the client, card vendor and Synctera, they remove the need for the integrator to be PCI certified.

<Info>
  This is a short-term solution. We are currently advancing this functionality to make it more customizable and easier to integrate with.
</Info>

Through the [marqeta.js client library](https://www.marqeta.com/docs/developer-guides/using-marqeta-js), you can display the following pieces of sensitive card information for a customer inside your application:

* **PAN** (primary account number)
* **CVV** (card verification value)
* **EXP** (expiration date)
* **PIN** (the card pin - *v2.0.0+*)

<CardGroup>
  <Frame>
    <img src="https://mintcdn.com/synctera/iG0lA_rrddf7APRb/images/docs/9c0e357-card-widgets-card-front.svg?fit=max&auto=format&n=iG0lA_rrddf7APRb&q=85&s=e12009e2bb870de75a28d311a844747a" alt="Card Front" width="316" height="197" data-path="images/docs/9c0e357-card-widgets-card-front.svg" />
  </Frame>

  <Frame>
    <img src="https://mintcdn.com/synctera/iG0lA_rrddf7APRb/images/docs/80afa9e-card-widgets-card-back.svg?fit=max&auto=format&n=iG0lA_rrddf7APRb&q=85&s=3a13c727f63e6b59770e31df07e96a4e" alt="Card Back" width="319" height="196" data-path="images/docs/80afa9e-card-widgets-card-back.svg" />
  </Frame>
</CardGroup>

Through the [Activate Card and Set PIN Widgets](https://www.marqeta.com/docs/developer-guides/using-activate-card-and-set-pin-widgets), you can interact with your card to activate it or to set card's PIN:

* [**Activate Card**](https://www.marqeta.com/docs/developer-guides/using-activate-card-and-set-pin-widgets) (activates a physical card by entering in the card number and CVV)
* [**Set PIN**](https://www.marqeta.com/docs/developer-guides/using-activate-card-and-set-pin-widgets) (sets the Card PIN for a newly activated card)

<CardGroup>
  <Frame>
    <img src="https://mintcdn.com/synctera/iG0lA_rrddf7APRb/images/docs/e7dbf89-card-widgets-activate-card.svg?fit=max&auto=format&n=iG0lA_rrddf7APRb&q=85&s=b1f9ae33e0de82188b53823aa7820208" alt="Activate Card" width="350" height="285" data-path="images/docs/e7dbf89-card-widgets-activate-card.svg" />
  </Frame>

  <Frame>
    <img src="https://mintcdn.com/synctera/iG0lA_rrddf7APRb/images/docs/a3fc9e8-card-widgets-set-pin.svg?fit=max&auto=format&n=iG0lA_rrddf7APRb&q=85&s=6deecd48da4a86899c959d64967dd8c5" alt="Set PIN" width="344" height="279" data-path="images/docs/a3fc9e8-card-widgets-set-pin.svg" />
  </Frame>
</CardGroup>

## Getting Started

Make sure you've got the necessary components in place before integrating widgets with your application.

### API Keys

First, ensure you have your [Synctera API Keys](/docs/dev-setup#sign-up-for-a-synctera-account-and-generate-api-keys) working for your business.

### Mobile applications

If you're integrating the widgets in a mobile application, you may need to use one of the following web views:

<CardGroup>
  <Card title="WKWebView in an iOS application" href="https://developer.apple.com/documentation/webkit/wkwebview" icon="apple" iconType="brands" horizontal />

  <Card title="WebView in an android application" href="https://developer.android.com/guide/webapps/webview" icon="android" iconType="brands" horizontal />

  <Card title="WebView in React Native" href="https://github.com/react-native-webview/react-native-webview" icon="react" iconType="brands" horizontal />
</CardGroup>

## Upgrading from Marqeta 1.1.0 to 2.0.0

To take advantage of the PIN reveal feature, you will need to upgrade from Marqeta 1.1.0 to 2.0.0. If you already implemented the Marqeta widget, read this section to quickly upgrade.

1. Replace `https://widgets.marqeta.com/marqetajs/1.1.0/marqeta.min.js` with `https://widgets.marqeta.com/marqetajs/2.0.0/marqeta.min.js`

2. For the config passed to `window.marqeta.bootstrap({ .... })`, the "showPan" field needs to wrapped in a "component" field:

<CodeGroup>
  ```js JavaScript theme={"system"}
     window.marqeta.bootstrap({
       ....
       component: {
          showPan: {
             cardPan: { domId: "display-card-pan", format: true },
             cardExp: { domId: "display-card-exp", format: true },
             cardCvv: { domId: "display-card-cvv" },
          },
       },
       ....
     });
  ```
</CodeGroup>

That's it!

## Display Card PAN, CVV, and EXP

<Info>
  Refer to Marqeta’s guide [Using Marqeta.js](https://www.marqeta.com/docs/developer-guides/using-marqeta-js) for additional information on the widget configuration and styling.
</Info>

The steps below describe how the application uses a client access token to show PAN, CVV and Card EXP using the marqeta.js client library:

1. Load `marqeta.js` into the window object of the browser by adding the following script into the `<head>` tag of the required page:

   <CodeGroup>
     ```html HTML theme={"system"}
     <script
       src="https://widgets.marqeta.com/marqetajs/2.0.0/marqeta.min.js"
       type="text/javascript"
     ></script>
     ;
     ```
   </CodeGroup>

2. Request a client access token for a card from Synctera via the POST request for [/cards/\{card\_id}/client\_token](/reference/getclientaccesstoken) endpoint. Pass `clientAccessToken` to your front-end via SSR or HTTP request. This token expires after five minutes and is only applicable to the given card, so it's a good idea to create a client access token on every page load:

   <CodeGroup>
     ```bash Bash theme={"system"}
     curl -X POST "https://api-sandbox.synctera.com/v0/cards/{cardId}/client_token" -H "Content-Length: 0" -H "Authorization: Bearer {apiKey}"

     {"client_token": ... }
     ```
   </CodeGroup>

3. Add a separate HTML `div` element to your client page per each piece of the sensitive card data (Card PAN, Card CVV, Card EXP). You can attach this information to any HTML container:

<CodeGroup>
  ```html HTML theme={"system"}
  <!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="utf-8" />
      <title>Synctera</title>
      <script
        src="https://widgets.marqeta.com/marqetajs/2.0.0/marqeta.min.js"
        type="text/javascript"
      ></script>
    </head>
    <body>
      <!-- each piece of sensitive information must have have it's
    own div -->
      <div id="display-card-pan"></div>
      <div id="display-card-cvv"></div>
      <div id="display-card-exp"></div>
    </body>
  </html>
  ```
</CodeGroup>

4. Initialize `marqeta.js` via bootstrap with token by calling `window.marqeta.bootstrap`. It will create an HTML iframe element inside each HTML `div` element. You can style the `div` elements and inner contents for the *card PAN*, *card CVV*, *card EXP* containers. To do so, use the `showPan` object as described in [Using Marqeta.js > The showPan object](https://www.marqeta.com/docs/developer-guides/using-marqeta-js#_the_showpan_object):

   <CodeGroup>
     ```js JavaScript theme={"system"}
     window.marqeta.bootstrap({
       clientAccessToken: clientAccessToken,
       integrationType: "custom",
       component: {
         showPan: {
           cardPan: { domId: "display-card-pan", format: true },
           cardExp: { domId: "display-card-exp", format: true },
           cardCvv: { domId: "display-card-cvv" },
         },
       },
       callbackEvents: {
         onSuccess: () => console.log("Widget loaded!"),
         onFailure: () => console.warn("Widget failed to load."),
       },
     });
     ```
   </CodeGroup>

```mermaid theme={"system"}
sequenceDiagram
  participant IFE as Integrator Frontend
  participant MFE as Marqeta.js
  participant IBE as Integrator Backend
  participant S as Synctera API
  participant M as Marqeta
  IFE ->> IBE: Request client access token
  IBE ->> S: POST /v0/cards/:card_id/client_token
  S ->> M: Get token
  M -->> S: Token
  S -->> IBE: Response with client_token
  IBE -->> IFE: Client access token
  IFE ->> MFE: Marqeta.js display card PAN, CVV, and EXP
  MFE ->> M: Request sensitive card data
  M -->> MFE: Response with sensitive card data
  MFE ->> MFE: Render sensitive card data
```

## Display Card PIN

1. Follow the first two steps from [Display Card PAN, CVV, and EXP](#display-card-pan-cvv-and-exp).

<Warning>
  Loading the PIN must be done in its own call to `window.marqeta.boostrap`, however you may call two instances simultaneously.
</Warning>

2. Add separate HTML elements to your client page for the card PIN (see example). You can attach this information to any HTML container:

<CodeGroup>
  ```html HTML theme={"system"}
  <!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="utf-8" />
      <title>Synctera</title>
      <script
        src="https://widgets.marqeta.com/marqetajs/2.0.0/marqeta.min.js"
        type="text/javascript"
      ></script>
    </head>
    <body>
      <!-- PIN provides three different features -->
      <span>
        <div id="display-card-pin"></div>
        <button id='toggle-card-pin'>Toggle</button>
        <div id='pin-timeout'></div>
      </span>
    </body>
  </html>
  ```
</CodeGroup>

3. Initialize `marqeta.js` via bootstrap with token by calling `window.marqeta.bootstrap`. It will create an HTML iframe element inside each HTML element. You can style the elements and inner contents for the *card PIN* containers. To do so, use the `pinReveal` object as described in [Using Marqeta.js > The pinReveal object](https://www.marqeta.com/docs/developer-guides/using-marqeta-js#_the_pinreveal_object):

   <CodeGroup>
     ```js js theme={"system"}
     window.marqeta.bootstrap({
       clientAccessToken: clientAccessToken,
       integrationType: "custom",
       component: {
         pinReveal: {
           cardPin: { domId: "display-card-pin" },
           toggleCardPin: { domId: "toggle-card-pin", mode: "transparent" },
           hidePinTimeout: {
             domId: "pin-timeout",
             hideTimeout: 10, // A value between 5 and 15
             styles: {}, // Requires styles object, can be empty
           },
         },
       },
       callbackEvents: {
         onSuccess: () => console.log("Widget loaded!"),
         onFailure: () => console.warn("Widget failed to load."),
       },
     });
     ```
   </CodeGroup>

## Display Activate Card and Set PIN Widgets

The **Activate Card** widget and **Set PIN** widget are displayed inside HTML iframe elements, with source URLs provided by the `/cards/card_widget_url` route.

<Info>
  Refer to Marqeta’s guide[ Using Activate Card and Set PIN Widgets](https://www.marqeta.com/docs/developer-guides/using-activate-card-and-set-pin-widgets) for additional information.
</Info>

1. Fetch the card widget URL from the related endpoint. On the server, make a request to `/cards/card_widget_url`. For the **Activate Card** widget (widget\_type === 'activate\_card'), you can omit the `card_id` param in the query:

   <CodeGroup>
     ```bash Bash theme={"system"}
     curl -X GET "https://api-sandbox.synctera.com/v0/cards/card_widget_url?card_id={cardId}&customer_id={customerId}&account_id={accountId}&widget_type={widgetType}" -H "Content-Type: application/json" -H "Authorization: Bearer {apiKey}"

     {"url": ... }
     ```
   </CodeGroup>

2. Pass the acquired URL to your front-end via SSR or HTTP request. Include the URL into an iframe on your client page. The desired widget will be rendered inside the iframe, allowing the user to input either *card PAN* or *card PIN* and press submit:

<CodeGroup>
  ```html HTML theme={"system"}
  <!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="utf-8" />
      <title>Synctera</title>
    </head>
    <body>
      <iframe
        src="{cardWidgetUrl}"
        title="Card
      Widget Url"
      />
    </body>
  </html>
  ```
</CodeGroup>

```mermaid theme={"system"}
sequenceDiagram
  participant IFE as Integrator Frontend
  participant IBE as Integrator Backend
  participant S as Synctera API
  participant M as Marqeta
  IFE ->> IBE: Request card widget
  IBE ->> S: GET /v0/cards/card_widget_url
  S ->> M: Get card widget URL
  M -->> S: Card widget URL
  S -->> IBE: Response with card_widget_url
  IBE -->> IFE: Card widget URL
  IFE ->> IFE: Render Activate Card or Set PIN widget
```

## Additional Information

As of version 2.0.0 of the Marqeta library allows for some customization of the fields' appearances, including the css hover state. Supported CSS attributes generally include: `color`, `font-family`, `font-size`, `background`, `font-weight` and `letter-spacing`.

For the particulars on stying, please review the [Using Marqeta.js > Concepts](https://www.marqeta.com/docs/developer-guides/using-marqeta-js#_concepts)

(From Marqeta's documentation: *"CSS importing schemes such as @import and @url are not supported. Marqeta.js only supports web-safe/system fonts that can be displayed on modern web browsers without a specific download."*)

We use Typescript at Synctera and find it helpful to type our window properties. See the example typescript below for the `window.marqeta` **version 2.0.0** object provided by `marqeta.js`:

```ts TypeScript theme={"system"}
// global.d.ts
declare interface Window {
   marqeta: {
     bootstrap(params: MarqetaShowPanParams | MarqetaPinRevealParams): void;
   }
}

// marqeta.d.ts
interface MarqetaBaseParams {
  clientAccessToken: string;
  options?: {
     // Must be included if using PIN reveal
    cardholderVerificationMethod: 'OTHER';
  };
  integrationType: 'custom';
  callbackEvents?: {
    onSuccess?: () => void;
    onFailure: () => void;
  };
}

export interface MarqetaShowPanParams extends MarqetaBaseParams {
  component: {
    showPan: {
      cardPan?: MarqetaShowItem;
      cardExp?: MarqetaShowItem;
      cardCvv?: Omit<MarqetaShowItem, 'format'>;
    };
    pinReveal?: undefined;
  };
}

export interface MarqetaPinRevealParams extends MarqetaBaseParams {
  component: {
    showPan?: undefined;
    pinReveal: {
      cardPin: Omit<MarqetaShowItem, 'format'>;
      toggleCardPin?: {
        domId: string;
        mode: 'transparent';
        onRevealSuccess?: () => void;
        onHideSuccess?: () => void;
      };
      hidePinTimeout?: {
        domId: string;
        hideTimeout: 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15;
        styles: CSSProperties;
        onSuccess?: () => void;
        onFailure?: () => void;
      };
    };
  };
}

export interface MarqetaShowItem {
  domId: string;
  format?: boolean;
  styles?: {
    span?: CSSProperties;
    'span:hover'?: CSSProperties;
  };
  mode?: 'transparent';
  onCopySuccess?: () => void;
  onCopyFailure?: () => void;
}
```
