Quickstart: Embedded payments SDK
Mount the WinkPG payment form inside your own checkout page with the browser loader.
The payer stays on your checkout page and the card fields are rendered inside a frame WinkPG serves. Your page keeps its own layout and flow, and neither your page nor your server ever touches a card number.
This is the redirect flow's sibling: the same page and the same session, mounted in place instead of navigated to. Set up the hosted page first, then come back here.
You need a hosted page id, an API key, and the origin your checkout is served from.
1. Authorize your origin to embed
Two settings have to line up, and a mismatch is the single most common reason an embed shows nothing.
Add your checkout's domain to the hosted page's allowed embedding domains in the portal. Wildcards such as *.example.com work; raw IP addresses, localhost, and entries with no top-level domain are rejected.
Then name the exact origin on every session you create. If the origin is omitted the session still works for a redirect, but the message channel the loader depends on stays closed, and your page receives nothing.
2. Create the session on your server
curl -X POST "https://your-gateway-host/api/hostedpaymentpages/sessions" \
-H "api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"hostedPageId": "{hostedPageId}",
"label": "Order 1042",
"parentOrigin": "https://checkout.example.com",
"amountMode": "Locked",
"prefilledFields": { "base_amount": "10.00" },
"expirySeconds": 900
}'
The response carries hppUrl, the absolute address the frame will point at, already resolved against the payment host. Hand that value back to your page. There's no second call to make for it:
{
"sessionId": "3f1c...",
"shortToken": "aB3kX9mZqR7T",
"hppUrl": "https://pay.your-environment.example/pay/s/aB3kX9mZqR7T",
"expiresAt": "2026-01-01T18:30:00Z",
"label": "Order 1042"
}
Keep the call on the server. The API key must never reach the browser: a key in page source is a credential anyone who views source can use.
3. Add the script
<script src="https://pay.your-environment.example/sdk/v1/pay.js"></script>
The loader is a few hundred bytes. It resolves the release your payment host is actually serving, injects the payment code with its integrity attribute already applied, and assigns a window global.
The name of that global is a per-deployment value, so no single name this page could print would be right everywhere. Your administrator reads it off the branding settings. The examples below call it PaySdk:
var PaySdk = window.YourConfiguredGlobalName;
https://pay.your-environment.example is a placeholder and doesn't resolve. Your administrator has the payment host for your environment.
4. Mount the form
<div id="checkout"></div>
<script>
var payment = PaySdk.mount('#checkout', {
sessionUrl: SESSION_URL_FROM_YOUR_SERVER,
onComplete: function (outcome) {
window.location = '/order/confirmed?ref=' + encodeURIComponent(outcome.transactionId);
},
onFailed: function (outcome) {
showMessage(outcome.responseMessage || outcome.reason || 'That payment was not approved.');
},
onCancelled: function () {
window.location = '/cart';
},
onSessionInvalid: function () {
showMessage('This checkout is no longer usable. Start again to get a fresh one.');
}
});
</script>
The container is an element or a CSS selector. A selector matching nothing throws straight away, on the page that set it up, rather than failing in front of a payer with no explanation.
In a single-page application, call payment.destroy() when the view unmounts. Leaving the frame and its message listener attached across a route change is the reliable way to end up with two mounts competing for one page.
5. Confirm from the webhook, not from the callback
onComplete is what you show the person looking at the screen. The webhook is the record. A browser that loses its connection between the approval and the callback leaves your page with nothing and your server with a real payment, so the reconciliation path has to be the delivery your server receives.
Next steps
- Quickstart: Webhooks sets up the receiver that confirms these payments.
- The embedded payments SDK is the full reference: every option, every event, script pinning, and the Content Security Policy your page needs.
- Embedded payments compared with direct card scripts covers why the card fields live in a frame.