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.
- A Forge-enabled EasyPost account
- A server endpoint capable of fetching a session ID from the EasyPost EmbeddableSessions API
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_hostThe integrator’s domain in bare-host format (e.g., example.com), excluding protocol and subdomains.
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)
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.
<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>
- The browser loads the EasyPost Embeddables script from https://embed.easypost.com/embeddables/1.0/client.js(opens in a new tab).
- When
onLoadfires, the integrator’s client initializes the SDK usingEasyPostEmbeddables.init(). - The
fetchSessionId()callback retrieves or refreshes the session ID as needed. - When a button is clicked, the
open()method launches the requested component inside a modal. - 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.
Option | Required | Description |
|---|---|---|
| fetchSessionId | Yes | Callback that returns a Promise resolving to a valid session ID fetched from the integrator’s server. |
| fonts | No | Optional array of font configuration objects. Each font can specify a cssSrc, src, family, style, and weight. See the Fonts section below for additional details. |
| appearance | No | Controls theming and modal layout options, including color tokens, font settings, and an optional modalZIndex for layering above or below existing UI. |
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:
-
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-facerules.EasyPostEmbeddables.init({ fonts: [{ cssSrc: 'https://fonts.googleapis.com/css2?family=Zen+Dots&display=swap' }], }); -
Direct Font Files: Use this form to load a font file directly. Note that in this form,
familyandsrcare required.EasyPostEmbeddables.init({ fonts: [ { family: 'Avenir', src: 'https://example.com/fonts/avenir.woff2', style: 'normal', weight: '400', }, ], });
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.
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\"" }
}
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): void | Registers 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): void | Removes 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(): void | Destroys the Embeddables iframe and removes all associated event handlers. Once called, a new instance must be re-initialized with EasyPostEmbeddables.init(). |
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.
The Billing Management component is accessed by passing "manage-billing" to the open() function on the created Embeddables instance.
The Carrier Management component is accessed by passing "manage-carriers" to the open() function on the created Embeddables instance.
The Payment Logs component is accessed by passing "manage-payment-logs" to the open() function on the created Embeddables instance.
The Reports component is accessed by passing "manage-reports" to the open() function on the created Embeddables instance.
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;
Please visit the Forge Help Center for more information.