Prerequisites
Before using UOA, you need:
Get your API keys
In your dashboard, create a new application and obtain your Secret Key . You will use this as the X-MAGIC-SECRET-KEY header on all requests.
Set up authentication
Choose one of the authentication options below to issue JWTs for your users.
Register your app with UOA
Register your application with your Magic secret key and OIDC configuration so UOA can validate your user JWTs. curl -X POST 'https://uoa-server.magic.xyz/apps' \
-H 'Content-Type: application/json' \
-d '{
"name": "My App",
"magic_app_secret_key": "sk-live-XXXXXXXX",
"magic_oidc_provider_id": "YOUR_OIDC_PROVIDER_ID",
"issuer": "https://your-auth-provider.com",
"audience": "your-app-audience",
"jwks_url": "https://your-auth-provider.com/.well-known/jwks.json"
}'
Authentication Options
UOA requires a JWT (Authorization header) and your Magic secret key (X-MAGIC-SECRET-KEY header) on every request. You can obtain the user JWT through either Magic Embedded Wallets or an external identity provider.
Use Magic Embedded Wallets to authenticate users directly in your frontend. The Magic SDK handles login and issues a DID token that you use as the JWT for UOA requests. Install the Magic SDK Initialize Magic import { Magic } from 'magic-sdk' ;
const magic = new Magic ( process . env . NEXT_PUBLIC_MAGIC_PUBLISHABLE_KEY ! );
Authenticate and get a DID token // Log in with Email OTP
const didToken = await magic . auth . loginWithEmailOTP ({ email: '[email protected] ' });
// Or use any other Magic login method:
// await magic.auth.loginWithSMS({ phoneNumber: '+1234567890' })
// await magic.oauth.loginWithRedirect({ provider: 'google' })
Use the DID token with UOA Pass the DID token as the Authorization header on your backend when making UOA API calls: const response = await fetch ( 'https://uoa-server.magic.xyz/account' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ didToken } ` ,
'X-MAGIC-SECRET-KEY' : process . env . MAGIC_SECRET_KEY ! ,
},
});
The X-MAGIC-SECRET-KEY is a server-side secret. Never expose it in client-side code. Use a backend proxy to forward requests to UOA.
When using Magic Embedded Wallets, you can use the Magic OIDC provider ID from your dashboard when registering your app with UOA. The issuer and JWKS URL are provided by Magic automatically.
Configure an external identity provider (Auth0, Firebase Auth, NextAuth, or a custom OIDC provider) that issues JWTs for your users. Register your JWT issuer, audience, and JWKS URL with UOA during app registration so it can validate your tokens. Send authenticated requests Include both the user’s JWT and your Magic secret key on every request: Authorization: Bearer < USER_JWT_TOKE N >
X-MAGIC-SECRET-KEY: < YOUR_MAGIC_SECRET_KE Y >
The X-MAGIC-SECRET-KEY is a server-side secret. Never expose it in client-side code. Use a backend proxy to forward requests to UOA.
Create an Account
Create or fetch a user account. This provisions wallets across all supported chains automatically.
curl -X POST 'https://uoa-server.magic.xyz/account' \
-H 'Authorization: Bearer USER_JWT_TOKEN' \
-H 'X-MAGIC-SECRET-KEY: YOUR_MAGIC_SECRET_KEY'
Response:
{
"success" : true ,
"app_user_id" : "user-123" ,
"user_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"public_address" : {
"ETH" : "0x1234567890abcdef1234567890abcdef12345678" ,
"SOL" : "7nYB5F2xVT9hVjhxUoZ5HQxvPz2kTmSoQvGPmxfTjKN"
},
"perp_dex_status" : {}
}
Calling POST /account multiple times for the same user returns the same account. Wallet addresses are derived deterministically.
Check Wallet Balances
Once the account is created, you can query on-chain balances across all chains.
curl -X GET 'https://uoa-server.magic.xyz/account/wallet' \
-H 'Authorization: Bearer USER_JWT_TOKEN' \
-H 'X-MAGIC-SECRET-KEY: YOUR_MAGIC_SECRET_KEY'
Response:
{
"public_address" : {
"ETH" : "0x1234...5678" ,
"ARB" : "0x1234...5678" ,
"POL" : "0x1234...5678" ,
"SOL" : "7nYB5F...TjKN"
},
"assets" : {
"ETH" : { "ETH" : "0.05" , "USDC" : "100.00" },
"ARB" : { "ETH" : "0.01" , "USDC" : "250.00" },
"SOL" : { "SOL" : "1.5" , "USDC" : "50.00" }
}
}
Initialize a Perp DEX
Before you can deposit funds into a DEX venue, you need to initialize it for the user. First, check if the requirements are met:
curl -X POST 'https://uoa-server.magic.xyz/account/check-perp-dex-requirements' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer USER_JWT_TOKEN' \
-H 'X-MAGIC-SECRET-KEY: YOUR_MAGIC_SECRET_KEY' \
-d '{
"dex": "hyperliquid"
}'
Then initialize:
curl -X POST 'https://uoa-server.magic.xyz/account/init-perp-dex' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer USER_JWT_TOKEN' \
-H 'X-MAGIC-SECRET-KEY: YOUR_MAGIC_SECRET_KEY' \
-d '{
"dex": "hyperliquid"
}'
Response:
{
"success" : true ,
"dex" : "hyperliquid" ,
"status" : {
"initialized" : true ,
"onboarded_at" : "2026-04-01T12:00:00Z"
},
"message" : "Hyperliquid initialized successfully"
}
Execute a Transfer
Create a transfer to move funds between locations. UOA plans the route and executes it asynchronously.
Estimate Costs
Before executing, estimate the transfer cost:
curl -X POST 'https://uoa-server.magic.xyz/transfer/estimate-transfer-cost' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer USER_JWT_TOKEN' \
-H 'X-MAGIC-SECRET-KEY: YOUR_MAGIC_SECRET_KEY' \
-d '{
"source": "self",
"destination": "hyperliquid",
"amount": "100",
"chain": "ARB",
"token": "USDC"
}'
Create the Transfer
curl -X POST 'https://uoa-server.magic.xyz/transfer' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer USER_JWT_TOKEN' \
-H 'X-MAGIC-SECRET-KEY: YOUR_MAGIC_SECRET_KEY' \
-d '{
"source": "self",
"destination": "hyperliquid",
"amount": "100",
"chain": "ARB",
"token": "USDC"
}'
Response:
{
"success" : true ,
"task_id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"message" : "Transfer task created and executing"
}
Monitor Progress
Poll the task to track execution:
curl -X GET 'https://uoa-server.magic.xyz/task/a1b2c3d4-e5f6-7890-abcd-ef1234567890' \
-H 'Authorization: Bearer USER_JWT_TOKEN' \
-H 'X-MAGIC-SECRET-KEY: YOUR_MAGIC_SECRET_KEY'
Response:
{
"task_id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"source" : "self" ,
"destination" : "hyperliquid" ,
"amount" : "100" ,
"chain" : "ARB" ,
"token" : "USDC" ,
"status" : "COMPLETED" ,
"progress" : {
"current_step" : 2 ,
"total_steps" : 2 ,
"steps" : [
{ "action" : "approve" , "status" : "completed" },
{ "action" : "deposit" , "status" : "completed" }
]
}
}
Resume a Failed Transfer
If a transfer fails, you can resume it from the last checkpoint:
curl -X POST 'https://uoa-server.magic.xyz/task/a1b2c3d4-e5f6-7890-abcd-ef1234567890/resume' \
-H 'Authorization: Bearer USER_JWT_TOKEN' \
-H 'X-MAGIC-SECRET-KEY: YOUR_MAGIC_SECRET_KEY'
Next Steps
API Reference Explore the complete API surface including all endpoints, parameters, and response schemas.
Express API Learn about the underlying Express API that powers UOA wallet operations.