> ## 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.

# Migration Guide: Marqeta to Synctera

> Step-by-step guide to migrate from Marqeta widgets to Synctera widgets.

If you are currently using Marqeta widgets for **Activate Card** or **Set PIN** functionality, follow this guide to migrate to Synctera widgets.

<Info>
  For **Reveal Card** functionality (displaying PAN, CVV, and expiration date), the [Synctera Reveal Card Widget](/v2/docs/card-widgets-reveal) is now available.

  For **PIN reveal** functionality (the legacy Marqeta `pinReveal` flow), the [Synctera Reveal PIN Widget](/v2/docs/card-widgets-reveal-pin) is now available — see its [migration table](/v2/docs/card-widgets-reveal-pin#migration-from-marqeta-pin-reveal).
</Info>

## Activate Card Migration

### API Changes

| Marqeta (Old)                                             | Synctera (New)                                               |
| --------------------------------------------------------- | ------------------------------------------------------------ |
| `GET /v0/cards/card_widget_url?widget_type=activate_card` | `POST /v1/cards/{card_id}/widget_token?widget_type=ACTIVATE` |
| Returns `{ url: "..." }`                                  | Returns `{ widget_token: "..." }`                            |

### Code Changes

**Before (Marqeta):**

```html theme={"system"}
<!-- Fetch widget URL from your backend -->
<iframe 
  src="{marqetaWidgetUrl}" 
  title="Activate Card"
  width="400"
  height="300"
/>
```

**After (Synctera):**

```html theme={"system"}
<!-- Load the widget script -->
<script 
  type="module" 
  src="https://assets.synctera.com/widgets/activate/v1.1.1/index.js"
></script>

<!-- Use the web component -->
<activate-card 
  token="{widgetToken}" 
  env="production"
></activate-card>

<script>
  // Handle events
  document.querySelector('activate-card').addEventListener('success', (e) => {
    console.log('Card activated:', e.detail);
  });
</script>
```

### Backend Changes

**Before (Marqeta):**

```javascript theme={"system"}
// Server-side: Get widget URL
const response = await fetch(
  `https://api.synctera.com/v0/cards/card_widget_url?card_id=${cardId}&customer_id=${customerId}&account_id=${accountId}&widget_type=activate_card`,
  {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  }
);
const { url } = await response.json();
// Return URL to frontend
```

**After (Synctera):**

```javascript theme={"system"}
// Server-side: Get widget token
const response = await fetch(
  `https://api.synctera.com/v1/cards/${cardId}/widget_token?widget_type=ACTIVATE`,
  {
    method: 'POST',
    headers: { 
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    }
  }
);
const { widget_token } = await response.json();
// Return token to frontend
```

***

## Set PIN Migration

### API Changes

| Marqeta (Old)                                       | Synctera (New)                                              |
| --------------------------------------------------- | ----------------------------------------------------------- |
| `GET /v0/cards/card_widget_url?widget_type=set_pin` | `POST /v1/cards/{card_id}/widget_token?widget_type=SET_PIN` |
| Returns `{ url: "..." }`                            | Returns `{ widget_token: "..." }`                           |

### Code Changes

**Before (Marqeta):**

```html theme={"system"}
<!-- Fetch widget URL from your backend -->
<iframe 
  src="{marqetaWidgetUrl}" 
  title="Set PIN"
  width="400"
  height="300"
/>
```

**After (Synctera):**

```html theme={"system"}
<!-- Load the widget script -->
<script 
  type="module" 
  src="https://assets.synctera.com/widgets/set-pin/v1.1.1/index.js"
></script>

<!-- Use the web component -->
<set-pin 
  token="{widgetToken}" 
  env="production"
></set-pin>

<script>
  // Handle events
  document.querySelector('set-pin').addEventListener('success', (e) => {
    console.log('PIN set:', e.detail);
  });
</script>
```

### Backend Changes

**Before (Marqeta):**

```javascript theme={"system"}
// Server-side: Get widget URL
const response = await fetch(
  `https://api.synctera.com/v0/cards/card_widget_url?card_id=${cardId}&customer_id=${customerId}&account_id=${accountId}&widget_type=set_pin`,
  {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  }
);
const { url } = await response.json();
// Return URL to frontend
```

**After (Synctera):**

```javascript theme={"system"}
// Server-side: Get widget token
const response = await fetch(
  `https://api.synctera.com/v1/cards/${cardId}/widget_token?widget_type=SET_PIN`,
  {
    method: 'POST',
    headers: { 
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    }
  }
);
const { widget_token } = await response.json();
// Return token to frontend
```

***

## Key Differences

### Event Handling

**Marqeta** widgets used postMessage or URL callbacks. **Synctera** widgets dispatch standard DOM events:

```javascript theme={"system"}
// Synctera widgets use standard DOM events
widget.addEventListener('success', (event) => {
  console.log('Success:', event.detail);
});

widget.addEventListener('failure', (event) => {
  console.error('Error:', event.detail);
});
```

### Customization

**Marqeta** widgets had limited customization. **Synctera** widgets support themes and custom labels:

```html theme={"system"}
<activate-card
  token="..."
  env="production"
  theme="night-shift"
  custom-labels='{
    "widgetTitle": "Activate Your Card",
    "submitButtonText": "Activate Now"
  }'
></activate-card>
```

### Token Expiration

Both widget types use tokens that expire. Generate a new token on each page load:

```javascript theme={"system"}
// Recommended: Fetch token when component mounts
async function initializeWidget() {
  const { widget_token } = await fetchWidgetToken(cardId);
  document.querySelector('activate-card').setAttribute('token', widget_token);
}
```

***

## Migration Checklist

* [ ] Update backend API calls from `/v0/cards/card_widget_url` to `/v1/cards/{card_id}/widget_token`
* [ ] Change HTTP method from `GET` to `POST` for token endpoint
* [ ] Add widget script to your HTML (`<script type="module" src="...">`)
* [ ] Replace `<iframe>` elements with web components (`<activate-card>` or `<set-pin>`)
* [ ] Update event handling to use DOM event listeners
* [ ] Test in sandbox environment before deploying to production
* [ ] (Optional) Add custom theming and labels

***

## Need Help?

If you encounter issues during migration, refer to the full documentation:

* [Activate Card Widget](/v2/docs/card-widgets-activate)
* [Set PIN Widget](/v2/docs/card-widgets-set-pin)
* [Reveal Card Widget](/v2/docs/card-widgets-reveal)
* [Reveal PIN Widget](/v2/docs/card-widgets-reveal-pin)
* [Legacy Marqeta Widgets](/v2/docs/card-widgets-legacy-marqeta)
