Authentication
d.pro JWT session — wallet-based challenge-response authentication for API features.
Authentication
d.pro uses a wallet-based JWT authentication system. Users prove ownership of their wallet address by signing a backend-generated challenge, then receive a JWT session token for subsequent API calls.
This is separate from Hyperliquid's on-chain transaction signing. You need both:
- d.pro JWT — for d.pro API features (referrals, OPC, watchlist, cohort)
- Hyperliquid signature — for on-chain actions (orders, transfers, approvals)
Hyperliquid itself is stateless — it validates on-chain signatures. The d.pro JWT layer exists purely to support d.pro's stateful application features.
Authentication flow
Request a login challenge
POST /api/v1/auth/login
Content-Type: application/json
{
"address": "0xYOUR_WALLET_ADDRESS"
}Response:
{
"message": "Sign this message to authenticate with d.pro: nonce_abc123_1708622398623",
"nonce": "nonce_abc123_1708622398623"
}The message is a random challenge that expires after a short window (typically 5 minutes).
Sign the challenge with your wallet
Use your wallet's personal_sign (EIP-191) to sign the message string returned in step 1.
In a browser wallet:
const signature = await window.ethereum.request({
method: 'personal_sign',
params: [message, address],
});With ethers.js:
const signature = await signer.signMessage(message);Submit the signed message
POST /api/v1/auth/sign-message
Content-Type: application/json
{
"address": "0xYOUR_WALLET_ADDRESS",
"message": "Sign this message to authenticate with d.pro: nonce_abc123_1708622398623",
"signature": "0xSIGNATURE_HEX"
}The backend:
- Recovers the signer address from the signature
- Verifies it matches the
addressfield - Checks the nonce has not been used before
- Returns a JWT token
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresAt": "2025-05-22T10:00:00Z"
}Use the JWT token
Include the token in the Authorization header for all protected d.pro API calls:
GET /api/v1/referral/status
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Refresh the token
Before the token expires, refresh it to extend the session:
POST /api/v1/auth/refresh
Authorization: Bearer CURRENT_TOKENResponse:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9_NEW...",
"expiresAt": "2025-06-22T10:00:00Z"
}The old token is invalidated. Replace it in your application storage.
Token storage
- Browser: Store in
localStorageorsessionStorage.localStoragepersists across sessions;sessionStorageclears on tab close. - Server / Bot: Store in an environment variable or secure secrets manager. Never commit tokens to source control.
JWT tokens grant full access to d.pro's API features for your wallet. Treat them like a password. If you suspect a token is compromised, log out (which invalidates the token) and re-authenticate.
Security model
d.pro's JWT auth is designed for application-layer features only. It cannot:
- Move funds on Hyperliquid
- Place orders on Hyperliquid
- Approve builder fees
All on-chain actions still require a valid on-chain signature from your wallet or an authorized Agent Key. The JWT is purely for d.pro's own API (referrals, OPC, watchlist, cohort management).