3rd party API

Overview

This document describes the HTTP API that external partners can use to automate account provisioning, portfolio monitoring, trading oversight, and conversational support. All endpoints are versioned under /api/v1 and require an API key. Need an API key? contact us on discord

Authentication

  • API key. Each partner receives an API key; send it with every request via the X-API-Key header. Example:

    curl -H "X-API-Key: sk_live_123" https://.../api/v1/users
  • User ownership. Downstream resources (wallets, position_theses, holdings, transactions, auto_trade_*, conversations, etc.) are scoped to a specific userId. Always supply the user ID in the path when the endpoint targets a user.

Error Handling

Every endpoint returns standard HTTP status codes. Error bodies follow this structure:

{
  "error": {
    "code": "string",
    "message": "Human readable explanation",
    "details": { "field": "optional data" }
  }
}

Pagination & Filtering

  • Collection endpoints accept page, pageSize (default 25, max 200), sort, and resource-specific filters.

Resource Models

Below are the core objects returned by the API.

Resource
Fields
Example

User

id, signupWalletId, wallets[] (each id, address, chain, type), provider, invitedBy, createdAt, updatedAt

{"id":"usr_123","provider":"wallet","wallets":[{"id":"wal_signup","address":"7HgJ...","chain":"solana","type":"signup"}]}

Holding

id, wallet, tokenAddress, chain, decimals, assetClass, totalHoldings, tokenUSDPrice, tokenSolPrice, totalUSDval, totalSolval, usdValueUpdatedAt, timestamps

{"id":"hld_1","wallet":"wal_1","tokenAddress":"So1111...","assetClass":"majors","totalUSDval":"200500.12"}

Transaction

id, walletId, orderId, txType (buy, sell, swap), fromToken, toToken, txAmount, toAmount, txSignature, solValue, usdValue, feeInLamports, timestamps

{"id":"txn_1","walletId":"wal_1","txType":"buy","usdValue":"2400.12","orderId":"ord_1"}

PositionThesis

id, userId, walletId, tokenAddress, tokenSymbol, thesis, riskRewardRatio, confidence, expiresAt, timestamps

{"id":"ths_1","userId":"usr_123","tokenSymbol":"HYPE","confidence":0.45}

AutoTradeLog

id, userId, log, thoughts, tokenAddress, createdAt

{"id":"log_1","userId":"usr_123","log":"Opened thesis on HYPE"}

AutoTradeInstruction

id, userId, instructions, allocation, allowList, strategy, riskTolerance, isActive, timestamps

{"id":"ati_1","userId":"usr_123","isActive":true,"riskTolerance":"balanced"}

Conversation

conversationId, userId, messages[] (each id, role, content, createdAt), updatedAt

{"conversationId":"65f...","userId":"usr_123","messages":[{"role":"user","content":"What is my PnL?"}]}

User payloads embed wallets, which mirror rows in milo.wallets and expose id, address, and chain (network, currently solana). The type field is normalized for this API: the wallet referenced by signupWalletId is labeled signup, and non-custodial wallets provisioned by Milo are labeled milo.

Wallet Structure Example

{
  "id": "wal_signup",
  "address": "7HgJ...signup",
  "chain": "solana",
  "type": "signup"
}

type is either signup (the onboarding wallet) or milo (non-custodial wallets issued by Milo). Additional non-custodial wallets inherit the same structure with their respective identifiers.

Endpoints

All endpoints below require the X-API-Key header described earlier (examples omit it for brevity). User-scoped endpoints always identify the target user through the userId path parameter.

1

Create User

Create a trading user and the first wallet. This endpoint fails with 409 Conflict if the supplied wallet already belongs to an existing Milo user.

  • Method: POST

  • Path: /api/v1/users

  • Headers: X-API-Key

  • Body:

{
  "signupWallet": "7HgJ... WALLET_ADDRESS"
}
  • Response:

{
  "user": {
    "id": "uuid",
    "signupWalletId": "uuid",
    "wallets": [
      {
        "id": "uuid",
        "address": "7HgJ...",
        "chain": "solana",
        "type": "signup"
      },
      {
        "id": "uuid",
        "address": "HCm9...",
        "chain": "solana",
        "type": "milo"
      }
    ],
    "provider": "wallet",
    "invitedBy": null,
    "createdAt": "2024-01-01T00:00:00.000Z",
    "updatedAt": "2024-01-01T00:00:00.000Z"
  }
}
2

Get Diary Logs

Return the short auto-trader diary entries attached to a user (auto_trade_logs).

  • Method: GET

  • Path: /api/v1/users/{userId}/diary-logs?page=1&pageSize=20

  • Response:

{
  "diaryLogs": [
    {
      "id": "uuid",
      "userId": "uuid",
      "log": "Opened thesis on HYPE",
      "thoughts": "Watching liquidity",
      "tokenAddress": "So111111...",
      "createdAt": "2024-01-01T00:00:00.000Z"
    }
  ],
  "page": 1,
  "pageSize": 20,
  "total": 58
}
3

Get Executed Transactions

List fulfilled blockchain transactions that originated from an order (non-null orderId).

  • Method: GET

  • Path: /api/v1/wallets/{walletId}/executed-transactions?since=2024-01-01T00:00:00Z

  • Filters: txType (buy, sell, swap), token, minUsdValue, since, until.

  • Response:

{
  "executions": [
    {
      "id": "uuid",
      "walletId": "uuid",
      "orderId": "uuid",
      "txType": "buy",
      "fromToken": "So1111...",
      "toToken": "DezXAZ8z7PnrnR...",
      "txAmount": "20.00",
      "toAmount": "120000.00",
      "txSignature": "5t7...",
      "solValue": "20.4",
      "usdValue": "2400.12",
      "feeInLamports": 5000,
      "createdAt": "2024-01-01T00:00:00.000Z"
    }
  ]
}
4

Get Holdings

Return the latest balance snapshot from the holdings table for a wallet or for every wallet accessible with the API key.

  • Method: GET

  • Path: /api/v1/wallets/{walletId}/holdings

  • Response:

{
  "holdings": [
    {
      "id": "uuid",
      "wallet": "uuid",
      "tokenAddress": "So1111...",
      "chain": "solana",
      "decimals": 9,
      "assetClass": "majors",
      "totalHoldings": "1250000000",
      "tokenUSDPrice": "160.40",
      "tokenSolPrice": "1",
      "totalUSDval": "200500.12",
      "totalSolval": "1250.50",
      "usdValueUpdatedAt": "2024-01-01T00:00:00.000Z",
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    }
  ]
}
5

Get Positions (Theses)

Fetch the user’s open and historical theses, enriched with linked orders and PnL metrics.

  • Method: GET

  • Path: /api/v1/users/{userId}/positions?status=active

  • Query Params: status (active, pending, not_active) optional.

  • Response:

{
  "positions": [
    {
      "thesisId": "ths_123",
      "userId": "usr_123",
      "walletId": "wal_1",
      "tokenSymbol": "HYPE",
      "tokenAddress": "So1111...",
      "tokenCanonical": "So1111...",
      "thesis": "Accumulating ahead of catalyst",
      "riskRewardRatio": 3.5,
      "confidence": 0.45,
      "thesisExpiresAt": null,
      "thesisCreatedAt": "2024-01-01T00:00:00.000Z",
      "thesisUpdatedAt": "2024-01-02T00:00:00.000Z",
      "entries": [
        {
          "orderId": "ord_entry",
          "createdAt": "2024-01-01T00:00:00.000Z",
          "status": "fulfilled",
          "executedAvgUnitPriceUsd": 0.002,
          "executedQty": 120000
        }
      ],
      "exits": [
        {
          "orderId": "ord_exit",
          "createdAt": "2024-01-05T00:00:00.000Z",
          "status": "fulfilled",
          "executedAvgUnitPriceUsd": 0.0034,
          "executedQty": 80000,
          "type": "sell"
        }
      ],
      "takeProfits": [
        {
          "orderId": "ord_tp",
          "createdAt": "2024-01-01T00:10:00.000Z",
          "status": "active",
          "executedAvgUnitPriceUsd": null,
          "executedQty": null,
          "triggerLevel": 0.004,
          "operator": "gte",
          "allocation": 0.25,
          "expiresAt": null
        }
      ],
      "stopLosses": [],
      "buyOrders": [],
      "sellOrders": [],
      "errors": [],
      "investedUsd": 2400.12,
      "soldUsd": 800.0,
      "remainingQty": 40000,
      "realisedPnlUsd": 160.5,
      "currentPriceUsd": 0.0038,
      "priceUpdatedAt": "2024-01-05T00:00:00.000Z",
      "currentValueUsd": 152,
      "remainingCostUsd": 96,
      "unrealisedPnlUsd": 56,
      "status": "active",
      "firstBuyTime": "2024-01-01T00:00:00.000Z",
      "lastTxTime": "2024-01-05T00:00:00.000Z",
      "tokenLogoUri": "https://assets.../hype.png",
      "tokenSocials": {
        "twitter": "https://x.com/hype",
        "website": "https://hype.xyz"
      }
    }
  ]
}
6

Get Transactions

Return every on-chain confirmed transaction captured for a wallet.

  • Method: GET

  • Path: /api/v1/wallets/{walletId}/transactions?page=1&pageSize=50

  • Notes: Includes both executed order-linked transactions and ad-hoc transfers (orderId can be null). txType is always one of buy, sell, or swap.

  • Response:

{
  "transactions": [
    {
      "id": "uuid",
      "walletId": "uuid",
      "orderId": null,
      "txType": "swap",
      "fromToken": "USDC",
      "toToken": "USDC",
      "txAmount": "5000.00",
      "toAmount": "5000.00",
      "txSignature": "45s...",
      "solValue": "0",
      "usdValue": "5000.00",
      "createdAt": "2024-01-01T00:00:00.000Z"
    }
  ],
  "page": 1,
  "pageSize": 50,
  "total": 240
}
7

Update Auto Trade Settings

Upsert the auto trade settings.

  • Method: PATCH

  • Path: /api/v1/users/{userId}/auto-trade-settings

  • Field requirements:

    • riskTolerance and strategy must always be supplied.

    • allocation, instructions, and allowList are optional.

    • isActive can be set to true only if the user’s Milo wallet currently holds at least 1 SOL.

  • Body:

{
  "instructions": "Always ladder out",
  "allocation": { "memes": 0.1, "majors": 0.3, "native": 0.6 },
  "allowList": ["memes", "native"],
  "strategy": "Risk-on rotation",
  "riskTolerance": "balanced",
  "isActive": true
}
  • Response:

{
  "autoTradeSettings": {
    "id": "uuid",
    "userId": "uuid",
    "instructions": "Always ladder out",
    "allocation": { "memes": 0.1, "majors": 0.3, "native": 0.6 },
    "allowList": ["memes", "native"],
    "strategy": "Risk-on rotation",
    "riskTolerance": "balanced",
    "isActive": true,
    "createdAt": "2024-01-01T00:00:00.000Z",
    "updatedAt": "2024-01-01T00:00:00.000Z"
  }
}
8

Get Conversation

Retrieve a conversation thread as a simple array of role-based messages.

  • Method: GET

  • Path: /api/v1/conversations/{conversationId}

  • Response:

{
  "conversation": {
    "conversationId": "65f...",
    "userId": "usr_123",
    "messages": [
      {
        "id": "msg_1",
        "role": "user",
        "content": "What is my PnL?",
        "createdAt": "2024-01-01T00:00:00.000Z"
      },
      {
        "id": "msg_2",
        "role": "assistant",
        "content": "Your realized PnL is 42.3 SOL.",
        "createdAt": "2024-01-01T00:00:05.000Z"
      }
    ],
    "updatedAt": "2024-01-01T00:00:05.000Z"
  }
}
9

Send Message

Append a new message to an existing conversation. Only the conversationId and the message payload (role, content) are required; the response echoes the stored message.

  • Method: POST

  • Path: /api/v1/messages

  • Body:

{
  "conversationId": "65f...",
  "message": {
    "role": "user",
    "content": "What is my PnL?"
  }
}
  • Response:

{
  "conversationId": "65f...",
  "message": {
    "id": "msg_3",
    "role": "user",
    "content": "What is my PnL?",
    "createdAt": "2024-01-01T00:00:10.000Z"
  }
}

Last updated