Skip to content

Widget Integration

SUIT provides an embeddable Web Component (<sunat-widget>) for manual document emission. It works with any framework or vanilla HTML — no dependencies required.

Add the widget script and place the component in your page:

<!-- Add the widget script -->
<script src="https://app.suit.pe/widget/suit-widget.js"></script>
<!-- Place the widget -->
<sunat-widget
api-key="sk_live_YOUR_API_KEY"
api-url="https://api.suit.pe"
></sunat-widget>
AttributeRequiredDescription
api-keyYesYour tenant API key (sk_live_xxx...)
api-urlYesSUIT API base URL (https://api.suit.pe for production)

The widget provides a self-contained 4-step wizard:

  1. Client selection — Search and select or create a new client
  2. Item entry — Add line items with quantities and prices
  3. Review — Verify totals, IGV calculations, and document details
  4. Confirm — Submit to SUNAT and see the result (accepted/rejected)
  • Self-contained Web Component using Shadow DOM
  • No CSS conflicts with your application
  • Supports Factura and Boleta emission
  • Auto-validates IGV calculations
  • Shows SUNAT response immediately
  • Responsive — adapts to container width

The widget runs inside Shadow DOM for complete style isolation. Control its size through the container element:

<div style="max-width: 600px; margin: 0 auto;">
<sunat-widget
api-key="sk_live_YOUR_API_KEY"
api-url="https://api.suit.pe"
></sunat-widget>
</div>

Embed the widget in an internal admin panel where staff manually emit invoices:

<div id="billing-section">
<h2>Emitir Comprobante</h2>
<sunat-widget
api-key="sk_live_YOUR_API_KEY"
api-url="https://api.suit.pe"
></sunat-widget>
</div>
<script src="https://app.suit.pe/widget/suit-widget.js"></script>
import { useEffect } from 'react';
function BillingWidget() {
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://app.suit.pe/widget/suit-widget.js';
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []);
return (
<div style={{ maxWidth: '600px', margin: '0 auto' }}>
<sunat-widget
api-key="sk_live_YOUR_API_KEY"
api-url="https://api.suit.pe"
/>
</div>
);
}
<template>
<div style="max-width: 600px; margin: 0 auto">
<sunat-widget
:api-key="apiKey"
api-url="https://api.suit.pe"
/>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
const apiKey = import.meta.env.VITE_SUIT_API_KEY;
onMounted(() => {
const script = document.createElement('script');
script.src = 'https://app.suit.pe/widget/suit-widget.js';
script.async = true;
document.body.appendChild(script);
});
</script>
  • The widget uses your API Key directly in client-side code. For production, consider:
    • Restricting the API key scope if possible
    • Using a dedicated API key labeled widget for tracking
    • Implementing domain restrictions on the API key
  • The widget communicates directly with the SUIT API over HTTPS