Kotlin snippets call
suspend SDK APIs; run them from a coroutine.How it works
1
Backend: get a bearer token
Exchange your OMS API key and secret for a short-lived bearer token.
2
Backend: create a customer
The customer’s
email is the address that can claim the wallet.3
Backend: preallocate a wallet
OMS returns a wallet ID (
wlt_...) and an address. The wallet is receive-only until it is claimed.4
Backend: fund the address (optional)
Send funds to the address before or after the claim.
5
App: sign the user in
The user signs in with that email. Unless the user already owns a wallet of that type, the SDK claims the wallet and activates it.
6
App: claim other wallets (optional)
Claim wallets that sign-in reported but did not claim.
7
Backend: confirm the claim (optional)
Check that the user claimed the wallet.
Prerequisites
YOUR_API_KEYandYOUR_API_SECRET: an OMS API key and its secret from the API Keys page of the OMS Dashboard. Create them in the same project and environment as your app’s publishable key. The OMS API is in early access; see Get started if your project does not have API keys yet. A wallet preallocated in one project or environment is not claimable from another. The secret is shown only once, when you create the key.- The OMS API base URL for the same environment as your app’s publishable key. The examples use Sandbox,
https://sandbox-api.polygon.technology/v0.13. For Production, usehttps://api.polygon.technology/v0.13. - An app that signs users in with the TypeScript, Swift, or Kotlin SDK, version 0.4.0 or later. To build an app, start with the quickstart for TypeScript, Swift, or Kotlin.
- The user’s email address. This guide uses
user@example.com.
1. Get a bearer token (backend)
Exchange the API key and secret for a bearer token:accessToken as Authorization: Bearer YOUR_ACCESS_TOKEN in steps 2 and 3. Request a new token before expiresAt. See Get bearer token.
2. Create a customer with the user’s email (backend)
If the user is already a customer, skip this step and use their existing customerid; check that its email is the address the user signs in with.
Otherwise, create the customer that the wallet belongs to. Set email to the address the user will sign in with. Only a user who signs in with that email can claim the wallet.
Idempotency-Key, such as a UUID, for each request, and reuse it only to retry that same request.
Your project’s KYC policy can require more fields for an individual, such as phone, birthDate, residentialAddress, or identifyingInformation. If the request returns 400, add the fields your project requires. See Create a customer for the full request schema.
A 201 response returns the customer. Store its id:
status depends on your project’s verification policy.
If the response is 202, creation is still running. Wait the number of seconds in the Retry-After header, then repeat the request with the same Idempotency-Key until it returns 201.
3. Preallocate the wallet (backend)
Create a non-custodial wallet for the customer. SetcustomerId to the customer id from step 2, and set details.networkFamily to evm, solana, or tron:
201 response returns the wallet with status set to preallocated:
id and details.address with your customer record.
Each email in a project has at most one preallocated wallet per network family, and allocations never expire. Repeating the request for the same email and network family, even with a new Idempotency-Key, returns the same wallet. To preallocate wallets on more than one network family, send one request per family.
4. Fund the address (optional, backend)
Send assets todetails.address. For test funds on an evm wallet, use Polygon Amoy (80002).
5. Sign the user in (app)
Sign the user in with the email you set on the customer, using either:- Email OTP for that email.
- An OIDC provider configured for your project whose ID token contains that
emailwithemail_verifiedset totrue.
User@Example.com matches user@example.com.
If the user signs in with a different email, or with an OIDC provider that does not report the email as verified, no wallet is claimable. Sign-in still succeeds: automatic selection activates a wallet the user already owns or creates a new one, without an error, and the preallocated wallet stays unclaimed.
With the default automatic wallet selection, the SDK activates a wallet of the requested wallet type in this order:
- A wallet of that type that the user already owns.
- Otherwise, a claimable wallet of that type, which the SDK claims.
- Otherwise, a new wallet.
walletType to completeEmailAuth, signInWithOidcIdToken, or the call that starts a redirect sign-in. It defaults to Ethereum. The network families from step 3 map to wallet types as evm to Ethereum, solana to Solana, and tron to Tron.
In these snippets, omsWallet is the OMSWallet instance your app configured with YOUR_PUBLISHABLE_KEY.
- TypeScript
- Swift
- Kotlin
id is the wlt_... ID and its address is the details.address from step 3. The user now owns the wallet, it appears in listWallets, and the session can sign with it.
If the SDK tries to claim the wallet and the claim fails, sign-in fails with the error in Handle claim errors, no session is stored, and the SDK does not create a new wallet instead.
6. Claim other wallets (optional, app)
Only a completed sign-in reports claimable wallets;listWallets does not include a wallet until it is claimed. A wallet the user does not claim is reported again at the next sign-in.
The sign-in result’s claimableWallets lists every claimable wallet that sign-in did not claim, of any wallet type.
Claim them with claimWallet while the session is active. Each claimed wallet becomes the active wallet, so switch back with useWallet if you need to. These snippets continue from the step 5 result.
- TypeScript
- Swift
- Kotlin
claimAndSelectWallet. See the authentication page for TypeScript, Swift, or Kotlin.
7. Confirm the claim (optional, backend)
After the user signs in, confirm the claim with either method:- Repeat the step 3 request with a new
Idempotency-Key. After the claim, it returns the same wallet withstatusset toactive. - Have your app send an OMS Wallet ID token after sign-in, and verify it as described in backend wallet verification. Compare its
wallet_addressclaim with the storeddetails.address.
Handle claim errors
A claim fails withAccountNotFound when the wallet is not preallocated for the signed-in user’s verified email, was already claimed, or the sign-in has no verified email:
Next steps
- Sessions and access for switching between the user’s wallets after a claim: TypeScript, Swift, or Kotlin.
- Backend wallet verification to confirm on your backend which wallet a user controls.