KYC & AML Hosted SDK Integration
Partner Integration Guide
Integrate Wedbush Hosted KYC into your web application with a script tag and a few lines of JavaScript.
Customers can complete identity verification in a secure Wedbush window inside your apps. Your app starts the flow and receives the result — you do not host KYC screens or store Wedbush system credentials.
Before you start
Wedbush will provide:
- Partner SDK key — public key used in the browser
- SDK script URL — CDN link to
wts-partner-sdk.min.js - Allowed website origins — for example,
https://app.yourcompany.com; this must match the origin where you load the SDK.
Serve your domain over HTTPS in production.
How it works
- A customer fills out account details on your app.
- Your app calls
WtsPartnerSdk.openKycIframe(...). - A Wedbush KYC window opens for review, status, and documents when needed.
- When the customer finishes or closes the window, your
onCompletecallback runs. - You save
externalIdandkycStatus, then update your UI.
The Flow:
Your app → Wedbush SDK → KYC window → onComplete → Your app
Step 1 — Add the SDK script
Place this before your application code, for example in index.html:
<script src="https://YOUR_CDN_HOST/wts-partner-sdk.min.js"></script>This exposes the global object window.WtsPartnerSdk.
Replace
YOUR_CDN_HOSTwith the URL Wedbush gives you.Staging -> hosted-kyc-assets.staging.wedbush.tech
Step 2 — Start a new KYC application
Collect applicant data in your own forms, then open KYC with that payload. The KYC window shows a read-only review of what you send; it does not replace your data-collection UI.
async function startKyc() {
if (!window.WtsPartnerSdk) {
console.error("Wedbush SDK failed to load");
return;
}
await window.WtsPartnerSdk.openKycIframe({
key: "YOUR_PARTNER_KEY",
// Use data your application already collected.
payload: {
customerType: "person",
customerData: {
firstName: "Jane",
lastName: "Doe",
emailAddress: "[email protected]",
documentSsn: "123456789",
birthdate: "1990-01-15",
phoneNumber: "+15551234567",
addresses: [
{
type: "legal",
line1: "123 Main St",
city: "New York",
state: "NY",
postalCode: "10001",
countryCode: "US",
},
],
},
},
onComplete: (result) => {
// Persist these values in your backend or session.
saveApplication({
externalId: result.externalId,
kycStatus: result.kycStatus,
completionStatus: result.status, // completed | closed | error
});
updateYourUi(result);
},
});
}Wire it to your button:
<button type="button" onclick="startKyc()">Submit Application</button>Step 3 — Handle the result
onComplete fields
onComplete fields| Field | Description |
|---|---|
externalId | Application ID — store this to resume later. |
kycStatus | Verification status from KYC. See the following table. |
status | How the window ended: completed, closed, or error. |
message | Optional error message when status is error. |
Always save the latest externalId and kycStatus when onComplete runs, including when the customer closes the window.
Step 4 — Resume an existing application
After the first successful start, reopen KYC with the saved ID. The customer skips the review form and lands on the current status or documents screen.
async function resumeKyc(externalId) {
await window.WtsPartnerSdk.openKycIframe({
key: "YOUR_PARTNER_KEY",
externalId,
onComplete: (result) => {
saveApplication({
externalId: result.externalId,
kycStatus: result.kycStatus,
completionStatus: result.status,
});
updateYourUi(result);
},
});
}API reference — openKycIframe
openKycIframeWtsPartnerSdk.openKycIframe(options): Promise<void>Options
| Option | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Your partner SDK key. |
payload | object | For new applications | Applicant data in the perform-KYC-style body. |
externalId | string | For resuming | Existing application ID. |
onComplete | function | Recommended | Called when the KYC window finishes or closes. |
environment | "local" | "staging" | "production" | No | Overrides the environment; it is usually inferred from the script URL. |
Pass either payload for a new application or externalId to resume an application. Do not use both as the primary path.
You do not configure Gateway or KYC UI URLs; the SDK includes them.
Framework examples
Vanilla JavaScript
<!DOCTYPE html>
<html>
<head>
<title>Open account</title>
<script src="https://YOUR_CDN_HOST/sdk/wts-partner-sdk.min.js"></script>
</head>
<body>
<button id="start">Submit Application</button>
<script>
const PARTNER_KEY = "YOUR_PARTNER_KEY";
let savedId = localStorage.getItem("kycExternalId") || "";
let savedStatus = localStorage.getItem("kycStatus") || "";
document.getElementById("start").onclick = async () => {
const options = {
key: PARTNER_KEY,
onComplete: (result) => {
if (result.externalId) {
savedId = result.externalId;
localStorage.setItem("kycExternalId", result.externalId);
}
if (result.kycStatus) {
savedStatus = result.kycStatus;
localStorage.setItem("kycStatus", result.kycStatus);
}
alert("KYC: " + savedStatus);
},
};
if (savedId) {
options.externalId = savedId;
} else {
options.payload = {
customerType: "person",
customerData: {
firstName: "Jane",
lastName: "Doe",
emailAddress: "[email protected]",
},
};
}
await WtsPartnerSdk.openKycIframe(options);
};
</script>
</body>
</html>React
async function startKyc({ partnerKey, payload, externalId, onDone }) {
const sdk = window.WtsPartnerSdk;
if (!sdk) {
throw new Error("Wedbush SDK not loaded");
}
await sdk.openKycIframe({
key: partnerKey,
payload: externalId ? undefined : payload,
externalId: externalId || undefined,
onComplete: onDone,
});
}
// Example button handler.
async function onClickSubmit() {
await startKyc({
partnerKey: process.env.REACT_APP_WTS_PARTNER_KEY,
payload: buildPayloadFromForm(),
onDone: (result) => {
setExternalId(result.externalId);
setKycStatus(result.kycStatus);
},
});
}Load the script in public/index.html or your host HTML, not through npm.
Angular
async startKyc(): Promise<void> {
const sdk = window.WtsPartnerSdk;
if (!sdk) {
this.error = "Wedbush SDK failed to load";
return;
}
await sdk.openKycIframe({
key: this.partnerKey,
payload: this.externalId ? undefined : this.buildPayload(),
externalId: this.externalId || undefined,
onComplete: (result) => {
if (result.externalId) {
this.externalId = result.externalId;
}
this.kycStatus = result.kycStatus;
},
});
}Add a TypeScript declaration if needed:
interface WtsCompleteResult {
externalId: string;
kycStatus: string;
status: "completed" | "closed" | "error";
message?: string;
}
interface Window {
WtsPartnerSdk?: {
openKycIframe: (options: {
key: string;
payload?: Record<string, unknown>;
externalId?: string;
environment?: "local" | "staging" | "production";
onComplete?: (result: WtsCompleteResult) => void;
}) => Promise<void>;
};
}Customer experience (what they see)
| Step | What happens |
|---|---|
| Review | The customer confirms the details your app sent (read-only). |
| Status | Shows verification status, can refresh, and may allow document uploads. |
| Documents | If required: passport front only; license or national ID front and back. |
| Done / Close | The result returns to your onComplete callback. |
Closing the window (×) still returns the latest status, so your buttons stay accurate.
Checklist for go-live
- Receive the partner key from Wedbush.
- Allowlist production origin(s), including the exact scheme and host, for example
https://app.example.com. - Add the SDK script URL to your pages.
- Test the new-application path with
payload. - Test the resume path with
externalId. - Persist
externalIdandkycStatusinonComplete. - Verify that the UI shows Approved, Denied, and Under Review correctly.
- Serve the site over HTTPS.
Troubleshooting
| Issue | What to check |
|---|---|
WtsPartnerSdk is undefined | Check the script URL, load order, and ad blockers. |
| Origin not allowed | Confirm that Wedbush allowlisted the exact origin, including https://. |
| Launch or session errors after refresh | Launch codes are one-time. Call openKycIframe again from your button. |
| Button still says Submit after KYC | Save the onComplete result and drive the UI from the stored status. |
| Resume shows Review again | Pass externalId only; do not send a new payload. |
Support
Contact your Wedbush partner manager or integration support for:
- Partner keys for staging and production
- Origin allowlist updates
- The SDK script URL for your environment
Updated 10 days ago