Embeddable Components Guide

Embeddable components enable Forge dashboard functionality to be embedded within third-party websites or applications. Integrators can provide users with direct access to billing management, carrier setup, payment logs, and reporting, all from their own platform.


Prerequisites

  • A Forge-enabled EasyPost account
  • A server endpoint capable of fetching a session ID from the EasyPost EmbeddableSessions API

Server Configuration

The server must expose an endpoint that retrieves a short-lived session ID from the EasyPost EmbeddableSessions API. This endpoint is called by the client application (browser) to initialize an embedded component.

The server-side request to EasyPost should be made with the platform’s EasyPost API key and include the following parameters:

  • user_id: The User ID of the sub account for which the embeddable session is being created.
  • origin_host The integrator’s domain in bare-host format (e.g., example.com), excluding protocol and subdomains.

Retrieve a Session ID Example (Python)

import os
import requests
from flask import (
    Flask,
    jsonify,
)

app = Flask(__name__)

EASYPOST_API_KEY = os.environ.get("EASYPOST_API_KEY", "")


@app.route("/api/easypost-embeddables/session", methods=["GET"])
def create_embeddable_session():
    payload = {
        "user_id": "SUB_ACCOUNT_USER_ID",  # Replace with sub-account user ID
        "origin_host": "ORIGIN_HOST",  # Replace with integrator's domain
    }

    response = requests.post(
        "https://api.easypost.com/v2/embeddables/session",
        auth=(EASYPOST_API_KEY, ""),
        json=payload,
        headers={"Content-Type": "application/json"},
        timeout=10,
    )
    response.raise_for_status()
    return jsonify(response.json())


if __name__ == "__main__":
    app.run(port=5000, debug=True)

Client Configuration

The client application must load the EasyPost Embeddables script and initialize the SDK with a function that fetches a session ID from the server.

Each embeddable component is rendered securely in an EasyPost-hosted iframe displayed inside a modal. Components are launched asynchronously in response to user actions such as button clicks.

Example Integration that Corresponds to the Above Python Snippet (HTML/JavaScript)

<html>
  <body>
    <div>Integrator's Website</div>
    <div id="container"></div>
    <div>
      <button id="button-billing">Manage Billing</button>
      <button id="button-carriers">Manage Carriers</button>
      <button id="button-payment-logs">Payment Logs</button>
      <button id="button-reports">Reports</button>
    </div>

    <!-- Load EasyPost Embeddables -->
    <script src="https://embed.easypost.com/embeddables/1.0/client.js" async></script>

    <script>
      window.EasyPostEmbeddables = window.EasyPostEmbeddables || {};
      window.EasyPostEmbeddables.onLoad = () => {
        // Function that calls the integrator's backend to get a session ID
        const fetchSessionId = async () => {
          const url = '/api/easypost-embeddables/session'; // your server endpoint
          try {
            const response = await fetch(url);

            if (!response.ok) {
              throw new Error(`Fetch Session ID error! status: ${response.status}`);
            }

            const data = await response.json();
            return data.session_id;
          } catch (error) {
            console.error('[EasyPostEmbeddables] Failed to fetch session ID:', error);
            return null;
          }
        };

        // Initialize EasyPost Embeddables
        const embeddables = window.EasyPostEmbeddables.init({
          fetchSessionId,
          fonts: [
            {
              cssSrc: 'https://fonts.googleapis.com/css2?family=Zen+Dots&display=swap',
            },
          ],
          appearance: {
            tokens: {
              'font.family': 'Zen Dots',
            },
            modalZIndex: '123456',
          },
        });

        // Example UI bindings
        document.getElementById('button-billing').addEventListener('click', async () => {
          await embeddables.open('manage-billing');
        });

        document.getElementById('button-carriers').addEventListener('click', async () => {
          await embeddables.open('manage-carriers');
        });

        document.getElementById('button-payment-logs').addEventListener('click', async () => {
          await embeddables.open('manage-payment-logs');
        });

        document.getElementById('button-reports').addEventListener('click', async () => {
          await embeddables.open('manage-reports');
        });
      };
    </script>
  </body>
</html>

Embeddable Component Workflow

  1. The browser loads the EasyPost Embeddables script from
 https://embed.easypost.com/embeddables/1.0/client.js(opens in a new tab).
  2. When onLoad fires, the integrator’s client initializes the SDK using EasyPostEmbeddables.init().
  3. The fetchSessionId() callback retrieves or refreshes the session ID as needed.
  4. When a button is clicked, the open() method launches the requested component inside a modal.
  5. The modal content is rendered securely from EasyPost’s domain.

Note: Session refreshing is handled automatically by EasyPost. Only the fetchSessionId function must be supplied.


Initialization Options

Option
Required
Description
fetchSessionIdYesCallback that returns a Promise resolving to a valid session ID fetched from the integrator’s server.
fontsNoOptional array of font configuration objects. Each font can specify a cssSrc, src, family, style, and weight. See the Fonts section below for additional details.
appearanceNoControls theming and modal layout options, including color tokens, font settings, and an optional modalZIndex for layering above or below existing UI.

Fonts

The fonts option in EasyPostEmbeddables.init() accepts an array of font configuration objects that define how custom fonts are loaded inside embeddable components. If the application uses custom fonts, they must be specified when initializing the SDK.

Custom fonts can be specified using one of two forms:

  1. cssSrc: Use this form to load a font from a hosted CSS file (for example, a Google Fonts stylesheet). The URL must point to a valid CSS file defining @font-face rules.

    EasyPostEmbeddables.init({
      fonts: [{ cssSrc: 'https://fonts.googleapis.com/css2?family=Zen+Dots&display=swap' }],
    });
    
  2. Direct Font Files: Use this form to load a font file directly. Note that in this form, family andsrc are required.

    EasyPostEmbeddables.init({
      fonts: [
        {
          family: 'Avenir',
          src: 'https://example.com/fonts/avenir.woff2',
          style: 'normal',
          weight: '400',
        },
      ],
    });
    

Appearance

The appearance option in EasyPostEmbeddables.init() controls the visual presentation of Embeddable components. It supports customization of theme tokens (color and typography) and modal layout properties such as stacking order. Integrators can pass either theme tokens to modify colors and font settings, or define a modalZIndex value to control how the modal overlays the application interface.

Theme tokens

The tokens are organized by categories that represent different parts of the visual system:

  • Primary: Main brand palette for key actions and highlights. The default is a blue shade.
  • Secondary: Accent tones used for emphasis or alternate states. The default is a purple shade.
  • Positive: Success, confirmation, or active states. The default is a green shade.
  • Negative: Errors or destructive actions. The default is a red shade.
  • Alert: Urgent notifications or attention states. The default is an orange shade.
  • Warning: Caution or mild alerts. The default is a yellow shade.
  • Neutral: Grayscale foundation for surfaces, borders, and text.

Font family defines the default typeface used throughout Embeddable components. By default, components use Poppins, with “Poppins Fallback” for compatibility.

{
  "color.primary.900": { "value": "#000824" },
  "color.primary.800": { "value": "#061340" },
  "color.primary.700": { "value": "#0B2780" },
  "color.primary.600": { "value": "#113ABF" },
  "color.primary.500": { "value": "#164DFF" },
  "color.primary.400": { "value": "#4571FF" },
  "color.primary.300": { "value": "#7394FF" },
  "color.primary.200": { "value": "#A2B8FF" },
  "color.primary.100": { "value": "#D0DBFF" },
  "color.primary.050": { "value": "#F6F9FF" },
  "color.primary.025": { "value": "#FBFDFF" },

  "color.secondary.900": { "value": "#150720" },
  "color.secondary.800": { "value": "#280E3C" },
  "color.secondary.700": { "value": "#501D77" },
  "color.secondary.600": { "value": "#772BB0" },
  "color.secondary.500": { "value": "#9F39EE" },
  "color.secondary.400": { "value": "#B261F1" },
  "color.secondary.300": { "value": "#C588F5" },
  "color.secondary.200": { "value": "#D9B0F8" },
  "color.secondary.100": { "value": "#ECD7FC" },
  "color.secondary.050": { "value": "#F9F1FF" },
  "color.secondary.025": { "value": "#FDFBFF" },

  "color.positive.900": { "value": "#001E16" },
  "color.positive.800": { "value": "#00392C" },
  "color.positive.700": { "value": "#007357" },
  "color.positive.600": { "value": "#00AC83" },
  "color.positive.500": { "value": "#00E5AE" },
  "color.positive.400": { "value": "#33EABE" },
  "color.positive.300": { "value": "#66EFCE" },
  "color.positive.200": { "value": "#99F5DF" },
  "color.positive.100": { "value": "#CCFAEF" },
  "color.positive.050": { "value": "#EAFFFA" },
  "color.positive.025": { "value": "#FAFFFE" },

  "color.negative.900": { "value": "#1B0707" },
  "color.negative.800": { "value": "#3F1716" },
  "color.negative.700": { "value": "#7E2E2D" },
  "color.negative.600": { "value": "#BC4543" },
  "color.negative.500": { "value": "#FB5C59" },
  "color.negative.400": { "value": "#FC7D7A" },
  "color.negative.300": { "value": "#FD9D9B" },
  "color.negative.200": { "value": "#FDBEBD" },
  "color.negative.100": { "value": "#FEDEDE" },
  "color.negative.050": { "value": "#FFF2F2" },
  "color.negative.025": { "value": "#FFFCFC" },

  "color.alert.900": { "value": "#411E00" },
  "color.alert.800": { "value": "#834003" },
  "color.alert.700": { "value": "#C36108" },
  "color.alert.600": { "value": "#F2780A" },
  "color.alert.500": { "value": "#FF8D25" },
  "color.alert.400": { "value": "#FFAD61" },
  "color.alert.300": { "value": "#FFBC7D" },
  "color.alert.200": { "value": "#FFD0A4" },
  "color.alert.100": { "value": "#FFEDE0" },
  "color.alert.050": { "value": "#FFF9F5" },
  "color.alert.025": { "value": "#FFFDFD" },

  "color.warning.900": { "value": "#423804" },
  "color.warning.800": { "value": "#6C4A07" },
  "color.warning.700": { "value": "#A57B0F" },
  "color.warning.600": { "value": "#D6A015" },
  "color.warning.500": { "value": "#F4D35E" },
  "color.warning.400": { "value": "#FEE281" },
  "color.warning.300": { "value": "#FFEBA4" },
  "color.warning.200": { "value": "#FFF2C4" },
  "color.warning.100": { "value": "#FFF8DF" },
  "color.warning.050": { "value": "#FFFCF0" },
  "color.warning.025": { "value": "#FFFEFB" },

  "color.neutral.900": { "value": "#000000" },
  "color.neutral.800": { "value": "#1C222D" },
  "color.neutral.700": { "value": "#384359" },
  "color.neutral.600": { "value": "#47547F" },
  "color.neutral.500": { "value": "#7086B2" },
  "color.neutral.400": { "value": "#8D9EC1" },
  "color.neutral.300": { "value": "#A9B6D1" },
  "color.neutral.200": { "value": "#C6CFE0" },
  "color.neutral.100": { "value": "#E2E7F0" },
  "color.neutral.050": { "value": "#F1F1F1" },
  "color.neutral.025": { "value": "#FAFAFA" },
  "color.neutral.000": { "value": "#FFFFFF" },

  "font.family": { "value": "Poppins, \"Poppins Fallback\"" }
}

Embeddables Instance Methods

When EasyPostEmbeddables.init() is called, it returns an Embeddables instance that provides several methods for interacting with embedded components. These methods allow integrators to open modals, listen for events, update appearance dynamically, or clean up the iframe when it’s no longer needed.

Method
Signature
Description
open(componentType)open(componentType: string): Promise<void>Launches a specified Embeddable Component (for example, "manage-billing", "manage-carriers", "manage-payment-logs", or "manage-reports") inside a modal overlay.
on(eventType, handler)on(eventType: string, handler: (event: unknown) => void): voidRegisters an event listener for messages emitted from the iframe. Events can be used to react to lifecycle changes, such as modal open/close or component updates.
off(eventType, handler)off(eventType: string, handler: (event: unknown) => void): voidRemoves a previously registered event listener.
update(options)update(options: { fonts?: Font[]; appearance?: Theme }): Promise<void>Dynamically updates the fonts or appearance tokens of an already initialized Embeddable modal. Can be used to change theme colors or font family at runtime.
destroy()destroy(): voidDestroys the Embeddables iframe and removes all associated event handlers. Once called, a new instance must be re-initialized with EasyPostEmbeddables.init().

Available Components

Each component mirrors its Forge counterpart and launches inside a modal. For instance, the carrier management component allows sub-accounts to connect, configure, and manage their carrier accounts.

Billing Management

The Billing Management component is accessed by passing "manage-billing" to the open() function on the created Embeddables instance.

Example of the Billing Management component

Carrier Management

The Carrier Management component is accessed by passing "manage-carriers" to the open() function on the created Embeddables instance.

Example of the Carrier Management component

Payment Logs

The Payment Logs component is accessed by passing "manage-payment-logs" to the open() function on the created Embeddables instance.

Example of the Payment Logs component

Reports

The Reports component is accessed by passing "manage-reports" to the open() function on the created Embeddables instance.

Example of the Reports component

Content Security Policy (CSP) Considerations

Integrators using Embeddable Components should ensure the CSP allows the EasyPost client script and embedded iframe to load correctly.

Below is a minimal CSP configuration example that allows Embeddable Components to function correctly in production environments:

default-src 'self';
script-src 'self' https://embed.easypost.com 'unsafe-inline';
frame-src https://embed.easypost.com;
style-src 'self' https://assets.embed.easypost.com 'unsafe-inline' https:;
font-src https://assets.embed.easypost.com data: https:;
img-src https://assets.embed.easypost.com data:;
connect-src 'self' https://assets.embed.easypost.com;

Additional Resources

Please visit the Forge Help Center for more information.