Embedded checkout
If you'd rather keep the payment form inside your own page, without redirecting the customer to another domain, use embedded checkout: a public script that mounts an iframe with Paytami's payment form.
It's more integration work than hosted checkout — still the right choice when you don't want any page jump during payment.
The flow
Just like hosted checkout, start by creating the payment from your backend with POST /v1/payments (see that guide for the details). The difference is step 2: instead of redirecting, you mount the iframe in the customer's browser.
1. Include the script on your page
<div id="paytami-slot"></div>
<script
src="https://link.paytami.com/checkout.js"
integrity="sha384-..."
crossorigin="anonymous"
></script>WARNING
The integrity value changes with every published version of checkout.js. Recalculate it against the real script before shipping to production:
curl -s https://link.paytami.com/checkout.js | openssl dgst -sha384 -binary | openssl base64 -A2. Initialize checkout with the pay_... you created
<script>
var checkout = new PaytamiCheckout({
paymentId: 'pay_8f2c1a9d4e6b7c0a1d2e3f40',
container: '#paytami-slot',
onSuccess: function (d) {
// UX signal only — don't activate the customer's access here.
},
onFailure: function (d) {
// The customer can retry.
},
onProcessing: function (d) {
// Asynchronous method (e.g. bank transfer), may take hours.
},
});
checkout.open();
</script>PaytamiCheckout accepts:
| Option | Type | Description |
|---|---|---|
paymentId | string (required) | The pay_... returned by POST /v1/payments. |
container | string | Element (required) | CSS selector or element to mount the iframe in. |
height | string | Iframe height. Defaults to 600px. |
onSuccess | (data: { paymentId }) => void | The customer completed the payment form flow. |
onFailure | (data: { paymentId }) => void | The payment attempt failed. |
onProcessing | (data: { paymentId }) => void | The payment landed on an asynchronous method, pending confirmation. |
3. Confirm the result from your backend
onSuccess is a signal to improve the on-page experience (e.g. show "you're all set!") — never proof that money actually moved. Before granting access or delivering the product, confirm with your api_key:
curl https://app.paytami.com/api/v1/payments/pay_8f2c1a9d4e6b7c0a1d2e3f40 \
-H "Authorization: Bearer sk_live_..."Only activate the customer's access once the response's status shows the payment actually completed.
When to use hosted instead of embedded
If you don't have a specific reason to keep the customer on your page, prefer hosted checkout: it's less code, updates itself (you never have to recalculate an integrity hash), and the resulting payment form is the same.

