Checkout Embed SDK

The Checkout Embed SDK allows you to integrate Autra payment links directly into your website. Instead of redirecting the payer to a separate page, the SDK opens the checkout in a modal overlay — keeping the payer on your site throughout the payment flow.

When to use

ScenarioRecommended approach
Payment link via email/WhatsAppShare the checkoutUrl directly (no SDK needed)
Checkout in a modal overlayUse SDK with mode: 'modal' (default on desktop)
Checkout inside a drawer or sidebarUse SDK with mode: 'inline' and a container element
Mobile appUse redirect mode or open checkoutUrl in a WebView
Server-to-server integrationUse the API directly (POST /v1/acquiring/links)

How it works

Your website                              Autra
────────────                              ─────
1. Payer clicks "Pay"
2. SDK opens modal overlay
3.                            ──────►    Loads checkout page
4.                                       Payer fills in data
5.                                       Payer pays (card/pix/boleto)
6.                            ◄──────    postMessage with result
7. SDK fires onSuccess callback
8. You update your page

The checkout page runs on the Autra domain (autra.io), ensuring full PCI isolation — card data never touches your website.


Quick start

Step 1: Include the SDK

Add the SDK script to your HTML head or body:

<script src="https://www.autra.io/sdk/checkout.js"></script>

Step 2: Open the checkout

Add a button (<button id="pay-btn">Pay now</button>) and initialize the SDK:

document.getElementById('pay-btn').addEventListener('click', function() {
  AutraCheckout.open({
    slug: 'lnk_a1b2c3d4',
    onSuccess: function(data) {
      console.log('Payment confirmed!', data);
      // data.paymentId — Autra payment ID
      // data.status    — ACCEPTED, AUTHORIZED, or PAID
      // data.amount    — payment amount
      // data.method    — CARD, PIX, or BOLETO
    },
    onClose: function() {
      console.log('Payer closed checkout without paying');
    },
    onError: function(err) {
      console.log('Payment error:', err.code, err.message);
    }
  });
});

Step 3: Done

The SDK handles everything — opening the modal, loading the checkout, listening for the payment result, and closing the modal.


Auto-bind (no JavaScript required)

For simple integrations, you can use the data-autra-checkout attribute on any HTML element. The SDK automatically binds click handlers on page load.

Add the SDK script, then add data-autra-checkout="your-slug" to any button or link:

<button data-autra-checkout="lnk_a1b2c3d4">Pay R$ 150.00</button>

To receive callbacks with auto-bind, set global handlers before loading the SDK:

window._autraOnSuccess = function(data) { console.log('Paid!', data); };
window._autraOnClose = function() { console.log('Closed'); };
window._autraOnError = function(err) { console.log('Error', err); };

You can also override the mode and return URL per-button via extra data-* attributes (useful when a specific button needs a different behavior from the global default):

AttributeEquivalent optionExample
data-autra-checkoutslug (required)data-autra-checkout="lnk_a1b2c3d4"
data-autra-modemodedata-autra-mode="redirect"
data-autra-return-urlreturnUrl (only with mode="redirect")data-autra-return-url="https://yoursite.com/thanks"
<button
  data-autra-checkout="lnk_a1b2c3d4"
  data-autra-mode="redirect"
  data-autra-return-url="https://yoursite.com/thanks">
  Pay R$ 150.00
</button>

Options reference

ParameterTypeRequiredDefaultDescription
slugstringYesPayment link slug (e.g. lnk_a1b2c3d4). Obtain from POST /v1/acquiring/links response
modestringNomodal (desktop) / redirect (mobile)modal opens an overlay. redirect navigates to checkout URL. inline renders inside a container
containerstring or ElementOnly for inline modeCSS selector or DOM element where the checkout iframe will be rendered
returnUrlstringNoURL to redirect after payment. Only used in redirect mode
onSuccessfunctionNoCalled when the payment is confirmed. Receives a data object (see below)
onClosefunctionNoCalled whenever the checkout closes — user cancel (X, ESC, click outside), programmatic AutraCheckout.close(), or after onSuccess. See notes below
onErrorfunctionNoCalled when a payment error occurs. Receives an error object (see below)

Methods

MethodDescription
AutraCheckout.open(options)Opens the checkout. See options reference above
AutraCheckout.close()Closes the checkout modal programmatically. Triggers onClose callback
AutraCheckout.versionReturns the SDK version string (e.g. "1.0.0")

Callback data

onSuccess

Fired when the payment is confirmed. The data object contains:

{
  "paymentId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "ACCEPTED",
  "amount": 150.00,
  "method": "CARD",
  "slug": "lnk_a1b2c3d4"
}
FieldTypeDescription
paymentIdstringAutra payment identifier. Use this to query payment details via API
statusstringPayment status: ACCEPTED (card), AUTHORIZED (Pix), PAID (boleto)
amountnumberPayment amount in BRL
methodstringPayment method used: CARD, PIX, or BOLETO
slugstringThe payment link slug that was paid

onError

Fired when the payment is declined or an error occurs:

{
  "code": "INSUFFICIENT_FUNDS",
  "message": "Payment declined"
}
FieldTypeDescription
codestringMachine-readable error code
messagestringHuman-readable error description

onClose

Fired whenever the checkout closes, for any reason. No arguments.

Triggers include:

  • Payer clicks the close button (X), presses ESC, or clicks outside the modal
  • Your code calls AutraCheckout.close()
  • A new AutraCheckout.open() is called while another checkout is already open (the previous one closes first)
  • After onSuccess fires (the checkout page sends a close message once the payment result is delivered)

Practical implication: if you use onClose to track "user gave up", you'll get false positives after every successful payment. Use onSuccess as the source of truth for completion and treat onClose as "modal is no longer visible" — not "user cancelled".


Opening modes

Modal (default on desktop)

Opens the checkout as an overlay on your page. The payer stays on your site.

AutraCheckout.open({
  slug: 'lnk_a1b2c3d4',
  mode: 'modal',
  onSuccess: function(data) { /* handle */ }
});

Behavior:

  • Full-screen overlay with a centered checkout container (480px max width)
  • Close button (X) in the top-right corner
  • Click outside the modal or press ESC to close
  • Page scroll is disabled while the modal is open
  • On mobile screens the modal expands to full screen

Redirect (default on mobile)

Navigates the browser to the Autra checkout page. After payment, the payer is redirected to your returnUrl.

AutraCheckout.open({
  slug: 'lnk_a1b2c3d4',
  mode: 'redirect',
  returnUrl: 'https://yoursite.com/payment/complete'
});

Behavior:

  • Full page navigation to the Autra checkout URL
  • After payment, redirects to returnUrl with query parameters: ?status=success&paymentId=xxx
  • If the payer closes the tab, no callback is fired

Inline (embed in your own container)

Renders the checkout iframe inside a container element on your page. Ideal for drawers, sidebars, or custom layouts where you want full control over the UI.

AutraCheckout.open({
  slug: 'lnk_a1b2c3d4',
  mode: 'inline',
  container: '#checkout-container',
  onSuccess: function(data) { /* handle */ }
});

The container parameter accepts a CSS selector string (e.g. '#my-div', '.checkout-area') or a DOM element reference.

Behavior:

  • The iframe fills 100% width and height of the container
  • No overlay, close button, or scroll lock is created
  • You control the container dimensions and visibility
  • All callbacks (onSuccess, onClose, onError) work the same as other modes

Removing the checkout in inline mode: in the current SDK (1.0.0), AutraCheckout.close() fires the onClose callback but does not remove the iframe from your container — that removal is done by the modal overlay only. In inline mode you should also clear the container yourself:

AutraCheckout.close();                                     // fires onClose + resets internal state
document.getElementById('checkout-container').innerHTML = ''; // actually removes the iframe

Example with a drawer:

// Open a drawer on your page
document.getElementById('pay-btn').addEventListener('click', function() {
  document.getElementById('drawer').style.display = 'block';

  AutraCheckout.open({
    slug: 'lnk_a1b2c3d4',
    mode: 'inline',
    container: '#drawer-content',
    onSuccess: function(data) {
      document.getElementById('drawer').style.display = 'none';
      alert('Payment confirmed!');
    },
    onClose: function() {
      document.getElementById('drawer').style.display = 'none';
    }
  });
});

Full integration example

// Include in your HTML:
//   <script src="https://www.autra.io/sdk/checkout.js"></script>
//   <button id="subscribe-btn">Subscribe now</button>
//   <div id="result" hidden></div>

document.getElementById('subscribe-btn').addEventListener('click', function() {
  AutraCheckout.open({
    slug: 'lnk_a1b2c3d4',

    onSuccess: function(data) {
      // Show confirmation on your page
      var result = document.getElementById('result');
      result.hidden = false;
      result.textContent = data.method + ' payment of R$ ' +
        data.amount.toFixed(2) + ' confirmed! ID: ' + data.paymentId;

      // Optionally notify your backend
      fetch('/api/payment-confirmed', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          paymentId: data.paymentId,
          slug: data.slug,
          amount: data.amount
        })
      });
    },

    onClose: function() {
      // Fires on cancel AND after onSuccess — do not treat as "user cancelled"
      console.log('Checkout closed');
    },

    onError: function(err) {
      alert('Payment failed: ' + err.message);
    }
  });
});

Idempotency and double-click prevention

The SDK does not enforce idempotency by itself — it just opens a checkout for a slug you already created via POST /v1/acquiring/links. Duplicate-charge prevention lives in two other places:

  • When you create the link — pass externalId in POST /v1/acquiring/links. If your backend retries the create, Autra returns the same link (same slug) instead of a new one.
  • On the checkout page — Autra deduplicates payment attempts server-side per slug. A payer refreshing or double-clicking "Pay" inside the checkout does not cause double charge.

Double-click on your own "Pay" button: the SDK itself does not disable your button. If you want to prevent the payer from opening the checkout twice in a row, disable the button on click and re-enable it inside onClose:

var btn = document.getElementById('pay-btn');
btn.addEventListener('click', function() {
  btn.disabled = true;
  AutraCheckout.open({
    slug: 'lnk_a1b2c3d4',
    onSuccess: function(data) { /* handle */ },
    onClose:   function()     { btn.disabled = false; },
    onError:   function(err)  { btn.disabled = false; }
  });
});

Security

ConcernHow the SDK handles it
Card data exposureCard data is entered on the Autra domain. Your site never sees card numbers, CVV, or sensitive data
Cross-origin communicationUses postMessage with strict origin validation. The SDK only accepts messages from https://www.autra.io
XSS on merchant siteEven if your site has XSS vulnerabilities, card data remains isolated in the Autra iframe
Fake checkoutThe checkout runs on the Autra domain — payers can verify the URL in the browser
CSRFThe checkout uses the payment link slug (public), not merchant sessions

Browser support

The SDK uses standard Web APIs and works on all modern browsers:

  • Chrome 60+
  • Firefox 60+
  • Safari 12+
  • Edge 79+
  • Mobile Safari (iOS 12+)
  • Chrome for Android

Troubleshooting

IssueSolution
Modal does not openCheck that checkout.js loaded correctly (no 404 in console). Verify the slug is valid
onSuccess not firingEnsure the checkout page can send postMessage (not blocked by browser extensions). Check browser console for errors
Modal opens but checkout is blankCheck for Content-Security-Policy headers on your site that might block the iframe. Add frame-src https://www.autra.io to your CSP
Card payment not accepted in the iframeThe iframe requests allow="payment; clipboard-write". If your site sets a restrictive Permissions-Policy header (e.g. payment=()), the browser silently blocks Payment Request API inside the iframe. Ensure payment=(self "https://www.autra.io") in your Permissions-Policy
AutraCheckout.close() in inline mode leaves the iframe visibleKnown limitation in SDK 1.0.0close() only removes overlay-mode DOM. In inline mode, also call container.innerHTML = '' after close(). See Inline section
Mobile modal is too smallThe SDK auto-detects mobile and uses redirect mode. To force modal, set mode: 'modal' explicitly
Payment confirmed but onSuccess not calledThe payer may have closed the modal before the callback fired. Use API polling as a fallback to verify payment status server-side

Related

  • Payment Links — Overview of the payment links feature (Funcionalidades)
  • POST /v1/acquiring/links — Create a payment link (API Reference)
  • GET /v1/acquiring/links/{linkId} — Query payment details (API Reference)