Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
If you want to learn more about the XRP Ledger first (concepts, transaction types, etc.) we have a great resource for you at https://learn.xumm.dev:
Xaman allows developers and app users to "meet up".
While app users can simply use the Xaman application interact with the XRP Ledger with their accounts, balances and transactions, the true power of Xaman is unleashed through the platform available for developers.
This way users can interact with third party tools & platforms in the most secure and convenient way, while developers don't have to worry about wallet & key management.
XRP Ledger transactions are traditionally user initiated: users open their wallet, enter the destination, amount, etc. and then you submit a transaction. This is referred to as a Push Transaction.
In retail / e-commerce & third party interaction scenarios, the ideal flow is inverted: a Pull Transaction. The third party environment wants the user to sign a specific transaction, and a transaction to sign is offered to the user.
This is where the Xaman platform comes in. An XRP Ledger transaction template can be delivered to the end user through the Xaman platform. This is called a Sign Request.
The most convenient way to interact with the Xaman platform is through the JavaScript/TypeScript SDK: . There are also some other SDKs available for Backend use in other languages:
The Xaman platform allows for easy integration in your application & workflow. Make sure to check the documentation for your environment:
You focus on building your cool app. We make sure your app & Xaman users can interact. Safely & smoothly.
Welcome to the Xaman Developer Docs! Xaman is a powerful platform designed to make your interaction with the XRP Ledger (XRPL) seamless. Whether you are an experienced developer or just getting started, Xaman offers a range of features, including xApps, payloads, transaction signing, and much more. This documentation will guide you through the essentials to get you up and running in no time.
While app users can simply use the Xaman app to manage their XRP ledger accounts, balances and transactions, the true power of Xaman can be experienced through the Xaman SDK, using our platform made available for developers.
Want to dive straight in? You're one click away from the
QR scanning is an engaging way to have users interact with payloads, especially in physical mediums. It is simple, quick, and versatile.
Mobile payload delivery is essential for a seamless experience in mobile applications.
Payload delivery from your native iOS / Android app happens through "Deep Links".
Deep Linking allows your mobile app to communicate directly with the Xumm app, enabling users to interact with payloads effortlessly.
For a detailed guide on implementing mobile payload delivery through Deep Linking, please refer to the page.
Multi-Device Scenarios: In cases like desktop to mobile, users can scan the QR code on the desktop screen with their mobile device. Typically, there's no need for a return URL as the desktop browser can pick up the results.
How It Works: Generate a QR code for the payload using Xumm. Users scan this QR code with the Xumm app to access and interact with the payload.
For end users, QR scanning is intuitive and engaging. They scan the QR code with their mobile device and are immediately taken to the payload in the Xumm app. This method is particularly effective in retail environments or when users operate across multiple devices.
Deep linking in Xumm enables developers to provide a seamless user experience by swiftly guiding users to interact with payloads.
Deep Links are a well known flow to allow users to automatically launch and open another app in a specific state. Xumm allows for a Deep Link workflow, where your application (browser based or native) can trigger Xumm to open and immediately show your sign request.
When to Use: Opt for deep linking when you want to minimize user steps and create a fluid transition between your app and Xumm.
Device Compatibility: Deep linking works when the origin (your app or browser) and Xumm are on the same device (iOS/Android).
Link Creation: Generate a deep link that opens Xumm with the payload ready for interaction, making interactions more seamless while keeping users engaged.
Return URL: Set a return URL in the payload to redirect users back to your app or browser post-interaction, maintaining a smooth flow.
For web origins, users return to the default browser, not necessarily the original tab. In order to make this smooth, handle session restoration to ensure continuity.
For end users, deep linking is a breeze. They tap a link, interact with the payload in Xumm, and return to your app effortlessly.
To authorize a Payment Channel, an off ledger "receipt" must be signed. This is implemented in Xaman through a 'Pseudo Transaction' with TransactionType `PaymentChannelAuthorize`.
PaymentChannelAuthorize is normally a 'Command' or locally signed object. Implemented in Xumm as a TransactionType (which it actually isn't, also: the resulting signed blob can never be submitted to an XRPL node as is). For more information, see: https://xrpl.org/use-payment-channels.html
https://gist.github.com/WietseWind/c7b6addfd9b8cb465894209cc9073c47
Note: the PaymentChannelAuthorize transaction type is useful when you want to authorize a payment channel without submitting a transaction to the XRPL.
In Xaman, you can use all XRPL transaction types when sending a JSON transaction payload. However, some special transaction types are unique to Xaman, or require some extra info to use them.
Developers can use the Xumm SDK to easily interact with the Xumm platform. This section contains the technical documentation for the Javascript/TypeScript API (objects, methods, arguments).
Signature verification is crucial for ensuring the integrity and authenticity of the data received. It involves verifying that the data was sent by Xumm and has not been tampered with.
If you want to make sure a WebHook received by your platform has been sent by the Xumm platform, verify the signature the platform sends in an HTTP header.
Every WebHook call contains a signature to verify the authenticity. It sends an HMAC using your application secret as a key. Sample verification in NodeJS:
import crypto from 'crypto'
// Xumm App secret (Xumm developer console)
const secret = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
const timestamp = req.headers?.['x-xumm-request-timestamp'] || ''
const json = req.body
const hmac = crypto.createHmac('sha1', secret.replace('-', ''))
.update(timestamp + JSON.stringify(json))
.digest('hex')
console.log(hmac, hmac === req.headers?.['x-xumm-request-signature'])Get aggregated exchange rates vs. XRP for most fiat & crypto assets.
The getRates method allows you to get the exchange rates for an XRP <> requested pair. The source information is aggregated from several data providers.
const rate = await Sdk.getRates('BTC');{
"USD": 1,
"XRP": 0.52069,
"__meta": {
"currency": {
"en": "US Dollar",
"code": "USD",
"symbol": "$",
"isoDecimals": 4
}
}
}The Xaman SDK can be used to interact with Xaman users. An example can be a "sign request", where the user is asked to sign a transaction, identification (sign in) or a user interface presented in Xaman (xApp).
The Xaman SDK offers a ready to use Javascript & Typescript SDK for all frontend and backend projects. With only minor differences depending on the environment you are using the SDK in, the SDK is the most convenient way to interact with Xaman users & the Xaman ecosystem.
If you are not working in a Javascript/Typescript environment and prefer to build your own backend implementation, you can use our API (endpoint) documentation or use one of our SDKs for Python (PyPI), PHP (Packagist) or C# (NuGet)
Typescript / Javascript
XRPL Labs ⭐
/
Python
Community
C# (.NET)
Community
PHP
Community
Typescript / Javascript
XRPL Labs ⭐
/ CDN
Python
Community
C# (.NET)
Community
PHP
Community
Essential terms and concepts to help you better understand and utilize the powerful features of the Xaman Wallet platform.
Xaman
The self custodial wallet application for iOS and Android developed by XRPL Labs. The app can be used by end users to manage their XRP Ledger account(s) and interact with the "Xaman Platform" (see below) through "Sign Requests" (see below).
Xumm
The previous name of Xaman, Xaman is formerly known as Xumm (and has rebranded). Some references in these docs may still point to our old name.
Xumm Platform
The platform your application and the Xaman app (iOS/Android) interact with. For developers, the platform offers the ability to send "Sign Requests" (see below) to the platform's "API" (see below). The Sign Request can then be interacted with by Xaman app users.
Xaman API
The endpoints providing features to developers & integrated applications. The API endpoint reference can be found here: but a more convenient way to interact with the Xaman Platform is through our SDK's (packages):
Developer Console
The Developer Console is where you can get your credentials (API Key & secret) and configure your Xaman platform integration. You can find the Xaman Developer Console at
Documentation
This website:
Payload delivery in Xumm is a crucial step in the transaction lifecycle. It involves delivering the payload to the user for signing.
In Xumm, a payload is a sign request sent by applications or developers to users for interaction. Users review the payload and decide to reject or accept by signing.
Xumm offers various payload delivery methods:
Deep Linking: Open the Xumm app with the payload already loaded.
QR Code Scanning: Users scan a QR code to access the payload.
Push Notifications: Send payloads as push notifications.
After delivering a payload, tracking its status is vital to know whether the user has interacted with it. Xumm provides mechanisms for obtaining notifications and results of payload interactions. You can learn more about this in the section.
Now that you have an overview of what payload delivery entails in Xumm, you can delve into the specifics of each delivery method.
Xumm's Payload status updates bridge the gap between your application and the end user by providing real-time feedback on payload interactions.
When users interact with payloads, Xumm provides real-time status updates and results (e.g., rejected, signed with signature). These updates allow you to make your application user interface reflect the status of the interaction with the user, and return sign request results to your application.
Keep track of user interactions with the payload.
Update the UI to reflect statuses like "opened" or "signed".
They provide status but not the final resolved data (for security reasons, resolved data like signatures can only be separately fetched from the Xumm platform).
Receive real-time updates in your front-end and back-end.
Frontend: Keep the user informed about the status.
Backend: Determine when you can fetch final results.
This ensures responsiveness and keeps the end-user informed.
Webhook: Once the payload is resolved, a Webhook can be sent to your platform for backend processing. For more on WebHooks, see .
API/SDK: Alternatively, fetch the payload end results using the Xumm API or SDK for more control and flexibility.
Understanding the end user's workflow/experience is vital. The real-time status updates and Webhooks are not just technical tools but communication channels between your application and the user.
By effectively using these features, you ensure an engaging and informed experience for the user.
To prevent excessive load on our platform, the Xumm platform applies rate limits. The limits depend on the type of consumer (regular API, SDK, JWT) and endpoint(s).
On average, the Xumm platform allows API consumers to make between 60~200 calls per minute. These numbers depend on the load on the platform and the use of the API consumer.
Some endpoints have lower limits, e.g.:
POST a Payload (sign request) on average allows for sending 30 payloads per minute
Fetching TXs (no need to use our platform, best use a native XRPL WebSocket connection): 60 requests per minute
KYC status: 600 calls per minute
Account metadata: 120 calls per minute
These numbers are not guarantees: they are averages and can be adjusted by our platform on the fly, based on your overall API call behaviour & end user interaction(s).
If there are good reasons to assign elevated API limits, we're happy to have a discussion to hear about the reasons how your application consumes the Xumm API, and why your application needs higher limits. Please .
API limits will only be raised if:
Your app does not use polling techniques: to retrieve the status of a payload, use the websocket we provide for status updates (or the createAndSubscribe / subscribe method provided by the SDK: / ). Backend applications can also use a webhook: .
(If your app is an xApp) - Your app respects the xApp \
Polling, or repeated API calls, is a common method to fetch updates. However, in Xumm, it's not the recommended approach due to rate limits.
Instead of polling, consider these efficient alternatives:
Webhooks: Once a payload is resolved, Xumm can send a WebHook to your platform, eliminating the need for constant polling. Learn more: Webhooks.
Websocket Subscription: Use Websocket to receive live status updates. Learn more: Websocket.
Excessive polling can lead to your application being temporarily rate limited, disrupting your service. If your application has been rate limited, you will receive a notification email later the same day on the e-mail address entered in the application details in the .
Xumm supports a wide range of transaction types to cater to various use cases on the XRPL. Here's what you need to know:
Standard Transaction Types: Xumm accepts all mainnet XRPL transaction types.
Exception: Transaction types for non-voted in amendments may be unavailable
Payment Channel signature types (non-transaction, receipt) are not yet supported (to be added in Xumm 2.5.0)
Pseudo-Transaction Types: One pseudo-transaction type: SignIn -
Limited Transaction Types:: Some transaction types, such as setting a Regular Key or setting a Signer List (multisign), require special permission for user security reasons:
Setting a Regular Key
Setting a Signer List (multisign)
Trying to get your OAuth2 / OpenID integration to work? There are a couple of tools to help you test things.
Xumm Payloads: creating, delivering, and utilizing incomplete XRP Ledger transactions as a Sign Request to end users.
The difference between XRP Ledger Transaction JSON and a Xumm Payload is that the XRP Ledger JSON needs to be complete and signed locally, while a Xumm Payload can contain an incomplete transaction.
The incomplete transaction, referred to as a Transaction Template, can be delivered to Xumm users allowing end users to view the Payload in the form of a "Sign Request": a transaction to sign and submit, or reject.
Xumm will then add the missing fields like the signer account, network Fee, Account Sequence, based on the context the user provides.
Xumm Payloads use the exact same syntax as the XRP Ledger JSON transaction format.
Xumm's workflow is designed to streamline the process of transaction signing and interaction with the XRP Ledger.
Here's a step-by-step guide to understanding and implementing Xumm's workflow in your application:
Create a Payload: Start by using Xumm's API to create a payload. A payload is essentially a transaction template containing all the details for the transaction you want the User to sign.
Deliver the Payload to the User: Once the payload is created, you need to deliver it to the User for signing. Xumm offers multiple delivery options, including push notifications, QR codes, and deep links. Choose the method that best suits your application.
Xumm's transaction lifecycle is a sequence of steps that ensures secure and efficient transaction processing on the XRP Ledger.
Here's a comprehensive guide to understanding and implementing Xumm's transaction lifecycle:
Start by composing the transaction you want to be signed in JSON format, as per the . You can include all except "Account" and "Sequence", which will be automatically filled by Xumm.
Therefore, any JSON value you'd use to sign and send to an XRPL node can be sent to the Xumm SDK/API, with the (signing) account fields being added/filled being the only major difference.
CORS (Cross-Origin Resource Sharing) is a security feature that restricts a web page from accessing resources from another domain. Xumm allows for CORS calls to JWT endpoints.
CORS (Cross-Origin Resource Sharing) is a mechanism that allows a web page from one origin (domain) to access resources from another origin. In other words, it is a security feature implemented by web browsers that restricts a web page from making requests to a different domain than the one that served the web page.
The Xumm API endpoints allow cross origin requests: we want your web application to be able to make calls to the Xumm platform using the credential (JWT) you have received when a user logged in.
If you are building a integration, CORS is irrelevant.
If you are building something in the browser (a web application), the most convenient way to interact with the Xumm platform is through the Javascript/TypeScript SDK: .
The Xumm API/SDK is designed to be network-independent, providing flexibility for developers and end users. This means that the end user determines the network on which transactions occur.
However, a payload can include a forced network identifier to specify a particular network. When a user signs a payload, the result includes information about the network the user was on when signing, allowing developers to track and manage transactions across different networks.
For web applications accessed through desktop browsers, Xumm provides an optimized delivery method.
This includes options like QR code scanning and deep linking, adapted for larger screens.
If you can't already identify the user, refer to the
If you have already identified the user and obtained a user_token, refer to the
When building xApps, there are some tools to make building & sharing your xApp easier.
While developing your xApp, you may want to easily test & debug your web application. You may even benefit from live reaload during development. You can expose your local development environment with a tool like or and configure your public URL as your xApp URL.
You can get access to the remote browser console using the techniques explained in the article.
If you want to share your xApp with a small group of testers or team members, you can ask them for their Xumm Device Identifier (Xumm - Settings - Advanced). You can add up to 10 Device Identifiers as xApp testers, so they can open your sandboxed xApp.
If you simply want to offer users a static link / QR code to sign a specific XRPL transaction, you can craft a link (to be offered directly or as contents of a QR code) for users to click / scan.
Offering a direct link / QR code to a payload does not come with the advantages of creating a of getting live feedback & webhooks based on the user's engagement.
The advantage of a simple Sign Link / QR is that you can craft the link / QR once, and it will be available for all users without further code implementations.
Simple Sign Link/QR is available for the following transaction type(s)
TrustSet (adding a Trust Line, a.k.a. adding a Token)
After a user signs a payload, a user can return to a URL (your website / app).
The Return URL (return_url) determines where the user is sent when the payload is signed. If none is given, the user will simply be displayed Close button in Xumm. Otherwise, the user will be presented a button which launches the Return URL.
Warning! iOS and Android do not allow the user to return to the browser tab they came from (if your flow starts in a browser). Make sure you restore state based on the payload / session / custom identifier or custom metadata assigned to the payload.
The `SignIn` payload is a "Pseudo transaction type": an off ledger transaction specific to Xaman, which can be used to identify a user and obtain a token to push sign requests to the end user.
Note that the SignIn transaction type is already embedded in the Xaman SDK and OAuth flows. You only need the SignIn transaction type if you are manually building your own integrations (e.g. API integrations:)
The SignIn transaction type is Xaman specific, signature only, can never be submitted. When sending a JSON transaction payload, you can use all XRPL transaction types, including a Xumm-specific "pseudo transaction type": SignIn.
The payload for a SignIn transaction can look like this:
To route users to a simple payment request, all you need to use is a URL / QR containing that URL, crafted with the right parameters.
To easily link to transaction explorers, you can link to the Xumm explorer launchpad and allow users to pick their preferred explorer.
Fetch an XRPL transaction & metadata. Please don't use this method unless absolutely necessary: please set up your own connection to an XRPL node to fetch this information.
The getTransaction method allows you to get the transaction outcome (mainnet) live from the XRP ledger, as fetched for you by the XUMM backend.
Note: it's best to retrieve these results yourself instead of relying on the XUMM platform to get live XRPL transaction information! You can use the package to do this:
Returns:
Fetch the available (known) networks and network parameters.
The getRails method allows you to get the network information for all networks known to Xumm.
Returns:
Get NFT Token details. Only available in JWT context. Please fetch your NFT info from other NFT data sources if possible.
This method is only available when using the SDK in a
JWTcontext!
The getNftokenDetail method allows you to get basic XLS20 token information as fetched/parsed/cached for you by the XUMM backend.
Note: it's best to retrieve these results yourself instead of relying on the XUMM platform to get live XRPL transaction information!
Returns:
A sign request in Xumm is a prompt to approve a transaction or action on the XRP Ledger. This page will show you how you can create a Sign Request, and how you can deliver the request to the end user.
Get the meta information for all known Hooks. Object returned contains Hook hash as key, meta as value.
Sdk.getHookHashes()
The getHookHashes allows you to get all meta information for all Hooks known to Xumm.
Returns:
Contact the Xumm platform to check for connectivity and valid auth.
The ping method allows you to verify API access (valid credentials) and returns some info on your XUMM APP:
Returns :
User Interaction: The User will interact with the payload through the Xumm app. They have the option to either sign or reject the transaction.
Retrieve the Result: After the User has interacted with the payload, your application needs to retrieve the result Status updates. This can be done by fetching the result from Xumm's API. The result will indicate whether the User signed or rejected the transaction.
Interact with the XRP Ledger: If the User signed the transaction, your application can now interact with the XRP Ledger to finalize the transaction. This involves submitting the signed transaction to the XRP Ledger and handling any responses or confirmations.
Provide Feedback to the User: Finally, provide appropriate Feedback based on the transaction's outcome. This could be a confirmation message for a successful transaction or an error message if something went wrong.
By following these steps, you can effectively integrate Xumm's workflow into your application and leverage its features for secure and streamlined transactions on the XRP Ledger.
Network Independence: The Xumm API/SDK operates independently of the network, giving the end user the freedom to choose their preferred network in the Xumm app.
Network Information in Results: The results of a signed payload include information about the network the user was on at the time of signing.
Forced Network Identifier: A user can be on any network while signing. You must check for the expected result in the Payload results. Alternatively, you can include a forced network identifier in a payload to specify a particular network.
Network Information in OTT Data: xApp OTT data also includes network information, providing additional resources for developers to manage transactions.
User Experience: The choice of the network result in loss of goods or funds: imagine getting paid on Testnet, while delivering actual sold goods expecting a mainnet payment. It's important to consider this in your application development process.
A simple payment on Xahau for 2 XAH (native asset) to the rwietse... account:
A payment on the XRP Ledger for 2 $RLUSD to the rwietse... account:
https://xaman.app/detect/request:rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ?amount=2&network=XRPL&dt=123&issuer=rMxCKbEDwqr76QuheSUMdEGf4B9xJ8m5De¤cy=524C555344000000000000000000000000000000
If the user does not have Xaman installed, the above links will automatically fall back to a regular webpage showing the payment request information & download links to Xaman. If you however want to craft a link / QR that is not Xaman specific, you can use a protocol prefix which can be claimed by any XRPL supporting app in the ecosystem. The downside is that if one does not have a supporting app installed, there is no graceful fallback webpage.
Instead of prefixing with https://xaman.app/detect/request you can prefix with the xrpl:// protocol handler:
amount - The amount in native asset or issued currency to request - can be omitted, the user can then enter the amount
network - The network the transaction should be sent on, can be XRPL or XAHAU, can be omitted, defaults to XRPL
dt - The Destination Tag to send to - can be omitted
invoiceid - The InvoiceID to send, must be formatted in HEX according to the InvoiceID length specifications (64 hex chars) - usually omitted
issuer - The issuing account, only required combined with currency for requests in issued currencies
currency - The currency code, must be in three-char ALPHA notation or HEX notation for issued currencies with asset codes > 3 char length. Only required in combination with issuer for payments in issued assets.
For App/Platform developers, there's an easy JS lib. to decode strings & parse them into normalised objects to support payment requests (and other ecosystem data formats):
These headers return the results of the current requests allowed per minute, and the amount remaining in the current (sliding) minute.
API Documentation
API endpoint reference: https://xumm.readme.io/reference
Sign Request
When you send a call to the Xumm Platform to ask a user to sign a transaction, you are creating a "Sign Request". You are delivering a "Payload" (see below) to the Xumm platform, containing the transaction template you would like the user to sign & possibly some options. You obtain a unique UUID (identifier) to the Sign Request to get real time status updates, Webhooks upon status change & when signed: the on ledger Transaction Hash and signed transaction.
Payload
The Payload (JSON formatted) is part of a Sign Request. It contains the Transaction Template to offer to the end user to sign. The Payload matches the formatting, fields & properties of native XRP Ledger transactions, except for the fact that some fields (like Fee, Account, Sequence) can be omitted as Xaman can add these for you.
xApp
An xApp is a Web App (HTML, JS, CSS) that can be opened inside Xaman by users, straight from and in Xaman. See xApps ("dApps")
Frontend
When referred to Frontend, we refer to your frontend: the HTML/JS/CSS application you are building, where you are integrating Xaman as xApps ("dApps")or Browser ("Web3") application.
Backend
When referred to Backend, we refer to your backend application. If you are building an xApp or Web3 (Browser) app, you may not have and may not need your own backend. If you are building a backend integration (e.g. headless application, backend for your own Frontend application), please see Backend (SDK / API)
SDK
The most convenient way to interact with the Xaman Platform is through our SDK's (packages): https://docs.xumm.dev/#packages
JWT
JSON Web Token: the authorization bearer as provided by Xaman when using the xApps ("dApps") or Browser ("Web3") flow. Valid for 24h, bound to the Xum App user, you can call the Xaman platform to create Sign Requests & more.
OTT
"One Time Token", specific to xApps. Automatically handled for you when using our Javascript/Typescript SDK.
Account: If this field is part of the transaction template, it will be completely ignored, as the Account will be automatically filled based on the account the end user uses to sign the transaction with in the Xumm app.
Sequence: Based on the account used to sign by the end user in the Xumm app, the Sequence will be automatically filled by Xumm.
LastLedgerSequence: If a valid ledger index is entered in the LastLedgerSequence field, it will be passed on unchanged to the Xumm app. However, if a value < 32570 is entered, the Xumm app will automatically calculate the {current ledger index} + the given amount of ledgers, where {current ledger index} is based on the most recent closed ledger index at the moment the end user taps the button to accept & sign the sign request.
Configure Payload Options: Configure the payload options to customize the transaction request. Refer to the Payload Options Documentation for detailed information on the available options.
If you are using a backend flow, you can optionally include a user token. This token is specific to the user and can be used for personalized transactions.
Submit the payload to Xumm through the Xumm SDK or API. You can also use alternative language SDKs for this step. This initiates the transaction signing process.
The client, a mobile app, xApp, or desktop application, will interact with the payload. Implement logic to handle this interaction and guide the user through the signing process.
The user will either sign or reject the transaction. Your application should be ready to handle both outcomes and take appropriate action.
After resolution, retrieve the payload results to understand the outcome of the transaction. You can use WebHooks, and WebSockets or verify through the SDK/API.
Finally, verify the transaction on the XRP Ledger. You can use libraries like xrpl-client or verify-xrpl-signature for on-ledger verification. Ensure to check for delivered_amount and other relevant fields.
Understanding and implementing Xumm's transaction lifecycle is crucial for creating secure and efficient transactions on the XRP Ledger through the Xumm platform.
If you are using the Javascript/TypeScript SDK (https://github.com/XRPL-Labs/Developer-Help-Center/blob/main/environments/browser-web3/broken-reference/README.md) the SDK will automatically make sure you are calling the right CORS enabled endpoints when a user signed in through the SDK.
If you are building your own, custom implementation, you will have to make sure you are calling the JWT routes: only our JWT (JSON Web Token) routes allow for cross origin calls, and serve the right headers to allow your browser to do so.
Your application crafts the XRPL transaction template. The difference between a regular XRPL JSON transaction and a Xumm transaction template is that you can leave out some fields (or leave them blank) as the Xumm app on the device of the end user will fill them automatically.
Your application backend will send the transaction template to the Xumm API / SDK. Your application will receive a unique Payload ID that contains your Sign Request.
Fee will be automatically filled with the appropriate network fee, but when set in the Payload, Xumm will respect your provided fee.
Sequence will be automatically filled with the Account sequence of the account interacting with your payload.
Account will be automatically filled with the account interacting with your payload.
When you want to develop in your local browser instead of in Xumm, please see the "OTT Replay" section in the Development & Debugging article.
We are currently working on a Desktop xApp Development Application so you can develop & test locally 🎉 (Work in progress, more good things are coming)
const rails = await Sdk.getRails();const txInfo = await Sdk.getNftokenDetail(tokenId);const hookHashes = await Sdk.getHookHashes();const pong = await Sdk.ping();{
quota: {},
application: {
uuidv4: '00000000-1111-2222-3333-aaaaaaaaaaaa',
name: 'My XUMM APP',
webhookurl: '',
disabled: 0
},
call: { uuidv4: 'bbbbbbbb-cccc-dddd-eeee-111111111111' }
}xumm.xapp.scanQr()
xumm.xapp.on('qr', data => {
console.log('QR', data)
})Returns an event: payload. Use on(xAppEvent, fn) to subscribe to the return data.
{ uuid: '...' }xumm.payload.create({
TransactionType: 'Payment',
Destination: 'rfHn6cB5mmqZ6fHZ4fdemCDSxqLTijgMwo',
Amount: String(1)
}).then(payload => {
xumm.xapp.openSignRequest(payload)
}){ text: 'Some text to share' }xumm.xapp.share({ text: 'Some text to share' })Verify a user token (or multiple), to see if the token is still valid (not expired, not revoked) and can be used to deliver sign requests to user(s)
The verifyUserTokens (or single token: verifyUserToken) method allows you to verify one or more User Tokens obtained from previous sign requests. This allows you to detect if you will be able to push your next Sign Request to specific users.
const someToken = '691d5ae8-968b-44c8-8835-f25da1214f35')
const tokenValidity = Sdk.verifyUserTokens([
someToken,
'b12b59a8-83c8-4bc0-8acb-1d1d743871f1',
'51313be2-5887-4ae8-9fda-765775a59e51'
])
if ((await Sdk.verifyUserToken(someToken).active) {
// Push, use `user_token` in payload
} else {
// QR or Redirect (deeplink) flow
}Can be used to check connectivity / JWT (credential) validity & to obtain basic information about the calling credentials.
{
"pong": true,
"auth": {
"quota": {},
"application": {
"uuidv4": "8525e32b-1bd0-4839-af2f-f794874a80b0",
"name": "Some App",
"webhookurl": "https://webhook.site/3e5dee90-a654-4e34-8112-c4391247a8ee",
"disabled": 0
},
"call": {
"uuidv4": "4b97cf7a-1837-471f-baed-2ebebcf5adb4"
}
}
}When a payload is created using the Xumm SDK in an xApp flow, the return URL is ignoded as the user will return to the xApp post signing, where an SDK event will be triggered.
{id} will be replaced with the xumm payload UUID.
{cid} will be replaced with the optional custom payload identifier.
{txid} will be replaced with the signed transaction hash.
{txblob} will be replaced with the signed transaction HEX blob.
If both the app and web return URL values are present, and if they are identical, the XUMM platform will execute logic to see if the user is coming from a browser tab (local device or remote, e.g. desktop browser). If so, and if the origin browser window is still active, only the origin browser window will redirect, and the app won't. Else (if the browser window is not active anymore) XUMM will redirect to the return URL.
This behaviour prevents a double redirect (both on mobile and on desktop / browser window).
After the user signs your SignIn request, the server-to-server call (to your configured Webhook location) will receive the signed transaction containing the signed transaction HEX blob.
You can verify the signature using the verify-xrpl-signature package:
https://github.com/XRPL-Labs/verify-xrpl-signature
Note: The SignIn transaction type is particularly useful when you want to authenticate a user without performing any transaction on the XRPL.
{
"txjson": {
"TransactionType": "SignIn"
}
}CTID is a more efficient way to link to transactions, as they contain the ledger index, transaction index in that ledger and the NetworkID.
More info: https://xrpl.org/ctid.html
https://xumm.app/explorer/{network}/{txhash}https://xumm.app/explorer/{ctid}{ refreshEvents: true }xumm.xapp.close({ refreshEvents: true })xApp property should be a valid xApp identifier.{ xApp: '...' }xumm.xapp.navigate({ xApp: 'xumm.support' }){ url: '...' }xumm.xapp.openBrowser({ url: 'https://wietse.com' }){
"txjson": {
"TransactionType": "..."
},
"options": {
"return_url": {
"app": "https://...",
"web": "https://..."
}
}
}Example QR:
const tx = {
TransactionType: 'TrustSet',
Flags: 131072,
LimitAmount: {
currency: 'XAH',
issuer: 'rswh1fvyLqHizBS2awu1vs6QcmwTBd9qiv',
value: '100000000',
}
}
const str = JSON.stringify(tx)
const hex = Buffer.from(str, 'utf-8').toString('hex')
console.log(`https://xaman.app/detect/${hex}`)Client side web apps "Web3"
xApps: your web app in Xaman
Backend integrations
Xaman as Identity Provider




const txInfo = await Sdk.getTransaction(txHash);Delivering Sign Requests using a push notification can be a very convenient way for end users to interact with your application: they don't even have to scan a QR code.
If you are building a backend integration, the flow is slightly different.
If your application features user sign-in (to identify your user) and you obtained a user_token from a previously signed payload from this specific user, you can add the user_token to the next payload to deliver the payload through a push notification.
The first interaction (to obtain the user_token) will always involve either: showing a QR code for the user to scan with the Xumm app or a deep link to the Xumm app to sign a payload.
A payload containing a user token looks like this:
After posting the payload the Xumm SDK/API, the response will confirm push notification delivery:
User token expiration
The issued user token expires 30 days after the last successfully signed payload of your application by the Xumm user using the same issued user token. If there's a good reason for your application to have longer living user tokens, please contact Xumm Support and explain your use case.
After the end user resolves the sign request by signing, the configured application Webhook URL will receive a JSON body per POST request containing the accessToken section:
When you get the payload results, the application.issued_user_token contains the user token.
xApps are custom applications that run within the Xumm environment. As a developer working with xApps, delivering payloads is crucial for a seamless user experience.
Delivering payloads within xApps is about efficiency and user experience. Since the user is already engaged with your xApp inside Xumm, delivering the payload directly within the xApp streamlines the process. This minimizes context switching for the user and keeps them focused on the task at hand.
Create a Payload: First, you need to create a payload with the transaction details. This payload is essentially a sign request you want the user to interact with. See:
Use Xumm SDK: To deliver the payload within your xApp, use the Xumm SDK. The SDK provides functions allowing you to seamlessly integrate the payload within your xApp. See:
Once integrated, the payload will be displayed to the user within your xApp. The user can then review and interact with the payload without leaving the xApp.
Developers can use the Xaman SDK to easily integrate with the Xaman platform. This allows for easy & secure end user interaction. With your application & the XRP Ledger.
Debugging your xApp is tricky: it runs on your phone. How to access the logs?
The easiest way to debug your xApps is by using our xApp Developer App for desktop (Mac, Windows, Linux): xAppBuilder 🏗️
Some things that may help debugging your xApp:
Using you can drop one line (script) in your page's <head> and get realtime access to the remote console (bi-directional).
If you open your own xApp using the device you added in the Xumm Developer Console as debug device (using the Device Identifier), the OTT (one time token) can be replayed when visiting from the same IP address.
Make sure your device (Xumm - Settings - Advanced) is whitelisted as Debug Identifier in the Xumm Developer Console
Make sure your phone and computer are visiting from the same public IP address (e.g. by having them both on the same WiFi and internet connection
Obtain your OTT in the xApp: it's the value of the xAppToken query parameter. Your xApp is being called with https://your-url/?xAppToken=...
You will now see your xApp in your browser.
Use a tool like ngrok () or localtunnel.me () to temporarily publish your local development URL to a publicly available URL you can use to access your xApp during live debug/development.
The XRP Ledger Protocol has several protocol-related things to check in your app/implementation to make the experience for end users better. Please take these things into account:
When building your own backend integration, you can request a user to sign a Sign Request with a "SignIn" transaction type. This is a pseudo transaction type allowing a user to confirm their r-address
A sign SignIn sign request can be as simple as this:
{
"txjson": {
"TransactionType": "SignIn"
}
}All Xumm payload options are valid for a SignIn transaction.
After the user signs your SignIn request, the server to server call (to your configured Webhook location) will receive the signed transaction containing the signed transaction HEX blob.
When the user signs the Sign Request, you will get a signed transaction (that has never been submitted to the XRP Ledger).
You can now get the account address and some basic public account information from the payload details, and assign this information to your own local dataset, like a session.
If you want to you can run your own signature verification on the signed SignIn pseudo transaction our platform returns to you. Of course the Xumm platform also verified the signature for you. Would you like to check yourself as well, we have created this package
Xumm xApps yield a JWT that can be used to make subsequent calls from the user context to the Xumm API's. You can also use this JWT for your own backend.
This makes it really convenient to obtain three things at once, making calls to your own backend with an Autorization: Bearer {The Xumm JWT} header:
You obtain basic user information, like the r-address and network the user is connected to, as this information is encoded in the JWT.
You can verify the authenticity of the JWT, as it is signed with your own Xumm API Secret.
You can make calls from the user context to the Xumm backend with this JWT (for as long as it is valid: 24h).
Every time when a user opens your xApp, a new JWT is issued, valid for 24h.
Please note: if you are using the OAuth2 flow instead of an xApp to obtain your JWT, you can verify the OAuth2 issued RS256 JWT using the certificate info publised as per OpenID specifications:
When using the JWT for authorization, you need to validate it before you can make sure that the user is who they say they are. This is a brief explanation in how to verify the JWT using a npm package called and the bearer provided by the Xumm SDK.
You can obtain the JWT associated with the OTT by initiating the Xumm SDK:
Then get the bearer by awaiting the environment:
This bearer is the JWT. You must check if the JWT is valid.
First, run:
After this, use the code underneath to verify the JWT. You'll need the xApp API Secret to sign the JWT and check it's validity.
This xApp API Secret is found in the developer console at .
To get payload details, status and if resolved & signed: results (transaction, transaction hash, etc.) you can get() a payload.
Note! Please don't use polling! The XUMM API offers Webhooks (configure your Webhook endpoint in the Developer Console) or use a subscription to receive live payload updates (for non-SDK users: Webhooks).
You can get() a payload by:
Payload UUID
const payload = await Sdk.payload.get("aaaaaaaa-bbbb-cccc-dddd-1234567890ab");Passing a created Payload object (see: Sdk.payload.create)
If a payload can't be fetched (eg. doesn't exist), null will be returned, unless a second param (boolean) is provided to get the SDK to throw an Error in case a payload can't be retrieved:
To cancel a payload, provide a payload UUID (string), a <XummPayload> (by performing a Sdk.payload.get() first) or a <CreatedPayload> (by using the response of a Sdk.payload.create() call). By cancelling an existing payload, the payload will be marked as expired and can no longer be opened by users.
Please note: if a user already opened the payload in XUMM APP, the payload cannot be cancelled: the user may still be resolving the payload in the XUMM App, and should have a chance to complete that process.
A response (generic API types here) looks like:
{
result: {
cancelled: boolean;
reason: XummCancelReason;
}
meta: XummPayloadMeta;
custom_meta: XummCustomMeta;
}Open the Destination Picker: select/find/scan (QR) an XRPL destination account by r-address, slug or PayString
If you want to request the destination address only, skipping the "Destination Tag" required check & input, you can provide the ignoreDestinationTag param. If not provided (or false) Xumm will chech if the destination account requires a Destination Tag and ask the user to input one.
{ ignoreDestinationTag: boolean }Returns an event: destination. Use to subscribe to the return data.
You can fetch the corresponding payload to verify the signature, to make sure it's signed by the account you expected to sign the payload.
xumm.payload?.get('some-payload-uuid').then(payloadResult => { /**/ })If you want the actual blob and signature for the user signed in with the Xumm OAuth2 flow:
Get the JWT contents
Get the payload from the JWT (that's the Sign In payload)
Get that payload with the SDK
Check the payload data, the response.hex property holds the signed TX Blob
Now you can verify the signature using the xrpl-verify-signature package, or using any native method capable of verifying XRP Ledger signatures:
CORS restricts access to resources on different domains to ensure privacy and security, allowing website owners to control access. As xApps run inside Xumm, allowing CORS is required for xApps.
If an xApp integration doesn't allow for running commands, and the console shows messages like "Couldn't connect to host", problems are a result of the same cause: CORS issues.
The SDK can't reach Xumm (the app), so:
"Could not contact Xumm host" error appears, and:
For example: the openSignRequest trigger doesn't fire, the Sign Request doesn't open, and:
Xumm keeps on trying, and is stalling the init. to see if the host can be reached - yielding "Attempt n » Retry" console messages (just to make sure it isn't a timing issue).
Check the following things:
Are you getting this messages from your frontend console, or backend (node?)
Do you have CORS setup correctly? (Allow iframe loading, allow CORS (origin: *)
Does your app run over http (instead of https with a valid certificate?)
While #3 and #4 should be valid, we've seen some Android phones where this prevented the integration from working. We use ngrok to work around the local http and non standard port development issues.
\
A sign request in Xumm is a prompt to approve a transaction or action on the XRP Ledger. This page will show you how you can create a Sign Request, and how you can deliver the request to the end user.
When creating Sign Requests from a backend environment, the Xumm SDK is called with your API Key & Secret. A payload can be opened by any user. A user will not get notified about a payload, unless if they interacted with the payload through a deeplink or scanning the Payload QR code.
If you want to deliver backend created Sign Requests to a user & the user is identified by your application, you have to provide a user_token to the payload. The user_token can be obtained after the user interacted with your application & signed a payload. See: Push
Introducing xAppBuilder, an advanced tool specifically designed to streamline the creation and debugging process of xApps for Xumm.
This is where xAppBuilder shines - it seamlessly emulates your xApp directly on your local development environment.
What does this mean for you? Instant, real-time feedback on your code modifications. Every tweak you save in your IDE, you can immediately see its effect on the emulated xApp.
xAppBuilder transforms these challenges into a smooth, manageable process.
One Time Tokens (OTTs) and replay tokens can often present challenges, particularly for those new to xApp development.
xAppBuilder assists in addressing this issue by offering an automatic fetching feature for OTT and Replay OTT, reducing development time and allowing developers to concentrate more on enhancing the functionality of their xApp.
Debugging becomes a breeze with xAppBuilder. How? With live console logs of your xApp, spotting and fixing bugs is a more efficient process.
These real-time logs help you to monitor and understand your xApp's performance and behavior better.
Ready to level up your xApp development process? xAppBuilder is now live for Linux on the , , and . Check out the demo video and download the tool today!
For more about xApps and Xumm, visit our . Here's to smoother, faster, and more efficient xApp development. Happy building, developers! 🏗️ 🛠️
Websockets provide real-time payload updates
All payloads get assigned a payload-specific Websocket URL. You can connect to this socket from the client side of your application to receive live status updates (if the user opens the payload on their device and the user resolves the payload).
The pushed information contains minimal information; it is meant to trigger your application to fetch more information from your application's backend.
If a payload doesn't exist, the Websocket connection will receive an {"message":"..."} update, and the socket will be closed. If the payload has expired, the connection will receive a {"expired":true"} message.
If the payload exists and did not expire, the connection will start with a message containing the remaining seconds until expiration: {"expires_in_seconds":51}. This message will be sent every 15 seconds for keepalive reasons. If the connection is still active when the payload expires, a {"expired":true"} message will be sent. The connection will be kept alive, leaving it up to the client to disconnect.
Webhooks are HTTP callbacks that allow you to receive notifications when a Payload (Sign Request) has been resolved (rejected or signed).
Webhooks are essential for asynchronous communication and can trigger specific actions in your application based on events in Xumm.
If you entered a valid Webhook URL in your Application Settings at the Xumm, your application would receive an HTTP POST containing a JSON body with limited details for the given payload.
Please note a Webhook will not contain the entire payload: to get the entire payload, you should GET the payload using an SDK/API call.
When building a native app (iOS / Android / React Native / Capacitor / ...) you can leverage "Sign In with Xumm" and offloading transaction signing to Xumm as well. This uses application deep links.
The process to integrate Sign In with Xumm and transaction signing by Xumm with your own native app is actually quite similar to either the flow: it uses OAuth2 (PKCE or Implicit flow) or the flow.
Combined with "Deep Links", your application sending off the user to Xumm will happen with a simple app-redirect. After the user interacted with your sign request, Xumm will return the user to the Return URL: the URL you added to your sign request payload to be opened post-signing.
If your application registers a Deep Link URL as well, and you pass that URL to Xumm as the payload Return URL, the user will be redirected back to your app. To match state, you can add information to the Deep Link URL Xumm sends the user to.
Frequently Asked Questions
Q: I do not see my xApp in the xAppBuilder. What should I do?
A: Ensure your Device ID has been entered in the Debug Device ID section.
Step 1: Retrieve your Device ID from Xumm by going to Xumm -> Settings -> Advanced -> Device ID (double tap to copy it).
Step 2: Visit , select your application, navigate to the xApp section, and paste the Device ID you copied in Step 1 into the Debug Device ID section.
With xAppBuilder, you can now conveniently connect your localhost for an efficient and real-time development experience. This video provides an overview of connecting your localhost.
Step 1: Create Your xApp
Begin by opening your preferred code editor (in this case, we are using VS Code). Establish a project folder, and within this, create an index.html file. Type some text between the body tag.
Next, install the Live Server extension for VS Code.
Then, initiate the Live Server by clicking the 'Go Live' button/link located in the bottom right corner of VS Code. Take note of the port number that is displayed.
Step 2: Make Your Website or Web Service Globally Accessible
In your terminal, execute the command npm install -g localtunnel. If you encounter a permission error, use sudo npm install -g localtunnel.
Following this, run lt --port 5500, making sure to replace '5500' with the port number noted in Step 1.
Get the KYC status for users, based on a user_token issued by a successful sign request.
The getKycStatus return the KYC status of a user based on a user_token, issued after the user signed a Sign Request (from your app) before (see Payloads - Intro).
If a user token specified is invalid, revoked, expired, etc. the method will always return NONE, just like when a user didn't go through KYC. You cannot distinct a non-KYC'd user from an invalid token.
Alternatively, KYC status can be retrieved for an XPRL account address: the address selected in XUMM when the session KYC was initiated by.
... or using an account address:
Returns .
Notes on KYC information
Using the Xumm SDK in xApps, you can trigger native Xumm interaction & receive events from Xumm in your xApp.
xApps are WebApps. They are opened in Xumm for a great user experience. They add value (tooling, wizards) for end users, using Sign Requests to help users perform tasks on the XRPL.
To add value for end users, your xApp will most likely implement some of the features Xumm offers natively in your xApp. E.g. open the QR scanner, Account Destination Picker, or start a Sign Request flow. Then to receive the response from these native Xumm flows in your xApp (WebApp).
Your xApp can trigger specific actions in Xumm:
These actions can be sent form your xApp (frontend Javascript) context, and will trigger functionality native to the Xumm app:
Open a Sign Request
Returning non-void in the callback function passed to the Sdk.payload.subscribe() method
Manually calling <PayloadSubscription>.resolve() on the object returned by the Sdk.payload.subscribe() method
The subscription will be closed by either:
Two types of Push:
Payload (Sign Request Push). Any application can send Sign Requests with a push notification after the user interacted with the app at least once.
Backend integration: the Webhook & Payload get will contain a user token after the user decided to interact by signing a payload.
When building xApps, it makes a lot of sense to stick to the design (colour palette, font, etc.) as used by Xumm to offer the best user experience to xApp users.
The main application uses the font-family: proxima-nova, sans-serif. Only when using this font for your (web) xApp to be embedded in XUMM, use this stylesheet:
When offering your application anywhere else than as embedded (web) xApp, check your licensing needs and requirements for the use of Proxima Nova.
See this code in action:
Some web server configurations don't allow CORS to work on a subdomain. Try running on a FQDN
retrieved- A user token is valid for 30 days (default, can be extended on a per app basis if good reasons are provided). Every time the user interacts with the app again, the 30 day cycle will reset. - When creating a new payload (sign request), the user token can be specified in the payload, after which the user will receive a push notification, and the sign request will present itself in the Event List of the user. - Users can revoke the user token validity in Xumm (Settings - 3rd party apps - Revoke) - A user token is user & app bound, meaning the same user token can only be used by the API credentials it was originally extended to.
Custom xApp push events. Custom xApp push events are permissioned.
Notification with link to xApp
Notification with link to xApp & Event in Event list with link to xApp
Handle Status Updates: Implement logic to handle status updates. This includes whether the user signed or rejected the payload. Xumm SDK provides functions that allow you to receive status updates and take appropriate actions based on the user's response, see: on(xAppEvent, fn)
Now open your public xApp URL with /force appended, and include the xApp Token. E.g. if your xApp launch URL is:
https://xumm.app/detect/xapp:sandbox.abcd1234
... You open (in your browser):
https://xumm.app/detect/xapp:sandbox.abcd1234/force?xAppToken=...


import { Xumm } from "xumm";
const xumm = new Xumm("some-api-key", "some-secret-key");
(async () => {
console.log("pong", await xumm.ping());
const transaction = { TransactionType: 'SignIn' };
console.log("payload", await xumm.payload?.create(transaction))
})()const { Xumm } = require('xumm')
const xumm = new Xumm('apikey', 'apisecret')
xumm.ping().then(pong => console.log(pong))
const transaction = { TransactionType: "SignIn" }
xumm.payload?.create(transaction).then(payload => console.log(payload))ownerwnerCount = accountInfo.account_data.OwnerCount
reserveBase = serverInfo.info.validated_ledger.reserve_base_native || serverInfo.info.validated_ledger.reserve_base_xrp
reserveInc = serverInfo.info.validated_ledger.reserve_inc_native || serverInfo.info.validated_ledger.reserve_inc_xrpconst newPayload: XummTypes.CreatePayload = {txjson: {...}}
const created: XummTypes.CreatedPayload = await Sdk.payload.create(newPayload)
const payload: XummTypes.XummPayload = await Sdk.payload.get(created)await Sdk.payload.get("aaaaaaaa-bbbb-cccc-dddd-1234567890ab", true)async Sdk.payload.cancel (
payload: string | XummPayload | CreatedPayload,
returnErrors: boolean = false
): Promise<DeletedPayload | null>xumm.xapp.selectDestination({ ignoreDestinationTag: false })
xumm.xapp.on('destination', data => {
console.log('Destination', data.destination)
})import { Xumm } from "xumm"
const xumm = new Xumm("some-api-key", "some-secret-key")
const payload = await xumm.payload?.create({
user_token: "xxxxxxxxxx",
txjson: {
TransactionType: "SignIn"
},
options: {
return_url: {
app: "https://sample.test/?...",
web: "https://sample.test/?id={id}"
},
force_network: "MAINNET"
},
custom_meta: {
identifier: "123123",
instruction: "Please sign this to..."
}
})) userToken.user_token) is issued and you plan on payload delivery using push notifications in the future, your application could/should store the token. See PushUse the payloadResponse.payload_uuidv4 to confirm and get payload outcome using an SDK/API call.
If you want to make sure the Webhook your application received came from the Xumm platform, there are two things you can do:
Send a GET for the payload to get the full payload using the SDK/API to the Xumm platform: get( … )
Verify the signature we send in a HTTP Header when we deliver the Webhook: Signature verification\
Once an account has successfully completed the XUMM KYC flow, the KYC flag will be applied to the account even if the identity document used to KYC expired. The flag shows that the account was once KYC'd by a real person with a real identity document.
Please note that the KYC flag provided by XUMM can't be seen as a "all good, let's go ahead" flag: it should be used as one of the data points to determine if an account can be trusted. There are situations where the KYC flag is still true, but an account can no longer be trusted. Eg. when account keys are compromised and the account is now controlled by a 3rd party. While unlikely, depending on the level of trust required for your application you may want to mitigate against these kinds of fraud.
const kycStatus = await Sdk.getKycStatus(
"00000000-0000-0000-0000-000000000000"
);const kycStatus = await Sdk.getKycStatus("rwu1dgaUq8DCj3ZLFXzRbc1Aco5xLykMMQ");The given account must be imported in Xumm
Xumm must be on the network the transaction is present on
{
account: '...',
tx: 'HASH...',
network?: 'MAINNET|TESTNET|XAHAU|...',
}xumm.xapp.tx({
account: 'rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ',
tx: '250DC3E83946EFE965DE36B3F9AE8608CD7ED793657BDEC5B794B665B2DCBC0E',
network: 'MAINNET',
})The response of a Sdk.payload.create() operation, looks like this:
The next.always URL is the URL to send the end user to, to scan a QR code or automatically open the XUMM app (if on mobile). If a user_token has been provided as part of the payload data provided to Sdk.payload.create(), you can see if the payload has been pushed to the end user. A button "didn't receive a push notification" could then take the user to the next.no_push_msg_received URL. The
Alternatively user routing / instruction flows can be custom built using the QR information provided in the refs object, and a subscription for live status updates (opened, signed, etc.) using a WebSocket client can be setup by connecting to the refs.websocket_status URL. Please note: this SDK already offers subscriptions. There's no need to setup your own WebSocket client: createAndSubscribe( … )
async Sdk.payload.create (
payload: CreatePayload,
returnErrors: boolean = false
): Promise<CreatedPayload | null>Open the QR scanner to retrieve a scanned value
Open the Account Destination Picker
etc.
Your xApp can also receive events (data) from Xumm:
Certain actions in Xumm will trigger an event so your xApp can retrieve data or act based on the event (details below):
Payload resolved
QR Code scanner opened/closed
Destination picker: closed / destination picked
Sdk.payload.subscribe()Sdk.payload.subscribe()onmessageMore information about the status update events & sample event data: Status updates
The payload is opened by a XUMM App user (webpage)
The payload is opened by a XUMM App user (in the app)
Payload expiration updates (remaining time in seconds)
The payload was resolved by rejecting
The payload was resolved by accepting (signing)
To subscribe to live payload status updates, the XUMM SDK can setup a WebSocket connection and monitor live status events. Emitted events include:
If a callback function is not provided, the subscription will stay active until the <PayloadSubscription>.resolve() method is called manually, eg. based on handling <PayloadSubscription>.websocket.onmessage events.
When a callback function is provided, for every payload specific event the callback function will be called with <SubscriptionCallbackParams>.
The <SubscriptionCallbackParams>.data property contains parsed JSON containing event information.
Either by calling <SubscriptionCallbackParams>.resolve() or by returning a non-void value in the callback function the subscription will be ended, and the <PayloadSubscription>.resolved promise will resolve with the value returned or passed to the <SubscriptionCallbackParams>.resolve() method.
Resolving (by returning non-void in the callback or calling resolve() manually) closes the WebSocket client the XUMM SDK sets up 'under the hood'.
The <PayloadSubscription> object looks like this:
{
"user_token": "c5bc4ccc-28fa-4080-b702-0d3aac97b993",
"txjson": { ... }
}{
"uuid": "<some-uuid>",
...
"pushed": true
}{
"meta": { ... },
"payloadResponse": { ... },
"userToken": {
"user_token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
...
}
}{
"meta": { ... },
"application": {
"issued_user_token": "e5fff0d0-698d-425d-bdcf-3156e744282d",
...
},
...
}const xumm = new Xumm(apiKey, xAppToken)const bearer = await xumm.environment.bearernpm install jsonwebtokenconst jwt = require('jsonwebtoken')
const apiKey = '' // Your Xumm API key here
const apiSecret = '' // Your Xumm API secret (BACKEND ONLY!)
const bearer = await xumm.environment.bearer
try {
// If decoded comes back as an object, the JWT is valid.
// Otherwise, the catch block is activated
const decoded = jwt.verify(bearer, apiSecret);
// For extra security, check if the decoded JWT contains
// the client_id of your xApp, e.g. the API Key from the developer console
if(decoded.client_id === apiKey) {
// JWT is valid and signed for this client (client_id matched)
} else {
// Valid JWT, but for another client? There's something
// wrong with an otherwise valid JWT.
}
} catch (error) {
// Handle your error here and inform the user that their access is denied.
}async Sdk.payload.get (
payload: string | CreatedPayload,
returnErrors: boolean = false
): Promise<XummPayload | null>{
"meta": {
"url": "<your-webhook-endpoint>",
"application_uuidv4": "<some-uuid>",
"payload_uuidv4": "<some-uuid>",
"opened_by_deeplink": true
},
"custom_meta": {
"identifier": "some_identifier_1337",
"blob": {},
"instruction": "Hey ❤️ ..."
},
"payloadResponse": {
"payload_uuidv4": "<some-uuid>",
"reference_call_uuidv4": "<some-uuid>",
"signed": true,
"user_token": true,
"return_url": {
"app": "<your-url>",
"web": "<your-url>"
},
"txid": "<some-tx-hash>"
},
"userToken": {
"user_token": "<some-token>",
"token_issued": 1635000000,
"token_expiration": 1637500000
}
}{
txjson: {
TransactionType: "Payment",
Destination: "r...",
Amount: "1000000"
},
options: {
return_url: {
app: "https://sample.test/?...",
web: "https://sample.test/?id={id}"
},
force_network: "MAINNET"
},
custom_meta: {
identifier: "123123",
instruction: "Please sign this to..."
}
}{
"uuid": "1289e9ae-7d5d-4d5f-b89c-18633112ce09",
"next": {
"always": "https://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09",
"no_push_msg_received": "https://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09/qr"
},
"refs": {
"qr_png": "https://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09_q.png",
"qr_matrix": "https://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09_q.json",
"qr_uri_quality_opts": ["m", "q", "h"],
"websocket_status": "wss://xumm.app/sign/1289e9ae-7d5d-4d5f-b89c-18633112ce09"
},
"pushed": true
}<html lang="en">
<body>
<div id="destinationname">...</div>
<input id="destinationaddress" value="" placeholder="Destination address" />
<button onclick="xumm.xapp.selectDestination()">Pick destination account</button>
<script src="https://xumm.app/assets/cdn/xumm.min.js"></script>
<script>
var xumm = new Xumm('your-api-key')
xumm.xapp.on('destination', data => {
if (data.destination.address) {
document.getElementById('destinationname').innerText = data.destination.name
document.getElementById('destinationaddress').value = data.destination.address
} else {
console.log('No destination selected', data.reason)
}
})
</script>
</body>
</html>{
payload: XummPayload,
resolved: Promise<unknown> | undefined
resolve: (resolveData?: unknown) => void
websocket: WebSocket
}async Sdk.payload.subscribe (
payload: string | XummPayload | CreatedPayload,
callback?: onPayloadEvent
): Promise<PayloadSubscription>xumm-xapp-sdkxumm-oauth2-pkce for browser / "Web3" interaction
All three packages above have been replaced by the xumm package, which allows for easier (unified) interaction with the three aforementioned topics.
x-api-key and x-api-secret headers to our platform.Frontend (browser, client side) implementations Browser ("Web3") can use our Javascript/Typescript SDK, in which case the entire authorization is abstracted away. Under the hood, the user will go through an OAuth2-flow and a JWT (JSON Web Token) is obtained from our platform. This token is valid for 24 hours and user context bound.
If you are building your own frontend implementation, any OAuth2 (Implicit and PKCE flows both supported) client will do. See Identity (OAuth2, OpenID)
Never use an API Secret obtained from the Developer Dashboard in a frontend environment! Anyone in possession of your API Secret (x-api-secret) can create payloads (Sign Requests) on behalf of your application. If abused, this can immensely damage the reputation of your application.
xApps xApps ("dApps") are loaded with several URL Query Paramters added, one of which is the xAppToken parameter. This parameter contains what we refer to as the "OTT", the "One Time Token". This token can be resolved by your application to a JSON response containing:
user context information
a JWT, JSON Web Token, allowing you to make subsequent calls to our platform
If you use our Javascript/Typescript SDK, this entire authorization flow is abstracted away by our SDK; the SDK (in the xApp, client side) will automatically resolve the xApp Token ("OTT") and use the JWT to make subsequent calls to our platform.
Any OAuth2 (Implicit and PKCE flows both supported) client will do. Your application Native Apps can redirect the user to our platform (to be redirected to the Xumm app) to sign in after which the client will be redirected back to your application (if your application supports deep links). You will obtain a JWT (JSON Web Token) to communicate to our platform from the user context. See:Identity (OAuth2, OpenID)
Also known as
"Server side"
"Sign in with Xumm"
"dApps", "web apps" embedded in Xumm
Credentials
API Key & Secret
JWT (SDK handles this for you)
JWT (SDK handles this for you)
Credential source
Obtained from the
Obtained after end user logs in (SDK does this for you)
The expiration should be handled as an OPEN/SCAN BEFORE, not a RESOLVE BEFORE. If the end user opens the payload (from the push notification, deep link, or QR scanning) but it didn't resolve before expiration, they will not receive a notification and will still be able to resolve it as if the payload hadn't expired.
When the user resolves after the expiration moment, the webhook and callback will handle the response as they would when the payload wasn't expired.
Websocket events to expect
Connected
{"message":"Welcome <payload-uuid>"}
After connecting and every 15 seconds while the connection is alive, a negative value means the transaction expired that many seconds ago
{"expires_in_seconds":54}
When the user received the payload, eg. push notification, deeplink or QR scan
{"opened":true}
When the Xumm SDK/API fetched the payload details
{"devapp_fetched":true}
When the user starts the signing routine
{"pre_signed":true}
When the submission to a node starts
{"dispatched":true}
WARNING! Do not just rely on a `signed: true` indication! If you receive a websocket message with `signed: true` indication, always fetch the payload to confirm that all payment details are as expected.
The Websocket payload resolve message looks like:
If you just want to authorize/identify a user with his/her r-address, the OAuth2 "Identify" flow suffices: you send off the user to a Sign In URL with a return URL and the user will return to your application with a JWT (JSON Web Token) you can use to call the Xumm API to get the user identification information (r-address). For more information, see Identity (OAuth2, OpenID).
If you are building a native app and you want to easily allow users to sign in with Xumm, you can use the OAuth2 Implicit flow like this:
Register an app at https://apps.xumm.dev and get the (public) API Key
Register a deeplink or deeplink protocol for your app, e.g. yourapp://signin
Add your deeplink / protocol URL to the Xumm Developer Console as a valid Return URL.
Redirect your user to:
https://oauth2.xumm.app/auth?client_id={apikey}
&redirect_uri=yourapp://signin
&response_type=token
Now, when the user signed in, Xumm redirects the user to your app, to the redirect_uri, with URL Query Parameters appended containing a JWT in the access_token field.
You can now use (you can construct the Xumm() with this JWT.
If you also want to send Sign Requests to users & you don't want the user to re-authorize the JWT every 24h, you can generate Sign Requests yourself, in which case the flow you will use is the Backend (SDK / API)flow. You craft your Sign In Payload: User identification payloads yourself, obtain a User Token after which you can generate user bound sign requests.
This workflow requires a backend on your end, where our application communicates to your backend to generate the Sign Requests. You need a backend for this, as you do not want to expose your Xumm API keys in your compiled application.
Q: Why are some of my xApps shown in gray at the end of the xApp list in xAppBuilder?
A: These xApps are ones you have not actively used, and their session has expired. To start a new session, open the xApp in Xumm and quit. Next, click on the "Refetch" link in xAppBuilder. This should fetch the active session of your xApp into xAppBuilder.
Q: How can I open the xApp on xAppBuilder with a different context / r-address?
A: Start by opening the xApp in Xumm with the different context / r-address, which will create a new session for the new context / r-address. Then return to xAppBuilder and click on the "Refetch" link. The new context / r-address should now be listed in the context dropdown menu.
Q: How do I exit / close the xAppBuilder?
A: On MacOS, hover over the top left corner to find the close, minimize, and maximize buttons. On Windows and Linux, click on the x symbol in the top right corner.
For Mac users, you can also use Shift + Click on the tray icon to exit.
A: First, switch to your desired network in Xumm. Next, open the relevant xApp within Xumm — this action generates the OTT for replay. Following this, click on the 'Refetch' button(top left corner) in xAppBuilder and open the xApp in xAppBuilder.
It's important to note that xAppBuilder doesn't connect to any specific network by itself. The connection relies on the most recent OTT of your xApp. For instance, if you last accessed your xApp on the Testnet and subsequently open it in xAppBuilder, it will connect to the Testnet.
If the network hasn't switched, ensure that you're accessing the xApp within xAppBuilder using the same account (raddress) as the one you recently used in Xumm OR maybe you forgot to click on the 'Refetch' button.
Verify Network in xAppBuilder\
\
The terminal will output a unique URL. Copy this, and open it in your browser. Here, submit your IP address (if you are unsure of your IP, a quick Google search of 'whatsmyip' will provide it).
For further information about this package, you can refer to the official Localtunnel documentation.
Step 3: Set Up Your Xumm Developer Console Account
Navigate to the Xumm Developer Console and create an xApp account.
Paste the URL acquired in Step 2 into the 'WebApp URL' section. In the 'Debug Device ID' section, enter your device ID (which can be found by navigating through Xumm -> settings -> advanced -> Device ID).
Step 4: Access Your xApp on xAppBuilder
Open xAppBuilder and scan the provided QR code using Xumm. Afterward, click on the xApp within xAppBuilder.
Now, when you make and save changes to your code in the VS code editor, these changes will be reflected in xAppBuilder, allowing for real-time modifications and testing.
Starting XUMM version 1.1 four colour palettes are available. The colour the app is running in will be passed to the xApp in the style parameter, see the xapp/ott/:token documentation (applies to the SDK as well).
Used colour palette codes:
LIGHT
DARK
MOONLIGHT
ROYAL
The four available themes are shipped as Bootstrap (version 4.5) rolled stylesheets, ready to use. You can include a Bootstrap 4.5 stylesheet by pointing to:
The {theme} element should be replaced by the theme name in lower case notation.
To load the right stylesheet dynamically in an environment without a backend, consider using this script in your <head>:
xumm.on("success", async () => {
const { payload_uuidv4 } = await xumm.environment.jwt
const payloadResult = await xumm.payload?.get(payload_uuidv4)
console.log(payloadResult)
})import { Xumm } from "xumm"
const Sdk = new Xumm(process.env.XUMM_KEY, process.env.XUMM_SECRET)
const pong = await Sdk?.ping()
const payload = await Sdk.payload?.create({
custom_meta: {
instruction: "Sign request from " + pong?.application.name,
},
txjson: {
TransactionType: "SignIn",
},
})
console.log(payload)This article presents a concise implementation checklist for developers using Xumm. By following these steps, you can ensure a smooth and secure integration whilst optimizing the user experience.
Fetch Payload Results: Trigger your application to fetch payload results after receiving a Webhook callback.
Inspect Payload Output: Confirm meta.resolved and meta.signed are both true in the payload output.
Identify Dispatched Node Type: Ensure response.dispatched_nodetype is "MAINNET" for real payments.
Validate Transaction ID: Validate the response.txid value on the ledger.
Examine Delivered Amount: Confirm the meta.delivered_amount equals the expected payment amount.
Use xrpl-txdata Package: Establish a connection to the XRP Ledger, fetch the transaction by hash, and cross-verify transaction details with the XRPL ledger.
Network Independence: Use the Xumm API/SDK, which operates independently of the network, to allow users the freedom of network choice.
Network Information: Ensure the results of a signed payload include the network the user was on during the signing.
Forced Network Identifier: Check for the expected result in the Payload results or specify a particular network using a forced network identifier in a payload.
Secure Your Webhooks: Implement appropriate security measures.
Verify Payloads: Authenticate received payloads.
Error Handling: Develop robust error management mechanisms.
xApp Creation & Audit: Anyone can create sandbox xApps, but public release requires an audit by XRPL Labs for user safety, compliance, and value addition.
User Experience: xApps must be self-explanatory, prevent dangerous mistakes, and provide a unique experience tailored to Xumm users.
Technical & Styling Standards: xApps must meet Xumm's technical guidelines and respect or have unique styling.
A sign request in Xumm is a prompt to approve a transaction or action on the XRP Ledger. This page will show you how you can create a Sign Request, and how you can deliver the request to the end user.
xApps are natively aware of the end user context, so a Sign Request payload can easily be served with the xumm.xapp.openSignRequest method: openSignRequest({ … })
<html lang="en">
<head>
<script src="https://xumm.app/assets/cdn/xumm.min.js"></script>
</head>
<body>
<pre id=
When a payload (Sign Request) has been created and opened in your xApp, you probably want to be informed if the payload has been signed or rejected, then to check the payload results and act on the results. You can do so by subscribing to the payload event, see:
Building a web app? Running as a client side SPA (single page webapp) or server side rendered? React Native / VueJS / VanillaJS / etc.: you can integrate with the Xumm ecosystem using our SDK.
The Xumm SDK can run fully client side: either as part of your compiled web app or using plain HTML and Javascript using our ready to use browserified version.
Using the Xumm SDK, you can easily add "Sign in with Xumm" capabilities to your web app. You don't even need a backend. You get the full "Web3" experience (sign in with a blockchain account) with our "Web2" compatible stack (see: Identity (OAuth2, OpenID) / Native Apps).
Make sure to add the return URL (also known as redirect URL) in the Xumm Developer Console on the application home page in the "Origin/Redirect URIs (one per line)" field.
Using the Xumm SDK in your web project, you get:
Sign in with a QR code for when loaded on a desktop
Deeplink (redirect to Xumm, back to your web app) on mobile
Basic user information: XRP Ledger account address, icon (hashicon or even avatar), connected chain (mainnet, testnet, ..) & some basic information about the end user's environment (currency, language, ...)
For the SDK documentation (objects, methods), see the SDK section: . For a simple demo of the Xumm SDK in a React Native environment, check this sample repository:
The <PayloadAndSubscription> object is basically a <PayloadSubscription> object with the created payload results in the created property:
All information that applies on Sdk.payload.create() and Sdk.payload.subscribe() applies. create( … ) / subscribe( … ). For the contents of a Payload, see the API Docs for more information about payloads object contents.
Differences are:
The input for a Sdk.payload.createAndSubscribe() call isn't a payload UUID / existing payload, but a payload to create.
The response object also contains (<PayloadAndSubscription>.created) the response obtained when creating the payload.
Returns information about the signed in user (in case of xApp or Web3 flow).
The following properties are part of the user object. Every property is a Promise that is resolved when the user is signed in.
account - r-address
picture - Profile picture or Hashicon URL
name - Account name (if present) - e.g. Xumm Pro account name
domain - Domain name (if present) for account
source - Information source (e.g. a specific explorer)
networkType - Enum, e.g. MAINNET, TESTNET, ... the user is connected to
networkEndpoint - WebSocket endpoint to connect to the network
blocked - If the account is on a blacklist (e.g. because of scams)
kycApproved - If the account owner went through opt in KYC with Xumm
proSubscription - If the account has a Xumm Pro subscription
profile - Xumm Pro Profile slug (URL)
token - User Token for future sign request Push delivery
The token field contains a user_token; this token is specific to both the application (SDK) credentials and the end user. It grants you access to asynchronously send notifications to the end user (for 30 days, unless granted long living tokens).
When your application creates a payload for the end user to sign using the SDK session (or JWT), a user will always receive a push notification.
If you want to asynchronously create a payload on your backend using the flow, you can include this token in the user_token field of the payload.
When using the native Xumm loader screen for your xApp (until your xApp is ready, fully hydrated, booted, etc.) you call this method to remove the Xumm loading screen.
To prevent showing a double loader (first the Xumm xApp loader, then your xApp's loader while hydrating / booting) you have to enable the "Xumm loader till SDK ready() is called" option in the Xumm Developer Console (xApp tab). The xApp will then show the Xumm native loader, until your application calls the ready() method on the Xumm SDK.
First your app loads, fetches, etc. Then you have all the information you need to render & show your app, and you call:
The xApp doesn't load, to be able to debug the app needs to be displayed (e.g. reverse proxy 502 error or some other app error, preventing the SDK's ready() call being made).
With Xumm in Developer Mode, the Xumm loading screen shows a 'Proceed to xApp' button at the Xumm loader screen, below the spinner. This way you can dismiss the Xumm loader and view the underlying problem.
The xApp takes very long to load or doesn't load at all: users are confronted with a long wait.
If the ready() method in the Xumm SDK isn't called within ~6 seconds a label + button is made visible: "xApp is slow to respond..." [Contact Developer].
This button then opens the Support URL for the xApp as entered in the Developer Console.
Build your own web app to live in-app, inside Xumm for all Xumm users. Build an xApp. Use your favourite tools & frameworks for the client side code (HTML, CSS, JS, etc.
Once a payment has been sent and the payload resolved on Xumm, some checks are performed to ensure secure payment verification. This document walks you through verifying a payment transaction on Xumm.
After a payload completes its lifecycle, which includes creation, user interaction, transaction signing, and transaction submission to the XRP Ledger by Xumm, your application will receive (if configured) a Webhook callback.
This callback should trigger your application to fetch the payload results. It is highly advisable to fetch the payload results again on your "thank you" or "return" page in case you did not persist the payload results after receiving a Webhook.
Payloads are the primary reason for the XUMM API (thus this SDK) to exist.
An XRPL transaction "template" can be posted to the XUMM API. Your transaction tample to sign (so: your "sign request") will be persisted at the XUMM API backend. We now call it a a Payload. XUMM app user(s) can open the Payload (sign request) by scanning a QR code, opening deeplink or receiving push notification and resolve (reject or sign) on their own device.
A payload can contain an XRPL transaction template. Some properties may be omitted, as they will be added by the XUMM app when a user signs a transaction. A simple payload may look like this:
As you can see the payload looks like a regular XRPL transaction, wrapped in an txjson object, omitting the mandatory Account, Fee and Sequence properties. They will be added containing the correct values when the payload is signed by an app user.
Get meta information for a known Hook, by specifying the Hook Hash (64 hex chars)
Sdk.getHookHash(hookHash: string)
The getHookHash method allows you to get meta information for a specific Hook hash (64 hex chars)
Returns:
Get the curated assets (shortlist in Xumm) for Trust Lines
The getCuratedAssets method allows you to get the list of trusted issuers and IOU's. This is the same list used to populate the "Add Asset" button at the XUMM home screan.
Returns :
https://xaman.app/assets/cdn/xumm.min.js{
"payload_uuidv4": "<some-uuid>",
"reference_call_uuidv4": "<some-uuid>",
"return_url":{
"app": "<some-url>",
"web": "<some-url>",
},
"signed": true,
"opened_by_deeplink": false,
"user_token": true,
"custom_meta":{
"identifier": "<some-identifier>",
"blob": {},
"instruction": "<some-instruction>"
},
"txid": "<some-tx-hash>"
}https://my.app.local/some/apphttps://my.app.local/some/app?xAppStyle={THEME}<link rel="stylesheet" href="https://use.typekit.net/vtt7ckl.css">https://xumm.app/assets/themes/xapp/xumm-{theme}/bootstrap.min.css<script>
var theme = ((new URLSearchParams(document.location.href))
.get('xAppStyle') || 'light').toLowerCase()
var link = document.createElement('link')
link.href = 'https://xumm.app/assets/themes/xapp/xumm-'
+ theme + '/bootstrap.min.css'
link.type = 'text/css'
link.rel = 'stylesheet'
document.getElementsByTagName('head')[0].appendChild(link)
</script>const { Xumm } = require("xumm")
const Sdk = new Xumm(process.env.XUMM_KEY, process.env.XUMM_SECRET)
Sdk.ping().then(pong => {
Sdk.payload.create({
custom_meta: {
instruction: "Sign request from " + pong.application.name,
},
txjson: {
TransactionType: "SignIn",
}
}).then(payload => {
// Done
console.log(payload)
})
})const Sdk = new Xumm('some-api-key')
Sdk.authorize()
Sdk.on("ready", () => {
Sdk.ping().then(pong => {
Sdk.payload.create({
custom_meta: {
instruction: "Sign request from " + pong.application.name,
},
txjson: {
TransactionType: "SignIn",
}
}).then(payload => {
// Done
console.log(payload)
})
})
})const payload = await xumm.payload?.create({
txjson: {
TransactionType: "Payment",
Destination: "r...",
Amount: "1000000"
},
options: {
return_url: {
app: "https://sample.test/?...",
web: "https://sample.test/?id={id}"
},
force_network: "MAINNET"
},
custom_meta: {
identifier: "123123",
instruction: "Please sign this to..."
}
})
xumm.xapp?.openSignRequest(payload)When the payload is resolved
{"payload_uuidv4": "...", [...] }
With: signed: true/false
When the payload is expired
{"expired":true}
When linking to Transaction Details using a Transaction Explorer, consider using our helper tooling: Tx Explorer(s)
Automatically obtained through a "One Time Token" (SDK does this for you)
Can send sign request push notifications
After the user signs their first Sign Request by you through deeplink / QR with a then obtained "User Token"
✅ Yes
✅ Yes
User identified with credentials?
No, "SignIn" payload (Sign Request) required first.
✅ Yes
✅ Yes
Usable in backend environments?
✅ Yes
Yes (but frontend obtained)
Yes (but frontend (xApp) obtained)
Usable in frontend (browser) environments?
❌ No
✅ Yes
✅ No
CORS ready?
❌ No
Yes (JWT endpoints, SDK handles this for you)
Yes (JWT endpoints, SDK handles this for you)
Usable in native app environments?
❌ No
Yes (but OAuth2 sign in flow required)
❌ No
Credential validity & authenticity can be offline verified?
❌ No
Yes, the JWT: using the OAuth2 certs information (RS256).
Yes, the JWT (HS256):Your own backend (Auth)








xumm.xapp.ready()Optionally (besides txjson) a payload can contain these properties (TS definition):
options to define payload options like a return URL, expiration, etc.
custom_meta to add metadata, user insruction, your own unique ID, ...
user_token to push the payload to a user (after obtaining a user specific token)
A more complex payload could look like this. A reference for payload options & custom meta can be found in: Payloads (sign requests)
Instead of providing a txjson transaction, a transaction formatted as HEX blob (string) can be provided in a txblob property.
{
txjson: {
TransactionType : 'Payment',
Destination : 'rwiETSee2wMz3SBnAG8hkMsCgvGy9LWbZ1',
Amount: '1337'
}
}const hookInfo = await Sdk.getHookHash('64hexchars');const curatedAssets = await Sdk.getCuratedAssets();{
curatedAssets: {
issuers: [ 'Bitstamp', 'GateHub' ],
currencies: [ 'USD', 'BTC', 'EUR', 'ETH' ],
details: {
Bitstamp: [Object],
GateHub: [Object]
}
}
}xApps have extra special permissions, allowing the xApp (web app) to interact with some of the native Xumm features:
They receive context (user account selected in Xumm when opened, Xumm theme, input params, account type (eg. Tangem / ...)
They can trigger overlay Sign Requests and receive callback info
They can trigger the QR scanner and receive scanned QR data
xApps can be opened (triggered) in lots of ways:
In the Xumm shortlist (we feature some apps, they get replaced by frequently used apps by the user)
From the xApp directory
By opening a deeplink (browser / from within another app)
By scanning a QR code
By attaching an xApp memo to an XRPL TX (so the Event list will show there's an xApp attached to the TX)
Using push notifications
From the Event list, as an xApp session pushed to a Xumm user
Trading interface (offloads signing to Xumm)
Admission ticket checking
NFT marketplaces / viewers
Issuing tokens, checking tokens
Tools: setting up accounts, crafting advanced transactions, escrows, etc.
Exchange deposit / withdraw integrations
xumm.on('payload', data => {
if (data?.uuid) {
xumm.payload.get(data.uuid).then(payload => {
// Payload contains the full paylaod data
})
}
})xumm.on('payload', data => {
if (data?.uuid) {
const payload = await xumm.payload.get(data.uuid)
// Payload contains the full paylaod data
}
})<html lang="en">
<body>
<h1 id="accountaddress">...</h1>
<button id="signinbutton" onclick="xumm.authorize()">Login</button>
<button id="logoutbutton" onclick="xumm.logout()">Logout</button>
<script src="https://xumm.app/assets/cdn/xumm.min.js"></script>
<script>
var xumm = new Xumm('your-api-key')
xumm.on("ready", () => console.log("Ready (e.g. hide loading state of page)"))
// We rely on promises in the `success` event: fired again if a user
// logs out and logs back in again (resets all promises)
xumm.on("success", async () => {
xumm.user.account.then(account => {
document.getElementById('accountaddress').innerText = account
})
})
xumm.on("logout", async () => {
document.getElementById('accountaddress').innerText = '...'
})
</script>
</body>
</html>xumm.payload.createAndSubscribe({
TransactionType: 'Payment',
Destination: 'rfHn6cB5mmqZ6fHZ4fdemCDSxqLTijgMwo',
Amount: String(1000000) // one million drops, 1 XRP
}, eventMessage => {
if (Object.keys(eventMessage.data).indexOf('opened') > -1) {
// Update the UI? The payload was opened.
}
if (Object.keys(eventMessage.data).indexOf('signed') > -1) {
// The `signed` property is present, true (signed) / false (rejected)
return eventMessage
}
})
.then(({ created, resolved }) => {
console.log('Payload URL:', created.next.always)
console.log('Payload QR:', created.refs.qr_png)
return resolved // Return payload promise for the next `then`
})
.then(payload => console.log('Payload resolved', payload))
// This is where you can do `xumm.payload.get(...)` to fetch detailsasync Sdk.payload.createAndSubscribe (
payload: CreatePayload,
callback?: onPayloadEvent
): Promise<PayloadAndSubscription><html lang="en">
<body>
<h1 id="accountaddress">...</h1>
<script src="https://xumm.app/assets/cdn/xumm.min.js"></script>
<script>
var xumm = new Xumm('your-api-key')
xumm.on("ready", () => console.log("Ready (e.g. hide loading state of xApp)"))
// Account can't change (like Web3 logout/login) so we can rely on the promise
xumm.user.account.then(account => {
document.getElementById('accountaddress').innerText = account
})
</script>
</body>
</html>Here are the steps to verify that you have indeed received a payment:
Check Payload Output: Verify if the Payload output contains meta.resolved. This value should be true. Otherwise, the payload is still pending or has been abandoned by the user. Also, check if the Payload output contains meta.signed. This value should be true, indicating that the user signed the transaction.
Check Response Dispatched Node Type: Verify the response.dispatched_nodetype value. If you are expecting a real payment, this value should contain MAINNET. If it doesn't, you might be accepting a TESTNET payment!
Check Transaction ID: The response.txid value is the on-ledger transaction hash. You must verify this transaction on the ledger. Note that it may take around 4 seconds for a ledger to close and slightly longer for the ledger and transaction info to propagate. You may want to repeat async/delay fetching this info if you don't get a result at first or if your result contains a validated: false value.
⚠️ Check Delivered Amount: After fetching the transaction details, check the meta.delivered_amount value to see if the amount of XRP (in drops, one million drops = one XRP) equals the expected amount to be paid. This is a crucial step in the verification process.
You can fetch transaction details using the XRPL Transaction Data fetcher or the JSON RPC (HTTP POST) method at https://xrplcluster.com.
After sending a Sign Request (payload) to Xumm, you receive a response with the signed transaction hash (Webhook: payloadResponse.txid, WebSocket: txid).
You're in luck if you immediately check this transaction hash on the XRP Ledger, and it's already in a validated ledger. However, if the transaction hasn't been included in a closed ledger, you might encounter a "Not Found" error, while if you had checked a few seconds later, you'd have found the transaction.
To streamline this process, use the xrpl-txdata NPM package (JS/TS). This package simplifies:
Establishing a redundant (multi-node, failover) and reliable (auto-timeout, auto-retry) connection to the XRP Ledger
Fetching a transaction by hash
Optionally, monitoring the XRP Ledger (all closed ledgers, all the transactions in those ledgers) and waiting for a specified time (seconds).
Once your transaction is found, the package returns the transaction outcome and validated balance changes.
Here's how to use it in JavaScript:
Good Practice: Cross-verify with the XRPL
It is always a good practice to cross-verify with the XRPL for absolute certainty. Using the tx method, you can fetch transaction details directly from the XRPL ledger.
More information on how to do this can be found in the XRPL Transaction Documentation.
Events fired by the SDK per environment. For the order of events, see the section per environment after the table with events.
retrieved
xApp, Web3 (browser)
A valid signed in Xumm SDK session has been retrieved.
success
xApp, Web3 (browser)
A user is succesfully identified and signed in
ready
xApp, Web3 (browser)
The SDK is ready (final state) so your application can render
The following order of events can be expected per environment.
retrieved - xApps always auto-resolve
success- all information is populated to SDK properties (Promises)
ready - ready to render your application with the correct Xumm SDK state
retrieving - but the user is signed out
ready - ready to render your application with the correct Xumm SDK state, but the user must still log in
The user signs in
retrieving - existing session information is being fetched & verified
success - all information is populated to SDK properties (Promises)
retrieved - you are dealing with an already signed in user
const {TxData} = require('xrpl-txdata')
const TxHash = '8F3CE0481EF31A1BE44AD7D744D286B0F440780CD0056951948F93A803D47F8B'
const VerifyTx = new TxData([
'wss://xrplcluster.com',
'wss://xrpl.link',
// Or:
// 'wss://testnet.xrpl-labs.com'
], {
OverallTimeoutMs: 6000,
EndpointTimeoutMs: 1500,
// If using testnet, see above:
// AllowNoFullHistory: true
})
// Specify the transaction hash to verify and the # of seconds
// to wait & monitor the XRPL if not found initially.
VerifyTx.getOne(TxHash, 20)
.then(tx => {
console.log(`Got the TX, details:`, tx)
})success - all information is populated to SDK properties (Promises)
ready - ready to render your application with the correct Xumm SDK state
retrieving
Web3 (browser)
The SDK is trying to retrieve & verify an existing session
logout
Web3 (browser)
The SDK is going to destroy a pending signed in session
loggedout
Web3 (browser)
The SDK destroyed a signed in session, a user can login again.
error
Web3 (browser)
An error occurred, see the browser console for more information
qr
The QR code scan dialog in Xumm has been closed (dismissed or a QR code has been scanned) From: scanQr()
payload
A Sign Request (payload) has been resolved (cancelled / signed / ...) From: openSignRequest({ … })
destination
The "Destination Picker" dialog in Xumm has been closed (dismissed or a destination has been selected) From: selectDestination({ … })
networkswitch
The user switched the selected network in Xumm while present in the xApp, while your xApp settings (Xumm Developer Console) indicate the xApp shouldn't reload but receive an event.
network contains getRails()key.
The PKCE flow (which is the new & more secure industry standard and replaces the Implicit flow) is also available.
All supported OAuth2 flows have their own use cases, advantages and caveats. The right one depends on your project & audience.
Backend
Frontend
Frontend
API Key + Secret
API Key
API Key
Custom implementation, custom sessions / token persistence if needed.
Xumm SDK handles user sign in & session retrieval
Xumm SDK handles user sign in & session retrieval
As secure as your own implementation
Secure (Man in the Middle attack not possible)
To use the Xumm Platform as OAuth2 / OpenID Connect provider, one or more valid OAuth2 redirect URI's must be whitelisted in the Xumm Developer Console, on an application level.
The same API Key and API Secret the Xumm Developer Console offers to be used calling our API's and using our SDK's can be used as OAuth2 client id and secret.
The Xumm platform returns a Bearer token (JWT) with limited validity. The token can not be refreshed: after expiration a new user sign in is mandatory to obtain a new JWT token.
When using the Xumm SDK (TypeScript & Javascript) all OAuth2/JWT interaction, authorisation & implementation will be abstracted away, which is by far the easiest way to interact with the Xumm platform.
Building your own integration, or using a standard OAuth2 consumer? All JWT tokens obtained through from a Xumm OAuth2 flow can be used with the JWT API endpoints (from a user locked context). The way to interact with the JWT endpoints is similar to the JWT flow for xApps, except the JWT is obtained through the OAuth2 flow instead of inside the xApp.
force_network allows you to specify a network the payload will have to be signed on. Sample values are MAINNET TESTNET XAHAU XAHAUTESTNET, etc.
signers allows you to specify one or more forced signers, by r-address, seperated by a comma (if multiple are to be provided where the user can choose from, providing they have signing capabilities for the account(s))
Sample Auth URL using the above params:
Authorization
https://oauth2.xumm.app/
Token
https://oauth2.xumm.app/
Userinfo
https://oauth2.xumm.app/
JWKS
https://oauth2.xumm.app/
OpenID Connect Metadata
https://oauth2.xumm.app/
All other JWT compatible Xumm API's
See our API docs:
xApps are WebApps, embedded in Xumm for a great user experience. They add value (tooling, wizards) for end users, using Sign Requests and their Web UI to help users perform tasks on the XRPL and beyond.
Anyone can create sandbox xApp
Only you can use your own sandbox xApp from a specific Xumm installation you can whitelist after activating xApp features.
The fact that you got a sandbox xApp is not to be presented anywhere as an endorsement (e.g. in communication like on social media, etc.))
To build an xApp, you need to have experience with Frontend Web Development as xApps are WebApps (loaded in Xumm)
xApps need to add value to a significant share of the Xumm user base
xApps need to be self explanatory to have clear instructions for end users
xApps need to be designed in a way where users can not make dangerous mistakes: users need to be protected
xApps developers can not be anonymous (accountability)
Promotion of speculation, pushing users towards buying tokens is not allowed (see: user protection)
Activating xApp features and building a sandbox xApp does NOT guarantee your xApp will be going live in the future. To take your xApp live, it will be audited by XRPL Labs. The rules above apply, security & usability will be tested. If you want to have more certainty in advance, please .
The xApp should be self explanatory, or do a good job explaining to the users what the xApp offers in the very first screen the xApp shows
xApps can not be designed in a way where it it completely unclear to end users if they are using a third party developed xApp or a XRPL Labs maintained component
xApps must not be a regular website/webapp fitted in an xApp: the user experience must be to seme degree tailored to users in Xumm, and must have relevance for Xumm users
All links to external sites / window opens must be replaced by a openBrowser call on the Xumm SDK: so that users won't reach another website through navigating in the xApp
Reliable user-bound storage is available not through cookies / localStorage, but through the Xumm userstore:
No polling should be used: to retrieve the status of a payload, use the websocket we provide for status updates (or the createAndSubscribe
Simple accessible navigation
Clear icons:
Reduce clutter: Keep minimum content on screen
Use accessible fonts
Accessibility Tools:
Contrast checker link 1:
Contrast checker link 2:
Iconset:
xApps should either have their own colour scheme (dark/light mode independent) or respect the Xumm colour schemes: . The end user styling will be passed to the xApp using the xAppStyle query parameter.
The xApp <html> and <body> tag must have a transparent background color right upon page load, so the xApp doesn't 'flicker' white while loading, until styling has been applied (rendered by the browser).
Full access, no restrictions, but only for the developer and max. 10 testers (whitelisted by Device UUID in the Xumm Developer Console)
The xApp should look appealing
The xApp should respect different Xumm user screen sizes
The xApp should be well crafted: it should be clear what the xApp will do, and it should do what the xApp promised to do
The xApp should have a clear Support workflow & offer terms & conditions & a privacy statement
The xApp should not be a "launchpad" to something that could be perfectly located at a website: if there is no actual Xumm wallet/XRPL interaction where the integration with Xumm adds value, it should be a website, not an xApp
Offer value (features people will appreciate/need) for a large part of the XRPL / Xumm user base
The frontend source code must either be open source, shared (under NDA) with XRPL Labs for review or a third party security audit (code & dependencies + dependency update procedures) acceptable by XRPL Labs has to be provided.
A sign request in Xumm is a prompt to approve a transaction or action on the XRP Ledger. This page will show you how you can create a Sign Request, and how you can deliver the request to the end user.
When working with Xumm sign in & payloads in the browser, there are two flows to consider. Your application should deal with both flows.
User is on mobile, Xumm is installed
User is on desktop, Xumm is on their phone
When a user visits on their smartphone with Xumm installed, your application can "deeplink" straight into Xumm, where a Sign Request will be opened.
To make sure the user is expecting Xumm to open, the best user experience would be to ask the user to open Xumm (with a button), alternatively allowing them to use a button to just show the QR code, so the Sign Request can be opened on another device.
Warning: most mobile browsers / operating systems will only allow deeplinks to trigger an application (so: the payload URL to trigger opening Xumm) if the button resulting in the trigger is user invoked.
Meaning there must always be a direct user onclick/ontap event resulting in the routine opening the payload URL being opened will deeplink.
On the desktop, a user may or may not receive a push notification. The user can scan a QR code as fallback. The ideal implementation:
Checks if the pushed property of the created payload
If false the user is displayed the payload QR code to scan with their phone.
Using the method the application receives real time updates about end user interaction. The application can update to reflect the interaction the user has with the Sign Request on their phone (
The Batch feature allows multiple transactions to be packaged together and executed as a single atomic transaction. Create and submit a batch of up to 8 transactions that succeed or fail atomically.
The Batch transaction type can be submitted through the Xaman API as any regular Sign Request (payload). It requires:
TransactionType "Batch"
Flags as integer, with one of the processing methods allowed for a Batch transaction:
https://oauth2.xumm.app/auth
?client_id=47fdfcb7-8362-47fe-9a89-a2efc55e86d5
&redirect_uri=https://dev.wietse.com
&response_type=token
&force_network=MAINNET
&signers=rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ,rTeLeproT3BVgjWoYrDYpKbBLXPaVMkgeSecure (but Man in the Middle attack possible)
You deal with the mobile return flow state persistence. You will have to make sure you restore your session to cover sessions where user return in another browser.
Only works on mobile when users leave and return from & to the same browser. E.g. when starting off in a Twitter embedded browser frame & returning to the native OS browser, the sign in will fail.
Works on mobile even when users start in one browser and get redirected to another browser (e.g. the OS native browser). Basically always works.
You deal with the desktop sign in flow (redirect / popup / ...)
Xumm SDK (TypeScript/Javascript) will trigger a pop up & handle sign state & events.
Xumm SDK (TypeScript/Javascript) will trigger a pop up & handle sign state & events.
"opened": trueIf true the user is displayed a message that the Sign Request has been delivered to their phone. A button with a label like "I did not receive the Push Notification" is displayed, which takes users to the QR flow.
xumm.payload.create({
txjson: {
TransactionType: "Payment",
Destination: "r...",
Amount: "1000000"
},
options: {
return_url: {
app: "https://sample.test/?...",
web: "https://sample.test/?id={id}"
},
force_network: "MAINNET"
},
custom_meta: {
identifier: "123123",
instruction: "Please sign this to..."
}
}).then(payload => {
// Redirect directly to payload.next.always, or (preferable)
var btn = document.getElementById('launchXummBtn')
btn.setAttribute('href', payload.next.always)
})ALLORNOTHING (tfAllOrNothing), Flag integer value: 65536
ONLYONE (tfOnlyOne), Flag integer value: 131072
UNTILFAILURE (tfUntilFailure), Flag integer value: 262144
INDEPENDENT (tfIndependent), Flag integer value: 524288
RawTransactions containing the inner transactions of the batch. Note that every single inner transaction needs to:
Have Fee at a string containing the value "0"
Have SigningPubkey as empty string ""
Have the Flags field contain the flag indicating it is an inner Batch transaction: 1073741824
One of the amazing features of Batch is the ability to atomically have multiple parties interact. Combined with ALLORNOTHING on the upper Batch, this allows for fully atomic transactions between multiple parties, where either every participant gets what they agreed to, or none of them do.
To use this feature, every individual party involved in the inner 'RawTransactions' need to provide a signature for the entire batch, then to be combined in the parent Batch. At this point any account (even one not participating in the inner Batch transactions) can bundle and submit, as the combined inner batch participant's transactions will satisfy the signing requirements.
Normally, the Batch transaction would require a formatted object with signers and signatures to be added to the Batch transaction in the BatchSigners field, as per XRPL's Batch specification.
To make it easier to deal with multiple inner signers, when using the Xaman SDK / API you can gather individual signer's transactions and then combine using only the Payload UUID's (or signed transaction blobs), at which point Xaman will 'unfurl' the information to craft a valid Batch transaction with multiple signers.
The workflow woud be as follows:
Craft the Batch transaction with the RawTransactions containing all transactions to be approved (signed) by different participants. At this stage the r-addresses for the individual transactions must already be known (see: SignIn). The overall Batch may look like below.
At this stage the upper Batch Transaction can have the Sequence/Ticket , Fee, and Account fields omitted. They don't have to be known yet, as they can be added later when the inner transactions are signed and any account can submit the bundle.
As can be seen in the proposed JSON transaction above, two signers will need to approve the transaction:
rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ
r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4
Each participant can now be presented with the Batch to be approved, where the signer is pre-filled, and thus enforced. The payload will have to be created with submit: false as we don't want to try to submit, we just want to get a signature from the Batch participant.
This means if someone with Xaman installed without the specific account present with signing permissions, Xaman will reject the sign request.
The same routine has then to be walked through for other signers.
Every Sign Request in the previous steps (per signer) is assigned an uuid. Gather those who are signed succesfully by the inner Batch transactions participants, to be combined (bundled) later to submit the Batch transaction. Now a specific signer is not required and submit can be true .
Note! While the official Batch spec requires a full signer object to be present in the BatchSigners field, Xaman accepts three different notations:
Conform native XRPL implementation: BatchSigners formatted object, containing an STArray with multiple signer pubkeys + their signature
Xaman specific (more convenient): the signed TX blob (as string) - this works for TX blobs signed by Xaman, or by any other XRPL signing implementation.
Xaman specific (most convenient): the signed Payload UUID - this works only if all signers are Xaman users.
const paload = await xumm.payload.create({
txjson: {
TransactionType: "Payment",
Destination: "r...",
Amount: "1000000"
},
options: {
return_url: {
app: "https://sample.test/?...",
web: "https://sample.test/?id={id}"
},
force_network: "MAINNET"
},
custom_meta: {
identifier: "123123",
instruction: "Please sign this to..."
}
})
// Now assigin the link to a button or redirect the user straight away to:
// payload.next.alwaysxumm.payload.createAndSubscribe({
TransactionType: 'Payment',
Destination: 'rfHn6cB5mmqZ6fHZ4fdemCDSxqLTijgMwo',
Amount: String(1000000) // one million drops, 1 XRP
}, eventMessage => {
if ('opened' in eventMessage.data) {
// Update the UI? The payload was opened.
}
if ('signed' in eventMessage.data) {
// The `signed` property is present, true (signed) / false (rejected)
return eventMessage
}
})
.then(({ created, resolved }) => {
console.log('Payload URL:', created.next.always)
console.log('Payload QR:', created.refs.qr_png)
return resolved // Return payload promise for the next `then`
})
.then(payload => console.log('Payload resolved', payload))
// This is where you can do `xumm.payload.get(...)` to fetch detailsconst { created, resolved } = await xumm.payload.createAndSubscribe({
TransactionType: 'Payment',
Destination: 'rfHn6cB5mmqZ6fHZ4fdemCDSxqLTijgMwo',
Amount: String(1000000) // one million drops, 1 XRP
}, eventMessage => {
if ('opened' in eventMessage.data) {
// Update the UI? The payload was opened.
}
if ('signed' in eventMessage.data) {
// The `signed` property is present, true (signed) / false (rejected)
return eventMessage
}
})
console.log('Payload URL:', created.next.always)
console.log('Payload QR:', created.refs.qr_png)
const payload = await resolved
console.log('Resolved', payload){
"TransactionType": "Batch",
"Flags": 65536,
"Fee": "1337",
"RawTransactions": [
{
"RawTransaction": {
"TransactionType": "Payment",
"Account": "rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ",
"Destination": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
"Amount": "100",
"Sequence": 36969,
"Fee": "0",
"Flags": 1073741824,
"SigningPubKey": ""
}
},
{
"RawTransaction": {
"TransactionType": "CredentialCreate",
"Expiration": 889004799,
"Account": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
"Subject": "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ",
"URI": "CAFEBABE",
"CredentialType": "4B5943CAFEBABE",
"Sequence": 36971,
"Flags": 1073741824,
"Fee": "0",
"SigningPubKey": ""
}
}
]
}{
"options": {
"submit": false,
"signer": "rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ"
},
"txjson": {
"TransactionType": "Batch",
"Flags": 65536,
"Fee": "1337",
"RawTransactions": [
{
"RawTransaction": {
"TransactionType": "Payment",
"Account": "rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ",
"Destination": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
"Amount": "100",
"Sequence": 36969,
"Fee": "0",
"Flags": 1073741824,
"SigningPubKey": ""
}
},
{
"RawTransaction": {
"TransactionType": "CredentialCreate",
"Expiration": 889004799,
"Account": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
"Subject": "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ",
"URI": "CAFEBABE",
"CredentialType": "4B5943CAFEBABE",
"Sequence": 36971,
"Flags": 1073741824,
"Fee": "0",
"SigningPubKey": ""
}
}
]
}
}{
"options": {
"submit": true
},
"txjson": {
"TransactionType": "Batch",
"Flags": 65536,
"Fee": "1337",
"BatchSigners": [
"82a46463-c8e7-4f5f-9a9e-4cc8a5b332b9",
"15dce664-a040-40ca-8de7-fdf3cc337055"
],
"RawTransactions": [
{
"RawTransaction": {
"TransactionType": "Payment",
"Account": "rnMsCBhSWeK3ngU7JWkejHsYZs3UVWqNoQ",
"Destination": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
"Amount": "100",
"Sequence": 36969,
"Fee": "0",
"Flags": 1073741824,
"SigningPubKey": ""
}
},
{
"RawTransaction": {
"TransactionType": "CredentialCreate",
"Expiration": 889004799,
"Account": "r38xHAWRdc5enrYsHKQxUzHf6javKrV3i4",
"Subject": "rwietsevLFg8XSmG3bEZzFein1g8RBqWDZ",
"URI": "CAFEBABE",
"CredentialType": "4B5943CAFEBABE",
"Sequence": 36971,
"Flags": 1073741824,
"Fee": "0",
"SigningPubKey": ""
}
}
]
}
}subscribeUse minimal of 16pt font for standard body text
Test on different devices:
Manage information on a logical level
Consistency in design
Use a 40x40px target area for touch controls
Good (horizontal) alignment:
Distinction between primary and secondary Buttons:
Clear error text:
Appropriate color contrast:
No slang or bad grammar. Use proper English.
Human like language:
Breaking up content:






