Web
This page details how to add the PayMitto iframe to your Web app
Legacy Web SDKFor customers using Web SDK versions prior to 4.0, see the Legacy Web SDK Integration Guide.
Overview
The PayMitto Web SDK is a money-transfer UI delivered as an iframe that you embed in your web application. Your host page initializes the SDK with a configuration payload and listens for transfer-related events using the window.rremit helper that wraps postMessage.
For authentication, the SDK supports two options:
- SLA token + session (recommended) — your backend mints a single-use, short-lived SLA token and your frontend passes it to the iframe.
- Encrypted resources (legacy) — your backend encrypts a sender-level access token with a customer-specific secret and your frontend passes the resulting string to the iframe.
ReadyRemit accepts both authentication mechanisms concurrently on v4.0+ of the Web SDK. New integrations should use the SLA-token flow. Existing customers can migrate on their own schedule — see Migration.
For the broader integration sequence (creating senders, fetching quotes, posting transfers from your backend), see the C2C via SDK guide.
Authentication
The Web SDK supports two authentication flows. Pick one per environment.
| Aspect | New flow (Recommended) | Legacy flow (Deprecated) |
|---|---|---|
| Secrets the customer manages | OAuth client_id / client_secret only | OAuth credentials plus a customer-specific encryption secret |
| OAuth token type used | Client-level (no sender_id) | Sender-level (with sender_id) |
| Backend endpoint customer calls | POST /v1/oauth/sla-token | None (customer encrypts locally) |
| Token passed to iframe | slaToken (single-use, 60 s TTL) | resources + customerId |
| Session lifetime | Bounded, sliding (see Session lifecycle) | Lifetime of the encrypted token |
Use the New Flow for new integrations. If you have an existing integration on the legacy flow, see Migration for the cutover playbook.
New Flow (Recommended)
The recommended flow is a three-step sequence: your backend obtains a client-level OAuth access token, exchanges it for an SLA token bound to a specific sender, and your frontend passes that SLA token to the iframe.
Step 1: Obtain a client-level access token
In your backend, mint a client-level OAuth access token using the standard client_credentials grant. A client-level token is obtained by calling the Get Access Token endpoint without a sender_id in the request body — see the Authentication guide for full details.
curl --request POST \
--url https://sandbox-api.readyremit.com/v1/oauth/token \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"client_id": "{{client_id}}",
"client_secret": "{{client_secret}}",
"audience": "https://sandbox-api.readyremit.com",
"grant_type": "client_credentials"
}'
Why nosender_idhere?Unlike the legacy flow, do not include
sender_idwhen obtaining the access token you'll use against the SLA-token endpoint. ThesenderIdis supplied to the SLA-token endpoint instead, which lets one client-level token mint SLA tokens for any sender in your account.
Step 2: Request an SLA token
In your backend, exchange the client-level access token for an SLA token bound to a specific sender. The SLA-token endpoint is co-located with POST /v1/oauth/token:
- Sandbox:
POST https://sandbox-api.readyremit.com/v1/oauth/sla-token - Production:
POST https://api.readyremit.com/v1/oauth/sla-token
curl --request POST \
--url https://sandbox-api.readyremit.com/v1/oauth/sla-token \
--header 'accept: application/json' \
--header 'authorization: Bearer {{client_level_access_token}}' \
--header 'content-type: application/json' \
--data '{ "senderId": "{{sender_id}}" }'A successful response returns 201 with:
{
"slaToken": "9f1c8e…",
"expiresIn": 60
}| Property | Description | Type |
|---|---|---|
slaToken | Single-use bearer credential. The Web SDK consumes it on initialization. | string |
expiresIn | Token lifetime in seconds. The token must be passed to the iframe within this window. | integer |
Operational constraints:
- Mint server-side only. The endpoint requires your
client_secret; never call it from the browser. - Single-use. The token is invalidated once the iframe consumes it. A page refresh requires a fresh SLA token.
- Short-lived. 60-second TTL. Mint on demand, immediately before initializing the iframe.
- One token per sender.
senderIdis required and bound to the resulting session.
Step 3: Pass the SLA token to the iframe
Deliver the slaToken from your backend to your frontend over an authenticated, HTTPS-only response, then pass it to the SDK's init call:
window.rremit.init(
{
sdkCore: {
slaToken, // returned from your backend's /v1/oauth/sla-token call
language: "en-US"
},
sdkFeatures: {
darkMode: false,
confetti: true
}
},
async (eventPayload) => {
// …same create-transfer callback as today…
}
);The create-transfer callback contract, window.rremit.completed(transferId), and window.rremit.failed(error) are unchanged from the legacy flow. See Iframe Integration for the full iframe wiring (helper instance, iframe element, callback handling).
Session lifecycle
-
The SDK consumes the
slaTokenimmediately on load and establishes its own session. You do not see or store a session identifier; the session is internal to the iframe. -
Default session lifetime is 900 seconds, capped at 1800 seconds. Override via
sdkCore.sessionTtl(integer seconds). -
The session extends automatically while the user is active in the iframe. No customer action required.
-
Extending the session from outside the iframe. If your host page expects activity that the iframe cannot see (for example, the user is interacting with your host shell rather than the SDK), call
window.rremit.activity()to extend the SDK session. -
Session expiry. When the session ends — whether by inactivity or by your host calling
window.rremit.logout()— the SDK postsreadyremit-logoutto the host. Register a handler to react:window.rremit.on("logout", () => { // e.g. remove the iframe from the DOM, navigate user back to your shell }); -
Re-initializing after expiry. To resume after a logout, mint a new SLA token from your backend and call
window.rremit.init(...)again with the fresh token.
Security considerations
- Treat the SLA token as a bearer credential despite its 60-second lifetime. Serve it to the browser only over HTTPS, in the response body of an authenticated request to your own backend, and never log it.
- Do not retry the SLA-token call from the browser on failure. Re-mint server-side instead.
- Use a client-level OAuth token (no
sender_id) when calling the SLA-token endpoint. This avoids issuing sender-scoped tokens through middle tiers. - Call the SLA-token endpoint at
https://sandbox-api.readyremit.com(sandbox) orhttps://api.readyremit.com(production). The iframe host (sandbox-sdk.readyremit.com/sdk.readyremit.com) is a separate domain and is not the backend target.
Error responses
The SLA-token endpoint returns the following customer-actionable errors:
| HTTP | error body | Cause | What to do |
|---|---|---|---|
| 400 | senderId required | Request body missing senderId. | Add the senderId field. |
| 401 | missing_or_invalid_authorization | Authorization header absent or not Bearer …. | Re-mint your client-level OAuth token and retry. |
| 401 | invalid_token | Bearer token rejected (expired, malformed, or revoked). | Re-mint your client-level OAuth token and retry. |
| 401 | unknown_customer | Token verified but the associated client is not provisioned for the Web SDK. | Contact ReadyRemit support. |
If the iframe shows a session-expired view after a successful SLA-token mint, treat it as session expiry and re-initialize the SDK with a fresh SLA token (see Session lifecycle).
Legacy Flow (Deprecated)
Soon-to-be-deprecatedThis authentication mechanism (encrypted
resources+customerId) is supported for existing v4.0+ integrations but no longer recommended for new integrations. ReadyRemit will continue acceptingx-resourcesuntil further notice; a removal date has not been set. New integrations should use the New Flow. Existing customers should plan a migration — see Migration.Note: this is unrelated to the pre-v4.0 SDK callout at the top of this page, which covers a different (older) Web SDK version.
The legacy authentication flow is a three-step sequence: your backend obtains a sender-level OAuth access token, encrypts it with a customer-specific secret to produce the resources string, and your frontend passes that string (along with customerId) to the iframe.
Step 1: Obtain a sender-level access token
In your backend, mint a sender-level OAuth access token by calling the Get Access Token endpoint with sender_id in the request body. See the Authentication guide for full details on sender-level vs. client-level tokens.
curl --request POST \
--url https://sandbox-api.readyremit.com/v1/oauth/token \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"client_id": "{{client_id}}",
"client_secret": "{{client_secret}}",
"audience": "https://sandbox-api.readyremit.com",
"grant_type": "client_credentials",
"sender_id": "{{sender_id}}"
}'Step 2: Encrypt the access token (resources)
resources)In your backend, encrypt the access token using a customer-specific encryption secret provided by ReadyRemit during onboarding. The encryption input is a JSON object of the form:
{ "token": "{{access_token}}" }Encrypting this payload yields the opaque resources string passed to the iframe.
Secret management is your responsibility. Store the customer-specific secret in a secrets manager (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault, etc.) and never embed it in frontend code or commit it to source control. ReadyRemit Technical Support provides encryption examples on request.
Step 3: Pass resources to the iframe
resources to the iframePass resources and customerId to the iframe via sdkCore instead of slaToken. The rest of the integration (iframe element, helper instance, create-transfer callback) is identical to the new-flow example shown in Iframe Integration — only the sdkCore fields differ:
const customerId = "<this will be provided by ReadyRemit>";
const resources = "<encrypted resources, generated in your backend>";
window.rremit.init(
{
sdkCore: {
customerId,
resources,
language: "en-US",
},
sdkFeatures: { darkMode: false, confetti: true }
},
async (eventPayload) => {
// …same create-transfer callback as the new flow…
}
);Resources/Token Security
Resources/Token SecurityIn the wrong hands, the ReadyRemit API access token used in the legacy flow can be used to view personal information about your users or create fraudulent transfers. Be sure to encrypt the token in your backend and only send the encrypted
resourcesstring to the frontend.If you suspect your customer-specific encryption secret has been exposed, contact ReadyRemit support to rotate it.
Migration
This section is for existing customers cutting over from the legacy encrypted-resources flow to the SLA-token + session flow within Web SDK v4.0+.
What changes
| Before (Legacy) | After (New) | |
|---|---|---|
| OAuth token type minted | Sender-level (sender_id in body) | Client-level (no sender_id in body) |
| Encryption step | Your backend encrypts { "token": ... } with a customer-specific secret | None — exchange the OAuth token for an SLA token via POST /v1/oauth/sla-token |
Fields in sdkCore | resources + customerId | slaToken |
| Secrets you manage | OAuth client_id / client_secret plus a customer-specific encryption secret | OAuth client_id / client_secret only |
What stays the same
- Iframe
srcURL and embedding pattern. - The
window.rremithelper API (init,completed,failed,on,activity,logout,postMessage). - All postMessage events visible to the host (
readyremit-create-transfer,readyremit-transfer-completed,readyremit-transfer-failed,readyremit-unload-iframe,readyremit-logout). - All
sdkFeatures(includingcustomStylestheming),sdkRtaf, andvirtualSenderAccountsconfiguration. - The
create-transfercallback shape (theeventPayloadyour backend submits to the ReadyRemit transfer API). - The OAuth
client_credentialsmechanism for obtaining access tokens (only the body changes — nosender_idin the new flow).
Migration checklist
- Verify your OAuth client supports client-level tokens (your
client_idis allowed to mint withoutsender_id). If unsure, run the cURL sample from Step 1 of the New Flow against the sandbox. If you receive an access token, you're set. - Add an SLA-token mint endpoint in your backend. Implement a backend route that authenticates your user, retrieves the user's
senderId, obtains a client-level OAuth token, andPOSTs to/v1/oauth/sla-token. Cache or re-mint the OAuth token per your existing strategy. - Update your frontend to call the new mint endpoint and pass
slaTokento the iframe. Replace theresources+customerIdpair insdkCorewithslaToken. - Remove the encryption step from your backend and decommission the customer-specific encryption secret from your code paths (you can leave the secret in your secrets manager until cutover is fully validated).
- Add a
window.rremit.on("logout", …)handler to react to session expiry (if not already in place). - Test end-to-end in sandbox. Verify a full transfer flow: SDK initializes, user completes a transfer,
create-transfercallback fires, transfer posts, confirmation renders. - Roll out per-environment. Sandbox → production. Both flows are accepted server-side concurrently, so a partial rollout is safe.
Rollback
Both flows are accepted concurrently by ReadyRemit, so reverting is a frontend-only change — ship a hotfix swapping slaToken back to resources / customerId in your sdkCore. No coordination with ReadyRemit is required.
FAQ
Do I need a new ReadyRemit account or new credentials?
No. Use the same client_id / client_secret. Only the OAuth call's request body changes (omit sender_id).
What happens to my customer-specific encryption secret?
You can stop using it after migration. ReadyRemit will retire customer-specific encryption secrets only after the legacy flow is removed.
Can I support both flows from one frontend?
Technically yes — omit slaToken or resources / customerId from sdkCore based on configuration — but it is not recommended. Pick one flow per environment.
My users have long sessions in my host app. Will their SDK session expire mid-flow?
The SDK session extends automatically while the user is active in the iframe. If you expect long idle periods inside the iframe or activity only in your host shell, call window.rremit.activity() on host-side user interaction to extend the SDK session.
Step 1. Add iframe and Integrate PayMitto Helper Instance
The Web SDK is loaded inside an iframe that your host page embeds. A small JavaScript helper (the ReadyRemit Helper Instance, loaded from snippet.min.js) wraps postMessage so your host page can initialize the SDK, react to events, and signal transfer completion.
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- ReadyRemit Helper Instance -->
<!-- use sandbox-sdk.readyremit.com for Sandbox and sdk.readyremit.com for Prod. -->
<script src="https://sandbox-sdk.readyremit.com/scripts/snippet.min.js"></script>
<!-- End ReadyRemit Helper Instance -->
<title>ReadyRemit Example</title>
</head>
<body>
<!-- Content of your website -->
<!-- It's required that the id of the iframe is set to be "readyremit-iframe" -->
<iframe
id="readyremit-iframe"
src="https://sandbox-sdk.readyremit.com"
allow="clipboard-read; clipboard-write; camera"
width="100%"
height="100%"
style="display: none;"
title="International & Domestic Transfers"
></iframe>
<script>
// Mint a fresh SLA token on your backend right before init — it's single-use and
// expires 60 seconds after issue. See Step 2 of the New Flow for the endpoint contract.
const slaToken = "{'<slaToken returned from your backend\\'s /v1/oauth/sla-token call>'}";
window.rremit.init(
{
sdkCore: {
slaToken,
language: "en-US",
},
sdkFeatures: {
darkMode: false,
confetti: true,
customStyles: {
foundations: {
colorPrimary: { light: "#934ae0", dark: "#A26FD8" }
}
}
},
virtualSenderAccounts: [
{
alias: "Main Checking",
last4: "1234",
balance: 100000,
srcProviderId: "your-internal-account-id"
}
]
},
async (eventPayload) => {
try {
// eventPayload: {
// language: string; // en-US | es-MX
// transfer: {
// quoteBy: string;
// quoteHistoryId: string;
// recipientId: string;
// recipientAccountId: string;
// fields: [{
// id: "VIRTUAL_SENDER_ACCOUNT_ID",
// type: "TEXT",
// value: string;
// }]
// };
// }
// TODO:
// 1. Post the transfer (eventPayload) to your server
// 2. In your backend, retrieve the quote details using the quoteHistoryId from the eventPayload
// 3. Post the transfer using the readyremit api with the data from eventPayload + the quote details from step 2
// The completed TransferId should be returned
// For more information, see Step 6 in the C2C via SDK guide
// https://developer.readyremit.com/docs/c2c-via-sdk#step-6-submit-the-transfer
//
// Example:
// let transferResponse = postTransferToServer(event.data.payload);
// let transferId = transferResponse.transferId;
// This message back to the iframe with the TransferId will render the confirmation screen
window.rremit.completed(transferId);
} catch (error) {
// the error object should match this structure
//{
// "response": {
// "data": {
// "code": 400,
// "message": "Insufficient funds"
// },
// }
//}
window.rremit.failed(error);
}
}
);
</script>
</body>
</html>Let's see what's happening in the code sample above (JavaScript Tab):
-
Line 7: PayMitto code snippet, it mostly works as a helper to communicate back and forth with the PayMitto SDK loaded in the iframe
-
Line 16: Iframe to load the PayMitto SDK. The iframe must have an id attribute with the value "readyremit-iframe".
-
Line 18: The PayMitto iframe URL is defined based on the environment (Sandbox or Production) and is the same as the one that was replaced earlier in the provided script.
-
Line 27: The
slaTokenis a single-use bearer credential returned by your backend's call toPOST /v1/oauth/sla-token(see New Flow Step 2). It has a 60-second TTL and must be minted immediately before initializing the iframe. If you're on the legacy auth flow, replace this withcustomerIdandresources— see Legacy Flow. -
Line 28: Initialize the PayMitto iframe. Parameter descriptions can be found in the spec below.
-
Lines 30-39: Core and features configuration. Theming is handled via
customStyleswithinsdkFeatures. See the SDK Theme Configuration guide for the full theming schema. -
Lines 41-48: Virtual Sender Accounts. Provides the SDK with a list of accounts the user can select to fund the transfer. See VirtualSenderAccounts for the full specification.
-
Line 50: This is your custom callback function. This callback is fired from the iframe when the user completes the transfer flow and wants to submit the transfer. For security purposes, the iframe does not complete the transfer but relies on your server to make the final API call to the PayMitto API. For more information, see Step 6 in the C2C via SDK guide. Here you'll receive an
eventPayloadthat containstransferandlanguage. -
Line 77: When you call your backend to complete the transfer, your backend will use its own server-side credentials (the same client-level OAuth token it used to mint the SLA token) to call the ReadyRemit API. The
slaTokenitself is consumed by the iframe on init and is not used for the transfer-posting call. -
Line 81: Once your server has completed the transfer with the PayMitto API, it will receive a Transfer ID in response. Here, we will post a message back to the iframe with the ID of the completed transfer.
-
Line 92: In the event of an error while attempting to post the transfer, your server should return an error (do not modify or alter it; we'll take care of that on our end).
Here, a message is sent back to the iframe with the error object, allowing it to be handled appropriately.
Step 2: Configuration & Styling
To initialize the PayMitto SDK, a message containing a payload is posted to the iframe. The specification for that payload is as follows:
Initialization Payload
| Property | Description | Type | Required |
|---|---|---|---|
| sdkCore | Core configuration for the SDK session | SDKCoreOptions | Yes |
| sdkFeatures | Feature flags and theme customization | SDKFeaturesOptions | No |
| sdkRtaf | RTAF (Real Time Account Funding) mode configuration | SDKRtafOptions | No |
| virtualSenderAccounts | Accounts from which funds will be debited | VirtualSenderAccounts | No |
SDKCoreOptions
| Property | Description | Type | Required | Supported |
|---|---|---|---|---|
slaToken | Single-use bearer token returned by the SLA-token endpoint. Required for the recommended authentication flow. Mutually exclusive with resources / customerId. See New Flow. | string | Yes (new flow) | |
sessionTtl | Optional session lifetime in seconds for the new flow. Defaults to 900, clamped to a maximum of 1800. | int | No | |
customerId | Deprecated. Customer ID provided during onboarding, paired with resources in the legacy flow. Not used in the new flow. See Legacy Flow. | string | Yes (legacy flow) | |
resources | Deprecated. Encrypted string containing a sender-level access token to connect to the ReadyRemit API. See Legacy Flow. | string | Yes (legacy flow) | |
language | Language of the remittance transfer flow. | string | No | en-US | es-MX |
idleTimeout | Timeout in milliseconds before the remittance session is canceled | int | No | |
defaultQuoteAmount | Default amount of a transfer. Can include decimal places for cents. | number | No |
Theming
Visual customization is configured via the customStyles property within sdkFeatures. For the full theming schema including foundations (colors, fonts) and component-level styling (buttons, inputs, loading screens), see the SDK Theme Configuration guide.
SDKFeaturesOptions
| Property | Description | Type | Required |
|---|---|---|---|
| iframeResize | This setting is used to enable dynamic iframe height adjustment. This should be enabled when the PayMitto iframe is placed inside a webpage with a layout that uses a dynamic height (not a fixed height). If your webpage layout has scrolling disabled on the body, then you should not use this option. If your page has a fixed header, also see scrollOffset. Before enabling it, read iframeResize and iframe styling. | bool | No |
| darkMode | Forces the iframe into dark mode regardless of browser settings | bool | No |
| defaultCountry | When a valid ISO3 code is provided, and the sender has missing fields, then the initial "Start a Transfer" screen is auto-filled with that code's country. A quote is automatically fetched, resulting in a filled transfer screen upon load. | string | No |
| useUnloadEvent | Enables the 'unloadEvent' when pressing the back button from the Home screen, causing the iframe to trigger an unload of itself through the parent application. In the scenario where the Web SDK is loaded within a parent application, you may want to use the built-in navigation of the Web SDK to have a user exit the SDK and return to the host application. | bool | No |
| customStyles | Theme configuration object. See the SDK Theme Configuration guide for the full schema. | object | No |
| confetti | Enables a confetti animation when a transaction is submitted | bool | No |
iframeResize and iframe styling
When iframeResize is enabled, the snippet owns the iframe's box. Each time the SDK reports a new height, the snippet writes these inline styles on #readyremit-iframe:
| Property | Value |
|---|---|
height | the SDK's measured content height |
min-height | the same value as height |
border | 0 |
padding | 0 |
Inline styles take precedence over your stylesheet, so a border or padding you declare for the iframe in CSS will be overridden. Both are cleared because they sit outside the content box — under box-sizing: border-box they would shrink the visible area to less than the height the SDK asked for, cutting off the bottom of the page. If you want a visual frame around the SDK, put the border and padding on a wrapper element instead of on the iframe.
Do not constrain the iframe's height. A fixed height, a max-height, or an ancestor shorter than the iframe will hide content rather than scroll it. In this mode your page is the scroller and the SDK suppresses its own scrollbars, so there is no inner scrollbar to fall back on and no visual indication that anything was cut off. Give the iframe and its ancestors room to grow to whatever height the SDK reports.
VirtualSenderAccounts
Virtual Sender Accounts provide the web SDK with a list of accounts from which funds will be debited. The web SDK will not initiate any fund transfers or money movement on its own.
When enabled, the SDK will display a dropdown menu showing the accounts and their balances. After a user selects an account, the SDK sends back a reference to that account. This allows you to identify which account to deduct funds from in your system.
Expected Payload for virtualSenderAccounts
The virtualSenderAccounts property expects an array of objects. Each object must match the following schema:
| Property | Description | Type | Required |
|---|---|---|---|
| alias | A user-friendly name for the account (e.g., "Main Checking"). | string | Yes |
| last4 | The last four digits of the account number are used to distinguish between accounts with the same alias. | number | Yes |
| balance | The current balance of the account. The SDK uses this to check if there are sufficient funds for a transfer. | number | Yes |
| srcProviderId | Your internal reference for the account, which you'll use to perform any necessary money movement. | string | Yes |
Handling Money Movement
Since the web SDK doesn't handle the money movement, it will include a new field inside fields array, VIRTUAL_SENDER_ACCOUNT_ID, in the eventPayload. This field provides the srcProviderId of the selected account, telling you which account needs to be updated or debited on your end.
eventPayload
When the user completes the transfer flow and clicks submit, the SDK fires the onCreateCallback with an eventPayload. This payload contains the transfer details your backend needs to call the PayMitto API.
RTAF ModeIf you are using RTAF mode, the eventPayload has a different structure. See the RTAF Integration Guide for details.
{
language: string; // e.g. "en-US"
transfer: {
quoteBy: string;
quoteHistoryId: string;
recipientId: string;
recipientAccountId: string;
fields: [{
id: "VIRTUAL_SENDER_ACCOUNT_ID",
type: "TEXT",
value: string;
}]
};
}transfer Properties
| Property | Description | Type |
|---|---|---|
| quoteBy | Indicates how the quote was generated (e.g., by send amount or receive amount) | string |
| quoteHistoryId | The ID of the quote generated during the transfer flow. Use this to retrieve quote details on your backend. | string |
| recipientId | The ID of the recipient selected by the user | string |
| recipientAccountId | The ID of the recipient's account selected for the transfer | string |
| fields | Additional fields returned by the SDK. When Virtual Sender Accounts are enabled, includes VIRTUAL_SENDER_ACCOUNT_ID. | array |
Your backend should:
- Retrieve the quote details using
quoteHistoryId - Call POST
/transferswith the transfer data and quote details - Return the
transferIdto the frontend - Call
rremit.completed(transferId)to show the confirmation screen, orrremit.failed(error)on failure
Snippet API Reference
The PayMitto snippet (snippet.min.js) exposes the window.rremit object with the following methods for communicating with the SDK iframe.
init
window.rremit.init(payload, onCreateCallback, onUnloadCallback, options)Initializes the SDK iframe with the provided configuration payload.
| Parameter | Type | Required | Description |
|---|---|---|---|
| payload | object | Yes | The initialization payload containing sdkCore, sdkFeatures, sdkRtaf, and/or virtualSenderAccounts |
| onCreateCallback | function | No | Called when the user submits a transfer. Receives eventPayload as the argument. |
| onUnloadCallback | function | No | Called when the SDK requests the iframe to be unloaded (e.g., user navigates back from home). |
| options | object | No | Host page options for the snippet. See options. |
completed
window.rremit.completed(transferId)Posts the completed transfer ID back to the SDK iframe to render the confirmation screen.
| Parameter | Type | Required | Description |
|---|---|---|---|
| transferId | string | Yes | The transfer ID returned by your backend |
failed
window.rremit.failed(error)Posts an error back to the SDK iframe so it can display the error to the user.
| Parameter | Type | Required | Description |
|---|---|---|---|
| error | object | Yes | Error object with response.data containing code and message fields |
Expected error structure:
{
response: {
data: {
code: 400,
message: "Insufficient funds"
}
}
}Session Activity & Logout
In addition to the transfer lifecycle methods above, the snippet exposes a small set of methods for coordinating session state between your host page and the SDK iframe. These let you keep an active SDK session alive while the user interacts with your surrounding page, end the SDK session when the user signs out of your app, and react when the SDK ends its own session.
activity
window.rremit.activity()Notifies the SDK of host-side user activity, resetting the SDK's inactivity timer (see idleTimeout in SDKCoreOptions). Call this when the user interacts with your surrounding page so that an actively-engaged user isn't logged out by the SDK's idle timeout. Takes no arguments.
logout
window.rremit.logout()Tells the SDK to end its current session and log the user out. Use this when the user signs out of your host application so the SDK session is terminated in step with it. Takes no arguments.
on
window.rremit.on(event, callback)Registers a callback for session lifecycle events emitted by the SDK iframe. Calling on again with the same event replaces the previously registered callback. These events are only delivered after init has run, since init installs the listener that dispatches them.
| Parameter | Type | Required | Description |
|---|---|---|---|
| event | string | Yes | One of activity, activity-ack, logout, logout-ack |
| callback | function | Yes | Invoked with no arguments when the corresponding event is received |
Events
| Event | Fired when |
|---|---|
activity | The SDK reports user activity occurring inside the iframe. |
activity-ack | The SDK acknowledges an activity() call sent from your page. |
logout | The SDK session ended (e.g. the user logged out or the session timed out). |
logout-ack | The SDK acknowledges a logout() call sent from your page. |
Example
// React when the SDK ends its session
window.rremit.on("logout", () => {
// The SDK session has ended — return the user to your app
window.location.assign("/dashboard");
});
// Keep your host session alive while the user is active in the SDK
window.rremit.on("activity", () => {
keepHostSessionAlive();
});options
The optional fourth argument to init. These options configure the snippet's behavior on your page, and are separate from the initialization payload sent to the SDK.
| Property | Description | Type | Required |
|---|---|---|---|
| debug | Emits diagnostic logs to console.log. See debug. | boolean | No |
| scrollOffset | Top inset in pixels applied to host page scrolls. See scrollOffset. | number | function | No |
debug
Enables verbose snippet logging, useful when diagnosing integration issues such as out-of-order calls, a missing iframe element, or unexpected message traffic between your page and the SDK. Defaults to false — no output is produced.
window.rremit.init(
payload,
onCreateCallback,
onUnloadCallback,
{ debug: true }
);What gets logged
When debug is enabled, you'll see two kinds of entries in the browser console:
snippet:call <method>— emitted whenever awindow.rremit.*method is called from your page. Use this to verify that your integration is invoking the snippet in the expected order. For example,snippet:call getIFrame {found: true}confirms the iframe element was located, while{found: false}indicates a missing or incorrectly-named<iframe id="readyremit-iframe">element.snippet:<event>— internal lifecycle traces such as the snippet receiving a postMessage from the SDK iframe, the initial handshake completing, or a previous listener being removed before re-initialization.
The internal lifecycle traces (snippet:<event>) you may encounter include:
snippet:execute/snippet:define— the snippet script ran and definedwindow.rremit.snippet:already defined in window— the snippet was loaded more than once; the duplicate load is a no-op.snippet: prevListener found, removing— a previousinitmessage listener was torn down before re-initializing.snippet:message received <type>— a postMessage arrived from the SDK iframe (e.g.readyremit-ready,readyremit-create-transfer).snippet:message readyremit-ready ignored— a duplicate ready handshake was received after init had already been sent.
Example: a healthy initialization
A normal startup handshake produces a sequence like this:
snippet:call init {hasPayload: true, hasOnCreate: true, hasOnUnload: true}
snippet:call getIFrame {found: true}
snippet:message received readyremit-ready
snippet:call postMessage {type: "readyremit-initiate"}Use it to localize a failed integration:
- If you see
getIFrame {found: false}, your<iframe id="readyremit-iframe">element is missing or incorrectly named. - If the sequence stalls before
snippet:message received readyremit-ready, the iframe never finished loading the SDK — verify the iframesrcand that it points at the correct environment.
Privacy & sensitive data
The snippet sanitizes log entries before emitting them. The encrypted resources token, your customer ID, and the full initialization and transfer payloads you pass to the SDK are never written to the log — for those, only structural metadata is recorded (method name, event type, and presence flags such as {hasPayload: true}).
Two identifiers are logged in full, by design, because they are what support needs to trace a transfer end to end:
completed(transferId)logs the rawtransferId.failed(error)logs the error'sname,message, andresponse.status. The error response body (response.data) is never logged.
That said, do not ship debug: true to production. The intended use is local development or a temporary capture during a support session. Once you've reproduced an issue, share the captured console output with PayMitto support.
scrollOffset
Tells the snippet how much room to leave at the top of your page whenever the SDK asks it to scroll.
When you need it
Only when iframeResize is enabled. In that mode the iframe is sized to its full content height and your page — not the iframe — is the scroller, so the SDK asks your page to scroll on each in-SDK navigation and when a modal opens.
If your page has a position: fixed header, those scrolls put the top of the SDK underneath it. scrollOffset is the height of that header.
Usage
// Static header
window.rremit.init(payload, onCreate, onUnload, { scrollOffset: 80 });// Header whose height changes — breakpoints, sticky-collapse, dismissible banners
const header = document.querySelector("#site-header");
window.rremit.init(payload, onCreate, onUnload, {
scrollOffset: () => header.offsetHeight,
});Prefer the function form for anything that isn't a fixed pixel height: it is re-read on every scroll, so it stays correct as the header changes. A number is read once, at init.
Behavior
- Defaults to
0. Omitting the option leaves scrolling exactly as it was before the option existed. - Applies to both scroll positions the SDK requests: scroll-to-top after navigation, and centering when a modal opens.
- Values that are not a finite positive number — a resolver that throws,
NaN, a negative, a numeric string, a non-number return — fall back to0. The scroll still happens; a bad offset never blocks navigation.
CSS-only alternativeIf you cannot change your
initcall, declare the inset in CSS on the iframe instead:#readyremit-iframe { scroll-margin-top: 80px; }The snippet leaves this in place when no
scrollOffsetis passed. Two limits: the value is static, so a media query is the only way to vary it by breakpoint, and it does not affect modal centering.
scroll-margin-topis safe to set this way because the snippet never writes it. Note that the same is not true ofborderandpadding— underiframeResizethe snippet overwrites both on the iframe. See iframeResize and iframe styling.
Updated 20 days ago

