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

# Embedded Checkout

> Learn how to embed Revolv3's checkout directly in your website using an iframe. Keep customers on your site while Revolv3 handles the payment form.

## What is Embedded Checkout?

**Embedded checkout** lets you include Revolv3's secure payment form directly in your website using an iframe. Customers complete payment without leaving your site, but Revolv3 still handles all the sensitive payment data.

**Benefits:**

* ✅ **Seamless experience**: Customers stay on your site
* ✅ **No card data handling**: You never see sensitive payment information
* ✅ **PCI compliance**: Revolv3 handles all security requirements
* ✅ **Brand consistency**: Checkout appears within your site design
* ✅ **Event-based updates**: Your page is notified when payment completes

**When to use it:**

* You want customers to stay on your site
* You want a seamless checkout experience
* You're okay with using an iframe
* You can handle postMessage events in JavaScript

## Prerequisites

Before you begin, make sure you have:

1. ✅ **Revolv3 account**: Active merchant account with configured processors
2. ✅ **API key**: Developer static token for authentication
3. ✅ **Trusted hostnames**: Your website domain added to Trusted Checkout Hostnames in the portal

## Step 1: Create a Checkout Session

Create a checkout session by sending a POST request to the checkout endpoint.

### API Endpoint

```
POST {{Api Root}}/api/Checkout
```

Replace `{{Api Root}}` with:

* **Production**: `api.revolv3.com`
* **Sandbox**: `api-sandbox.revolv3.com`

### Required Headers

<Warning>
  **Origin HTTP header required**

  You **must** include the `Origin` HTTP header in your request. This header should match one of your trusted hostnames.

  If the `Origin` header is missing or doesn't match a trusted hostname, you'll get a **400 Bad Request** error.
</Warning>

Include these headers:

* `Origin`: Your website's origin (e.g., `https://mysite.com`)
* `x-revolv3-token`: Your API key
* `Content-Type`: `application/json`

### Sample Request

<CodeGroup>
  ```bash bash theme={null}
  {
    "OneTimePayment": {
      "CheckoutLineItems": [
        {
          "Name": "Item 1",
          "Description": "Product description",
          "Value": 9.99,
          "ValueType": "Standard"
        },
        {
          "Name": "Item 2",
          "Description": "Another product",
          "Value": 21.99,
          "ValueType": "Standard"
        }
      ]
    }
  }
  ```
</CodeGroup>

**Note**: For embedded checkout, you typically don't need a `ReturnUrl` since the customer stays on your page. However, you can include one if needed.

For details on line items and value types, see [Checkout Line Items Value Types](/docs/checkout/checkout-line-items-value-types).

### Response

When you create a checkout session, you'll get back a checkout link:

<CodeGroup>
  ```bash bash theme={null}
  {
    "checkoutId": "0584773e-47bf-4822-91de-06acb5de9358",
    "checkoutLink": "https://portal.revolv3.com/checkout/0584773e-47bf-4822-91de-06acb5de9358"
  }
  ```
</CodeGroup>

**Understanding the response:**

* `checkoutId`: Unique identifier for this checkout session (save this for tracking)
* `checkoutLink`: The URL to embed in your iframe

## Step 2: Embed the Checkout Page

Embed the checkout link in your website using an iframe:

### HTML Example

```html theme={null}
<iframe 
  title="Revolv3 Checkout" 
  src="https://portal.revolv3.com/checkout/0584773e-47bf-4822-91de-06acb5de9358"
  frameborder="0" 
  scrolling="no"
  width="100%" 
  height="600">
</iframe>
```

**Iframe attributes:**

* `src`: The `checkoutLink` from the API response
* `title`: Descriptive title for accessibility
* `frameborder="0"`: Removes border for seamless integration
* `scrolling="no"`: Prevents scrollbars (adjust height as needed)
* `width` and `height`: Set to fit your page layout

### React Example

```jsx theme={null}
function CheckoutEmbed({ checkoutLink }) {
  return (
    <iframe
      title="Revolv3 Checkout"
      src={checkoutLink}
      frameBorder="0"
      scrolling="no"
      style={{ width: '100%', height: '600px' }}
    />
  );
}
```

## Step 3: Listen for Payment Completion

When the customer completes payment, Revolv3 sends a message to your page using the `postMessage` API. You need to listen for this message to know when payment is done.

### Add Event Listener

Add a message event listener to your page:

<CodeGroup>
  ```javascript theme={null}
  addEventListener("message", receiveMessage, false);

  function receiveMessage(event) {
    // ⚠️ SECURITY: Always verify the message origin
    if (event.origin === 'https://portal-sandbox.revolv3.com' ||
        event.origin === 'https://portal.revolv3.com') {
      
      // Message is from Revolv3 - safe to process
      const data = event.data;  // { checkoutId: string, checkoutStatus: string }
      
      // Handle the payment result
      if (data.checkoutStatus === 'PaymentCompleted') {
        // Payment succeeded - show success message, update UI, etc.
        showSuccessMessage();
        hideCheckoutIframe();
      } else if (data.checkoutStatus === 'PaymentFailed') {
        // Payment failed - show error, allow retry, etc.
        showErrorMessage();
      }
    }
    
    // Ignore messages from other origins
    return;
  }
  ```
</CodeGroup>

<Warning>
  **Always verify event.origin**

  **Security requirement**: You **must** verify that the message came from Revolv3 (either `portal.revolv3.com` or `portal-sandbox.revolv3.com`). Never process messages from unknown origins.

  This prevents malicious websites from sending fake payment completion messages to your page.
</Warning>

### Understanding the Message Data

The message from Revolv3 contains:

```typescript theme={null}
{
  checkoutId: string,      // Unique checkout session ID (GUID format)
  checkoutStatus: string  // Current status of the checkout
}
```

### Checkout Status Values

| Status             | What It Means                          | What to Do                                             |
| ------------------ | -------------------------------------- | ------------------------------------------------------ |
| `Pending`          | Checkout created, payment not yet made | Keep showing the iframe, wait for payment              |
| `PaymentCompleted` | Payment was successful                 | Show success message, hide iframe, update order status |
| `PaymentFailed`    | Payment attempt failed                 | Show error message, allow customer to retry            |

## Step 4: Handle Payment Results

Based on the checkout status, update your page:

### Payment Completed

```javascript theme={null}
if (data.checkoutStatus === 'PaymentCompleted') {
  // Hide the checkout iframe
  document.getElementById('checkout-iframe').style.display = 'none';
  
  // Show success message
  showSuccessMessage('Payment completed successfully!');
  
  // Update order status in your system
  updateOrderStatus(data.checkoutId, 'paid');
  
  // Redirect or update UI as needed
}
```

### Payment Failed

```javascript theme={null}
if (data.checkoutStatus === 'PaymentFailed') {
  // Show error message
  showErrorMessage('Payment failed. Please try again.');
  
  // Optionally allow customer to retry
  // (create a new checkout session)
}
```

## Getting Checkout Information

You can check the checkout status at any time using the API:

```
GET {{Api Root}}/api/Checkout/{checkoutId}
```

Replace `{checkoutId}` with the checkout ID from the session response.

This is useful if:

* You need to verify payment status
* The customer refreshes the page
* You want to poll for status updates

## Complete Integration Example

Here's a complete example of embedded checkout:

### HTML

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <meta name="referrer" content="origin" />
  <title>Checkout</title>
</head>
<body>
  <div id="checkout-container">
    <iframe 
      id="checkout-iframe"
      title="Revolv3 Checkout" 
      src=""
      frameborder="0" 
      scrolling="no"
      width="100%" 
      height="600">
    </iframe>
  </div>
  
  <div id="success-message" style="display: none;">
    Payment completed successfully!
  </div>
  
  <div id="error-message" style="display: none;">
    Payment failed. Please try again.
  </div>

  <script>
    // Create checkout session (on page load)
    async function createCheckout() {
      const response = await fetch('{{Api Root}}/api/Checkout', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Origin': window.location.origin,
          'x-revolv3-token': 'your-api-key'
        },
        body: JSON.stringify({
          OneTimePayment: {
            CheckoutLineItems: [
              {
                Name: "Product",
                Value: 99.99,
                ValueType: "Standard"
              }
            ]
          }
        })
      });
      
      const data = await response.json();
      document.getElementById('checkout-iframe').src = data.checkoutLink;
    }
    
    // Listen for payment completion
    window.addEventListener("message", function(event) {
      // Verify origin
      if (event.origin === 'https://portal.revolv3.com' ||
          event.origin === 'https://portal-sandbox.revolv3.com') {
        
        const { checkoutId, checkoutStatus } = event.data;
        
        if (checkoutStatus === 'PaymentCompleted') {
          document.getElementById('checkout-iframe').style.display = 'none';
          document.getElementById('success-message').style.display = 'block';
        } else if (checkoutStatus === 'PaymentFailed') {
          document.getElementById('error-message').style.display = 'block';
        }
      }
    });
    
    // Create checkout when page loads
    createCheckout();
  </script>
</body>
</html>
```

## Best Practices

1. **Verify message origin**: Always check `event.origin` before processing messages
2. **Handle all statuses**: Account for Pending, PaymentCompleted, and PaymentFailed
3. **User experience**: Show loading states and clear success/error messages
4. **Iframe sizing**: Set appropriate width and height for your layout
5. **Error handling**: Handle cases where checkout creation fails
6. **Test thoroughly**: Test the full flow in sandbox before production

## Common Questions

**Q: Can I style the iframe?**
A: You can style the iframe container, but the content inside is controlled by Revolv3 for security reasons.

**Q: What if the customer closes the iframe?**
A: The checkout session remains valid. You can check its status or create a new one.

**Q: How do I know if payment completed?**
A: Listen for the `postMessage` event from Revolv3. The message includes the checkout status.

**Q: Can I customize the payment page?**
A: The embedded checkout uses Revolv3's standard design. For more customization, you'd need to build your own form.

**Q: What browsers support this?**
A: All modern browsers support iframes and postMessage. Test in your target browsers.

## Security Notes

* **Always verify origin**: Never process messages without checking `event.origin`
* **Use HTTPS**: Always use HTTPS for your site when handling payments
* **Trusted hostnames**: Ensure your domain is in the trusted hostnames list
* **Origin header**: Always include the Origin header in API requests

## Next Steps

* **[Hosted Page](/docs/checkout/hosted-page)** — Learn about redirect-based checkout
* **[Checkout Line Items](/docs/checkout/checkout-line-items-value-types)** — Understand how to structure checkout items
* **[Checkout Overview](/docs/checkout)** — Return to checkout overview

***
