Web SDK authentication
Authentication is how your backend lets the Web SDK act on behalf of an account holder without ever exposing your credentials in the browser. This guide covers both supported flows, so you can pick the right one and, if needed, migrate.
Before you begin
- Have your PayMitto API credentials stored securely on your backend. See Securely storing API credentials.
- Add the iframe to your page. See Web SDK.
What you'll do
- Choose a flow. New integrations should use the new flow.
- Mint a token on your backend and pass it to the iframe.
- Handle the session lifecycle.
The Web SDK supports two authentication flows. Pick one per environment.
| Aspect | New flow (recommended) | Legacy flow (deprecated) |
|---|---|---|
| Secrets you manage | 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, short-lived) | 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 on your backend only. The endpoint requires your client level access token; 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. 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. -
Sessions time out after a period of inactivity. You can set the session lifetime with
sdkCore.sessionTtl(integer seconds), up to a maximum PayMitto applies. -
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.
Tokens at a glance
| Token | Notes |
|---|---|
| Client level access token | The expires_in value in the token response tells you how long it lasts. Request a new one before it expires. |
| SLA token | Single-use. Request it right before you initialize the iframe. |
| SDK session | Times out after inactivity |
Security considerations
- Treat the SLA token as a bearer credential, even though it is single-use. 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 on your backend 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 PayMitto 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)
DeprecatedThis authentication mechanism (encrypted
resources+customerId) is supported for existing v4.0+ integrations but no longer recommended for new integrations. PayMitto 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 PayMitto 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 your secrets manager and never embed it in frontend code or commit it to source control. PayMitto 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 PayMitto>";
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 PayMitto 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 PayMitto 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 PayMitto 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 on your backend concurrently, so a partial rollout is safe.
Rollback
Both flows are accepted concurrently by PayMitto, so reverting is a frontend-only change: ship a hotfix swapping slaToken back to resources / customerId in your sdkCore. No coordination with PayMitto is required.
FAQ
Do I need a new PayMitto 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. PayMitto 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.
Next steps
- Snippet API reference: session methods such as
activityandlogout. - Your first sandbox transfer: put the SLA token flow to work end to end.
- Transfer status updates: receive status changes after a transfer is submitted.
Updated about 17 hours ago

