Skip to main content

Prerequisites

Before using UOA, you need:
1

Create a Magic Account

Visit the Magic Dashboard and sign up for a Magic developer account.
2

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

Set up authentication

Choose one of the authentication options below to issue JWTs for your users.
4

Register your app with UOA

Register your application with your Magic secret key and OIDC configuration so UOA can validate your user JWTs.
cURL
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

npm
npm install magic-sdk

Initialize Magic

lib/magic.ts
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.

Create an Account

Create or fetch a user account. This provisions wallets across all supported chains automatically.
cURL
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
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
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
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
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
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
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
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.