d.prod.pro docs
API

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:

  1. Recovers the signer address from the signature
  2. Verifies it matches the address field
  3. Checks the nonce has not been used before
  4. 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_TOKEN

Response:

{
  "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 localStorage or sessionStorage. localStorage persists across sessions; sessionStorage clears 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).

On this page