For the complete documentation index, see llms.txt. This page is also available as Markdown.

Authenticated Endpoints

REST API endpoints requiring signature authentication

All authenticated endpoints require EIP-712, EIP-2612, or canonical-JSON personal_sign signatures depending on the endpoint.

Base URL: https://api.app.hello.trade/api


POST /api/referral/apply

Apply an invite code to grant a wallet app access. Without app access, the wallet cannot authenticate against any other authed write endpoint — see Authentication & Account Model — App Access Gate.

Headers

Header
Description

content-type

application/json

x-signature

viem personal_sign over the canonical-JSON payload below

x-timestamp

The same timestamp value used in the signed payload (Date.now() ms)

x-nonce

The same nonce value used in the signed payload — must be unique per request, [A-Za-z0-9_-]{8,128}

Signed Payload (canonical JSON)

{
  "body":{
    "code":"HELLO12",
    "walletAddress":"0xabc..."
    },
  "method":"POST",
  "nonce":"<unique>",
  "path":"/referral/apply",
  "timestamp":1715500000000,
  "walletAddress":"0xabc..."
}
Field
Description

body

The full request body, with keys sorted alphabetically. null for bodyless requests. Bodies must be flat JSON objects — nested objects are not deterministically ordered by this scheme.

method

Literal "POST"

nonce

Matches the x-nonce header

path

Literal "/referral/apply"

timestamp

Matches x-timestamp; ms since epoch; server enforces a ±5 minute window

walletAddress

Lowercased wallet that is applying the code

Top-level keys must appear in alphabetical order with no whitespace; keys inside body must also be sorted alphabetically. The server canonicalizes identically before recovering the signer, so any tampering with body fields invalidates the signature.

Request Body

Field
Type
Description

walletAddress

string

Lowercased wallet address (must match the walletAddress in the signed payload)

code

string

Invite code, [A-Z0-9-]{1,7}. Must match the code field inlined under body in the signed payload.

Response — Success

HTTP status 201 Created. kind is "attributed" for affiliate codes and "system" for admin-minted codes; the "system" branch omits referrerAddress.

Response — Errors

HTTP
Body shape
Notes

400

{"error":"walletAddress and code are required"}

Malformed body

401

{"error":"Unauthorized: <reason>"}

Signature problem (missing headers, expired timestamp, replay, or signer mismatch)

422

{"error":"ALREADY_REFERRED"}

Wallet has already applied a referral code. Attribution is first-touch and immutable.

422

{"error":"CODE_NOT_FOUND"}

No referral code matches the submitted string

422

{"error":"CODE_REVOKED"}

Code is valid but has been revoked. The affiliate likely rotated it; ask for a current code.

422

{"error":"CODE_EXHAUSTED"}

Code has reached its maxUses limit

422

{"error":"SELF_REFERRAL"}

The signer owns the code they're trying to apply

503

{"error":"Referral service unavailable, please retry"}

Transient transport failure between api-gateway and the referral service. Safe to retry.

504

{"error":"Referral service timed out, please try again later"}

Upstream is reachable but slow. Back off before retrying — tight retry loops can worsen a wedge.

TypeScript example

After a successful apply, re-check GET /api/user/access-status/:walletAddress if you want a positive read before issuing further signed requests.


POST /api/margin/deposit

Deposit collateral using ERC-2612 permit and vault authorization.

Request

Field
Type
Description

amount

string

Deposit amount (human-readable, e.g., "1000.50")

instrument

string | null

Instrument symbol for isolated margin, null for cross margin

marginMode

string

"Cross" or "Isolated"

permitSignature

Object

ERC-2612 permit signature (type 0x05)

depositSignature

Object

Vault deposit authorization signature (type 0x07)

Important Notes:

  • Requires two signatures: Permit (token approval) and Deposit (vault authorization)

  • permitSignature.payload contains encoded Permit struct (token nonce must be fetched from token contract)

  • depositSignature.payload contains encoded Deposit struct (includes market, flags, deadline)

  • Cross margin: instrument: null, marginMode: "Cross", and in the Deposit signature market: 0, flags bit 0 = 0

  • Isolated margin: instrument set to the market's symbol, marginMode: "Isolated", and in the Deposit signature market = the instrument ID, flags bit 0 = 1. The collateral lands in that market's isolated margin.

For signature construction, see Signatures - Deposits.

Response

Field
Type
Description

command_id

u64

Command ID for tracking

status

string

Submitted or Rejected

Track deposit completion via DepositMargin execution report on WebSocket.


POST /api/margin/withdrawal

Withdraw collateral.

Request

Field
Type
Description

amount

string

Withdrawal amount (human-readable, e.g., "500.25")

instrument

string | null

Instrument symbol for isolated margin, null for cross margin

marginMode

string

"Cross" or "Isolated"

signature

Object

EIP-712 withdrawal signature (type 0x03)

Important Notes:

  • signature.payload contains encoded Withdrawal struct with owner, amount, market, flags, nonce, deadline

  • Cross margin: instrument: null, marginMode: "Cross", and in the signature market: 0, flags bit 0 = 0

  • Isolated margin: instrument set to the market's symbol, marginMode: "Isolated", and in the signature market = the instrument ID, flags bit 0 = 1. Withdraws from that market's isolated margin; alternatively transfer to cross first and withdraw from there.

For signature construction, see Signatures - Withdrawals.

Response

Track withdrawal completion via WithdrawMargin execution report on WebSocket.


POST /api/margin/transfer

Move collateral between cross margin and a market's isolated margin. No tokens move on- or off-chain — the transfer reallocates collateral within the account.

Request

Field
Type
Description

amount

string

Transfer amount (human-readable, e.g., "250.00")

instrument

string

Instrument symbol of the isolated market

direction

string

"crossToIsolated" or "isolatedToCross"

signature

Object

EIP-712 margin transfer signature (type 0x08)

Important Notes:

  • signature.payload contains the encoded MarginTransfer struct with owner, amount, market, flags, nonce, deadline

  • market in the signature is the instrument ID of the isolated market (both directions)

  • flags bit 0 carries the source account's margin mode — 0 for crossToIsolated, 1 for isolatedToCross — and must match direction

  • crossToIsolated draws from cross withdrawable (free collateral); isolatedToCross draws from the market's free isolated margin

For signature construction, see Signatures - Margin Transfers.

Response

Track transfer settlement via TransferMargin execution report on WebSocket. The same operation is also available over the trading WebSocket as a transferMargin message (acked with marginTransferred).


POST /api/update_leverage

Update leverage for an instrument.

Request

Field
Type
Description

leverage

u32

Leverage × 100 (e.g., 1000 = 10x)

instrument

string

Instrument symbol

marginMode

string

"Cross" or "Isolated"

signature

Object

EIP-712 leverage update signature (type 0x04)

Important Notes:

  • signature.payload contains encoded LeverageUpdate struct with account, market, leverage, flags, nonce, deadline

  • flags bit 0 must match marginMode (0 = Cross, 1 = Isolated)

  • Leverage is tracked per margin mode: the same instrument can hold different leverage cross vs isolated

For signature construction, see Signatures - Leverage Updates.

Response

Track leverage update completion via UpdateLeverage execution report on WebSocket.


Common Errors

HTTP Status
Description

400

Bad Request (invalid parameters, signature verification failed)

404

Not Found (account not found)

500

Internal Server Error

Error response format:

For detailed error descriptions, see Error Codes.

Last updated