@melio-eng/web-sdk
v1.5.0
Published
Melio Web SDK - Embed core Melio workflows directly into partner UI with minimal effort
Maintainers
Readme
Melio Web SDK
The Melio Web SDK allows partners to embed core Melio workflows directly into the partner UI with minimal effort. It provides a high-level API for launching flows such as onboarding and pay flow, while managing authentication, lifecycle, and secure communication under the hood.
📚 Documentation
- Pay Flow Integration Guide — the full end-to-end guide for embedding Melio payments (backend
preparecall, auth code, SDK setup, events, testing checklist). Start here. - SDK Reference — auto-generated API reference for every class, config, and event.
🚀 Quick Start
Installation
npm install @melio-eng/web-sdkBasic Usage
import { MelioSDK } from "@melio-eng/web-sdk";
// Create SDK instance
const melioSDK = new MelioSDK();
// Initialize the SDK with your authorization code
const init = melioSDK.init("AUTH_CODE_FROM_YOUR_BACKEND", {
partnerName: "your-partner-name", // required
environment: "production", // optional — defaults to 'production'
keepAlive: true, // optional — keeps the session warm
debug: false, // optional — verbose console diagnostics
});
init.on("authenticationSucceeded", () => {
// Open the Pay Flow with the Melio bill IDs returned by /pay-flow/prepare
const payFlow = melioSDK.openPayFlow({
containerId: "melio-payflow-container",
billIds: ["bill_abc123"],
billIdType: "melio",
});
payFlow.on("completed", (data) => {
console.log("Payment completed:", data);
});
});
init.on("authenticationFailed", () => {
// Re-mint the auth code on your backend and retry
});The full integration (backend
POST /pay-flow/prepare, minting the auth code, and handling every event) is documented in the Pay Flow Integration Guide.
📖 API Reference
Initialization
melioSDK.init(authenticationCode: string, options: InitOptions): InitFlowInstanceParameters:
authenticationCode(string, required): short-lived, user-scoped code minted on your backendoptions(InitOptions, required): Configuration optionspartnerName(string, required): The partner name for the SDK instancekeepAlive(boolean): If true, the session will be kept alive in the background via an invisible iframedebug(boolean): If true, the SDK prints debug-level diagnostics to the console. Warnings and errors always printenvironment(Environment): The environment to use for API endpoints (defaults to'production')branchOverride(string): Advanced/testing only
init returns an InitFlowInstance you can listen on for authenticationSucceeded / authenticationFailed.
Debug logging
Every SDK console line is prefixed with [melio-sdk], so you can filter it out of a busy
host page. Warnings and errors — a flow whose iframe never loaded, a failed authentication,
a MELIO_ERROR from the embedded app — always print. Pass debug: true to also get the
step-by-step trace: the host environment, the redacted flow URLs, iframe load timings and
every message received from the iframe. Credentials and customer details are redacted.
Environment Configuration
The SDK supports multiple environments to facilitate development and testing:
// Production (default)
melioSDK.init("auth_code", { partnerName: "your-partner-name", environment: "production" });
// Staging
melioSDK.init("auth_code", { partnerName: "your-partner-name", environment: "staging01" });
// Public QA
melioSDK.init("auth_code", { partnerName: "your-partner-name", environment: "public-qa" });
// Certification
melioSDK.init("auth_code", { partnerName: "your-partner-name", environment: "certification" });
// Localhost (for local development)
melioSDK.init("auth_code", { partnerName: "your-partner-name", environment: "localhost" });Each environment uses a different base URL:
| Environment | SDK environment | API base URL |
|---|---|---|
| Production | production (default) | https://partnerships.melioservices.com |
| Staging | staging01 | https://partnerships.staging01.melioservices.com |
| Public QA | public-qa | https://partnerships.public-qa.melioservices.com |
| Certification | certification | https://partnerships.certification.melioservices.com |
| Localhost | localhost | http://localhost:3005 |
Flow Methods
Pay Flow
Pay one or more bills. Pass the Melio bill IDs returned by POST /pay-flow/prepare together with billIdType: "melio".
melioSDK.openPayFlow(config: PayFlowConfig): FlowInstancebillIdType controls how the platform resolves billIds (defaults to "accounting"):
"melio"—billIdsare Melio bill IDs from/pay-flow/prepare; the payment screen opens directly. Use this for the prepare-based pay-flow integration."accounting"—billIdsare external accounting-software IDs, imported on demand (for accounting-software partners such as Xero / QuickBooks).
Just Pay Flow
Vendor-based payment (start from a vendor rather than a specific bill).
melioSDK.openJustPayFlow(config: JustPayFlowConfig): FlowInstanceOptionally pass defaultCurrency (an ISO 4217 code such as "USD") to set the currency on
synced vendors that have none in your accounting software. Vendors that already carry a
currency keep it. Omit it and Melio picks the default.
Payments Dashboard Flow
Let users view and manage their payments inside your product.
melioSDK.openPaymentsDashboard(config: PaymentsDashboardConfig): FlowInstanceOnboarding Flow
Collect any missing account / KYC information directly in Melio.
melioSDK.openOnboarding(config: OnboardingConfig): FlowInstanceSettings Flow
Host Melio account settings within your product.
melioSDK.openSettings(config: SettingsConfig): FlowInstanceEntry Point (entryPoint)
PayFlowConfig, JustPayFlowConfig and OnboardingConfig accept an optional entryPoint — which
page of your product the user came from. Melio uses it to word the button that ends the flow:
| entryPoint | return button reads |
|---|---|
| "bills" | "Back to bills" |
| "contacts" | "Back to contacts" |
| "quickpayment" | "Back to quick payment" |
| "managepayments" | "Back to manage payments" |
| "home" | "Back to homepage" |
| "generic" | "Finish and return" |
| omitted | today's default wording |
It's wording only — the completed event carries no destination, so your app still handles
navigation. On the Pay Flow, it has no effect when billIdType is "melio". See
Entry point in the full guide for a worked example.
Event Handling
Each flow method returns a FlowInstance that allows you to register event listeners:
const flow = melioSDK.openPayFlow({
containerId: "melio-payflow-container",
billIds: ["bill_abc123"],
billIdType: "melio",
});
flow.on("loaded", () => console.log("Flow rendered"));
flow.on("completed", (data) => console.log("Payment completed:", data));
flow.on("error", (err) => console.warn("Flow error:", err.errorCode));
flow.on("exit", () => console.log("User exited the flow"));
flow.on("navigated", (p) => console.log("Navigated to:", p.target));Available Events:
loaded: The flow iframe has renderedcompleted: The user successfully finished a flowerror: A flow error occurred (billsSyncFailed, orvendorsSyncFailedin the Just Pay flow)exit: The user exited the iframenavigated: Navigation occurred inside the iframebuttonClicked: The user clicked a button whose destination is in your product (see below)authenticationSucceeded/authenticationFailed: emitted on theinitinstance
Button clicks (buttonClicked)
Some Melio screens contain buttons whose destination lives in your product, not in Melio — today the "+ Quick payment" button on the payments dashboard, which should take the user to your own supplier selection page. Melio cannot navigate the host page, so it reports the click and waits for you:
const dashboard = melioSDK.openPaymentsDashboard({
containerId: "melio-dashboard-container",
});
dashboard.on("buttonClicked", ({ type }) => {
if (type === "quickPayment") {
window.location.assign("/suppliers/select");
}
});| type | Emitted when | What you should do |
|---|---|---|
| quickPayment | The user clicks the quick payment button on the payments dashboard | Take them to your supplier selection page, then open a pay flow |
Without a listener the button does nothing at all. Only buttons whose destination is in your
product are reported here — buttons that end a flow keep their existing events, so "Back to
bills" still arrives as completed. Further button types ship in minor releases, so switch on
type and treat an unrecognised value as a no-op.
💡 Examples
Pay Flow
const payFlow = melioSDK.openPayFlow({
containerId: "melio-payflow-container",
billIds: ["bill_abc123", "bill_def456"], // Melio bill IDs from /pay-flow/prepare
billIdType: "melio",
});
payFlow.on("completed", (data) => {
console.log("Payment completed:", data);
});
payFlow.on("exit", () => {
console.log("User exited the payment flow");
});Development with Staging Environment
const init = melioSDK.init("your_auth_code", {
partnerName: "your-partner-name",
environment: "staging01",
keepAlive: true,
});
init.on("authenticationSucceeded", () => {
melioSDK.openPayFlow({
containerId: "payment-container",
billIds: ["bill_abc123"],
billIdType: "melio",
});
});Onboarding
const onboarding = melioSDK.openOnboarding({
containerId: "onboarding-container",
});
onboarding.on("completed", (data) => {
console.log("User completed onboarding:", data);
});🧪 Running the Examples Locally
The repository includes interactive examples that demonstrate the SDK functionality. They render a partner-style accounting UI (navigation, tabs, a bills table with single and batch selection) and wire the SDK into it end-to-end.
# Serve all examples in the /examples directory
npm run examplesThen open the example HTML files (e.g. http://localhost:3009/examples/basic-usage.html or http://localhost:3009/examples/bill-pay-example.html).
The bill-pay example demonstrates:
- Automatic SDK initialization on page load
- Interactive bill management: checkbox selection for batch payments, individual "Pay bill" buttons, real-time totals, and status updates after completion
- Full integration: how the SDK slots into an existing partner interface
- Event logging for every flow lifecycle event
🔄 Session Keep-Alive
When keepAlive: true is passed to init(), the SDK renders a hidden 1x1 pixel iframe that points to Melio's authentication endpoint. This iframe:
- Periodically sends
USER_ACTIVE_PINGpostMessages to Melio - Prevents session expiration during long-lived host app sessions
- Is invisible to the user and does not impact the layout
This mechanism avoids redundant SSO handshakes and ensures seamless flow launches without delays.
🏗️ How It Works
Session Initialization
- SDK uses the authorization code to perform a token exchange with Melio
- Melio receives the user's identity from the partner
- Melio generates a new access token and initializes the session used for iframe-based flows
- A valid session is stored in local/session storage
- All future flows reuse this session if it is still valid
iframe Injection
- SDK creates and injects an iframe into the specified
containerId - It builds an
authUrlwith token, target, entrypoint, and context (e.g., billIds)
Communication
- SDK and Melio iframe communicate using
postMessage - Navigation, height, session, and errors are synchronized
🛠️ Development
Building
npm run buildDocumentation
npm run docs # generate the SDK reference + guides
npm run docs:serve # generate docs and start a local server
npm run docs:view # view already-generated docsTesting
npm test📋 Requirements
- Modern browser with ES2020 support
- HTTPS environment (required for iframe communication)
- Valid Melio partner authorization code
🔒 Security
- All communication is done over HTTPS
- Origin validation for postMessage communication
- Session tokens are managed securely
- Your API key is used server-to-server only — never in the browser
🤝 Support
For support, please contact the Melio team or create an issue in this repository.
📄 License
MIT
