Web

This page details how to add the PayMitto iframe to your Web app

📘

Legacy Web SDK

For 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.

AspectNew flow (Recommended)Legacy flow (Deprecated)
Secrets the customer managesOAuth client_id / client_secret onlyOAuth credentials plus a customer-specific encryption secret
OAuth token type usedClient-level (no sender_id)Sender-level (with sender_id)
Backend endpoint customer callsPOST /v1/oauth/sla-tokenNone (customer encrypts locally)
Token passed to iframeslaToken (single-use, 60 s TTL)resources + customerId
Session lifetimeBounded, 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 no sender_id here?

Unlike the legacy flow, do not include sender_id when obtaining the access token you'll use against the SLA-token endpoint. The senderId is 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
}
PropertyDescriptionType
slaTokenSingle-use bearer credential. The Web SDK consumes it on initialization.string
expiresInToken lifetime in seconds. The token must be passed to the iframe within this window.integer

Operational constraints:

  1. Mint server-side only. The endpoint requires your client_secret; never call it from the browser.
  2. Single-use. The token is invalidated once the iframe consumes it. A page refresh requires a fresh SLA token.
  3. Short-lived. 60-second TTL. Mint on demand, immediately before initializing the iframe.
  4. One token per sender. senderId is 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 slaToken immediately 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 posts readyremit-logout to 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) or https://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:

HTTPerror bodyCauseWhat to do
400senderId requiredRequest body missing senderId.Add the senderId field.
401missing_or_invalid_authorizationAuthorization header absent or not Bearer ….Re-mint your client-level OAuth token and retry.
401invalid_tokenBearer token rejected (expired, malformed, or revoked).Re-mint your client-level OAuth token and retry.
401unknown_customerToken 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-deprecated

This authentication mechanism (encrypted resources + customerId) is supported for existing v4.0+ integrations but no longer recommended for new integrations. ReadyRemit will continue accepting x-resources until 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)

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

Pass 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 Security

In 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 resources string 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 mintedSender-level (sender_id in body)Client-level (no sender_id in body)
Encryption stepYour backend encrypts { "token": ... } with a customer-specific secretNone — exchange the OAuth token for an SLA token via POST /v1/oauth/sla-token
Fields in sdkCoreresources + customerIdslaToken
Secrets you manageOAuth client_id / client_secret plus a customer-specific encryption secretOAuth client_id / client_secret only

What stays the same

  • Iframe src URL and embedding pattern.
  • The window.rremit helper 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 (including customStyles theming), sdkRtaf, and virtualSenderAccounts configuration.
  • The create-transfer callback shape (the eventPayload your backend submits to the ReadyRemit transfer API).
  • The OAuth client_credentials mechanism for obtaining access tokens (only the body changes — no sender_id in the new flow).

Migration checklist

  1. Verify your OAuth client supports client-level tokens (your client_id is allowed to mint without sender_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.
  2. 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, and POSTs to /v1/oauth/sla-token. Cache or re-mint the OAuth token per your existing strategy.
  3. Update your frontend to call the new mint endpoint and pass slaToken to the iframe. Replace the resources + customerId pair in sdkCore with slaToken.
  4. 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).
  5. Add a window.rremit.on("logout", …) handler to react to session expiry (if not already in place).
  6. Test end-to-end in sandbox. Verify a full transfer flow: SDK initializes, user completes a transfer, create-transfer callback fires, transfer posts, confirmation renders.
  7. 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 slaToken is a single-use bearer credential returned by your backend's call to POST /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 with customerId and resources — 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 customStyles within sdkFeatures. 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 eventPayload that contains transfer and language.

  • 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 slaToken itself 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

PropertyDescriptionTypeRequired
sdkCoreCore configuration for the SDK sessionSDKCoreOptionsYes
sdkFeaturesFeature flags and theme customizationSDKFeaturesOptionsNo
sdkRtafRTAF (Real Time Account Funding) mode configurationSDKRtafOptionsNo
virtualSenderAccountsAccounts from which funds will be debitedVirtualSenderAccountsNo

SDKCoreOptions

PropertyDescriptionTypeRequiredSupported
slaTokenSingle-use bearer token returned by the SLA-token endpoint. Required for the recommended authentication flow. Mutually exclusive with resources / customerId. See New Flow.stringYes (new flow)
sessionTtlOptional session lifetime in seconds for the new flow. Defaults to 900, clamped to a maximum of 1800.intNo
customerIdDeprecated. Customer ID provided during onboarding, paired with resources in the legacy flow. Not used in the new flow. See Legacy Flow.stringYes (legacy flow)
resourcesDeprecated. Encrypted string containing a sender-level access token to connect to the ReadyRemit API. See Legacy Flow.stringYes (legacy flow)
languageLanguage of the remittance transfer flow.stringNoen-US | es-MX
idleTimeoutTimeout in milliseconds before the remittance session is canceledintNo
defaultQuoteAmountDefault amount of a transfer. Can include decimal places for cents.numberNo

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

PropertyDescriptionTypeRequired
iframeResizeThis 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.boolNo
darkModeForces the iframe into dark mode regardless of browser settingsboolNo
defaultCountryWhen 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.stringNo
useUnloadEventEnables 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.boolNo
customStylesTheme configuration object. See the SDK Theme Configuration guide for the full schema.objectNo
confettiEnables a confetti animation when a transaction is submittedboolNo

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:

PropertyValue
heightthe SDK's measured content height
min-heightthe same value as height
border0
padding0

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:

PropertyDescriptionTypeRequired
aliasA user-friendly name for the account (e.g., "Main Checking").stringYes
last4The last four digits of the account number are used to distinguish between accounts with the same alias.numberYes
balanceThe current balance of the account. The SDK uses this to check if there are sufficient funds for a transfer.numberYes
srcProviderIdYour internal reference for the account, which you'll use to perform any necessary money movement.stringYes

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 Mode

If 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

PropertyDescriptionType
quoteByIndicates how the quote was generated (e.g., by send amount or receive amount)string
quoteHistoryIdThe ID of the quote generated during the transfer flow. Use this to retrieve quote details on your backend.string
recipientIdThe ID of the recipient selected by the userstring
recipientAccountIdThe ID of the recipient's account selected for the transferstring
fieldsAdditional fields returned by the SDK. When Virtual Sender Accounts are enabled, includes VIRTUAL_SENDER_ACCOUNT_ID.array

Your backend should:

  1. Retrieve the quote details using quoteHistoryId
  2. Call POST /transfers with the transfer data and quote details
  3. Return the transferId to the frontend
  4. Call rremit.completed(transferId) to show the confirmation screen, or rremit.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.

ParameterTypeRequiredDescription
payloadobjectYesThe initialization payload containing sdkCore, sdkFeatures, sdkRtaf, and/or virtualSenderAccounts
onCreateCallbackfunctionNoCalled when the user submits a transfer. Receives eventPayload as the argument.
onUnloadCallbackfunctionNoCalled when the SDK requests the iframe to be unloaded (e.g., user navigates back from home).
optionsobjectNoHost 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.

ParameterTypeRequiredDescription
transferIdstringYesThe 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.

ParameterTypeRequiredDescription
errorobjectYesError 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.

ParameterTypeRequiredDescription
eventstringYesOne of activity, activity-ack, logout, logout-ack
callbackfunctionYesInvoked with no arguments when the corresponding event is received

Events

EventFired when
activityThe SDK reports user activity occurring inside the iframe.
activity-ackThe SDK acknowledges an activity() call sent from your page.
logoutThe SDK session ended (e.g. the user logged out or the session timed out).
logout-ackThe 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.

PropertyDescriptionTypeRequired
debugEmits diagnostic logs to console.log. See debug.booleanNo
scrollOffsetTop inset in pixels applied to host page scrolls. See scrollOffset.number | functionNo

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 a window.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 defined window.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 previous init message 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 iframe src and 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 raw transferId.
  • failed(error) logs the error's name, message, and response.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 to 0. The scroll still happens; a bad offset never blocks navigation.
📘

CSS-only alternative

If you cannot change your init call, declare the inset in CSS on the iframe instead:

#readyremit-iframe {
  scroll-margin-top: 80px;
}

The snippet leaves this in place when no scrollOffset is 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-top is safe to set this way because the snippet never writes it. Note that the same is not true of border and padding — under iframeResize the snippet overwrites both on the iframe. See iframeResize and iframe styling.


Did this page help you?