weltiq
한국어 Log in Start free

WELTIQ / DOCS / QUICK STARTS

Quick starts — MCP, REST API, TradingView

Three complete walkthroughs to a first paper order: Claude or Codex over MCP, your own code over the REST API, and a TradingView alert hook — with the real endpoints and field names.

Three complete paths to a first paper order. Every path needs a free account; the trading limits are always approved by you in the browser, never by a key, an agent or a script.

Claude · Codex · MCP

MCP: API key → scope → approve limits → first order → check the fill

  1. Issue an API key — Sign up at weltiq.ai/login (email or Google), then open My → Connections → API keys (/connections). Choose a label and scopes and issue the key. The wq_… secret is shown once — store it as WELTIQ_API_KEY.
  2. Pick the scopes — read-data reads markets, account, fills and journal; operate-sim places paper orders and runs resident slots; run-backtest runs backtests. For a trading agent issue read-data + operate-sim. The analyst server (https://weltiq.ai/mcp/analyst) accepts read-data-only keys.
  3. Approve order limits in the browser — Open My → Connections and use the Order limits section (/connections#envelope): symbols (e.g. BTCUSDT), max notional per order, max notional per day, validity in days. Keys and MCP cannot create or widen limits — they get 403. Without an approved limit the first order is rejected with envelope_required.
  4. Connect the MCP server — Claude Code: one command. Claude Desktop or any client that speaks streamable HTTP MCP (Codex included): add the server URL with the Authorization header to the client's MCP config. The trading server exposes order_oneoff, oneoff_orders, fills, account, slots and more; the analyst server has no order tools.
    claude mcp add --transport http weltiq https://weltiq.ai/mcp --header "Authorization: Bearer $WELTIQ_API_KEY"
    
    {"mcpServers": {"weltiq": {"url": "https://weltiq.ai/mcp", "headers": {"Authorization": "Bearer wq_..."}}}}
  5. Place the first order — Ask: "Buy 0.001 BTCUSDT at market on binance-spot. Thesis: the 4-hour support holds; I am wrong below 60000." The agent calls order_oneoff(venue="binance-spot", symbol="BTCUSDT", side="buy", qty="0.001", thesis_why=…, px_below="60000"). thesis_why is mandatory; opening a position also needs px_below and/or px_above (the engine closes the position when a level is hit). MCP adds client_ts for you. The same call over REST is POST /v1/orders/oneoff.
    curl -sS -X POST https://weltiq.ai/v1/orders/oneoff -H "Authorization: Bearer $WELTIQ_API_KEY" -H "Content-Type: application/json" \
      -d '{"venue":"binance-spot","symbol":"BTCUSDT","side":"buy","type":"market","qty":"0.001",
           "thesis":{"why":"4h support holds"},"invalidation":{"px_below":"60000"},
           "client_ts":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"}'
    # {"queue_id":"dq_…","status":"queued","est_notional":"…","closing":false,"target":"paper"}
    curl -sS https://weltiq.ai/v1/orders/oneoff -H "Authorization: Bearer $WELTIQ_API_KEY"   # queued → filled | rejected (result.code)
  6. Check the fill or the rejection — Ask "did it fill?" — the agent calls oneoff_orders: status queued → filled (result.fills: qty, px, fee) or rejected with result.code. Typical codes: thesis_required, invalidation_required, envelope_required, order_notional_exceeded, daily_notional_exceeded, no_price, spot_short_not_allowed. Then fills(mode="paper") and account for the ledger. A sell against the open position is a close (reduce-only, no levels needed).

Korean manual section →

REST API · your own code

REST API: connection approval → curl or Python order → status

  1. Approve a connection in the browser — My → Connections (/connections) → New connection: one Binance spot USDT symbol (e.g. BTCUSDT), virtual capital, max_order_notional and max_daily_notional in USDT, stop_loss_pct, allowed rule_ids (default buy: entry, sell: exit), a strategy description of 10+ characters, validity in days, optionally fee_venue. Approve & create. Copy the connection_id (pc_…). This screen is the only place limits are set — POST /v1/paper/connections needs a browser session, not a key.
  2. Send the order with curl — Body fields: schema_version 1, event_id (unique inside the connection), sequence (positive integer, strictly increasing), emitted_at (UTC ISO 8601, must arrive within 60 s), action buy or sell, qty as a string Decimal aligned to the lot size, rule_id from the allowed list. Any other field (target, live, cred_id, user_id) is rejected with 422. 202 means accepted, not filled.
    curl -sS -X POST "https://weltiq.ai/v1/paper/connections/$CID/orders" \
      -H "Authorization: Bearer $WELTIQ_API_KEY" -H "Content-Type: application/json" \
      -d '{"schema_version":1,"event_id":"bot-1","sequence":1,"emitted_at":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","action":"buy","qty":"0.001","rule_id":"entry"}'
    # 202 {"status":"queued","event_id":"bot-1","order_id":"dq_…","exec_mode":"delayed","status_url":"/v1/paper/connections/pc_…/orders/bot-1"}
  3. Or from Python — Use the API key with the Authorization header and keep sequence monotonic across restarts (a millisecond timestamp works). Re-sending the same body returns 200 with duplicate: true; the same event_id with a different body returns 409 idempotency_conflict.
    import os, time, datetime, httpx
    BASE, CID = "https://weltiq.ai", os.environ["WELTIQ_CID"]
    H = {"Authorization": "Bearer " + os.environ["WELTIQ_API_KEY"]}
    seq = int(time.time() * 1000)                      # strictly increasing sequence
    body = {"schema_version": 1, "event_id": f"bot-{seq}", "sequence": seq,
            "emitted_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
            "action": "buy", "qty": "0.001", "rule_id": "entry"}
    r = httpx.post(f"{BASE}/v1/paper/connections/{CID}/orders", json=body, headers=H, timeout=10)
    print(r.status_code, r.json())                    # 202 queued — accepted, not filled
    st = httpx.get(BASE + r.json()["status_url"], headers=H).json()
    print(st["status"], st.get("filled_qty"), st.get("fill_vwap"), st.get("protection"))
  4. Read the status — GET /v1/paper/connections/{cid}/orders/{event_id}: status queued → submitted → filled (or partial, rejected, expired, canceled), filled_qty, fill_vwap, fills [{qty, px, fee}], and protection — the stop derived from the fill VWAP and stop_loss_pct. GET …/orders lists recent orders plus events rejected at admission; GET …/fills lists fills of the connection's own paper book.
    curl -sS "https://weltiq.ai/v1/paper/connections/$CID/orders/bot-1" -H "Authorization: Bearer $WELTIQ_API_KEY"
    # {"event_id":"bot-1","status":"filled","filled_qty":"0.001","fill_vwap":"…","fills":[{"qty":"0.001","px":"…","fee":"…"}],"protection":{…}}
    curl -sS "https://weltiq.ai/v1/paper/connections/$CID/fills" -H "Authorization: Bearer $WELTIQ_API_KEY"
  5. Rejections you will meet — 422 invalid_payload (field format), event_expired (emitted_at older than 60 s), future_event, rule_not_allowed, insufficient_position (sell larger than held), connection_inactive; 409 position_exists (buy while a long is open or queued) and out_of_order (sequence not increasing); 429 rate_limited (60 per minute, 2,000 per day per connection); 404 or 410 unknown or revoked connection. buy opens one long per connection; sell only reduces it.
  6. Cancel or close — DELETE /v1/paper/connections/{cid}/orders/{event_id} cancels an order the engine has not claimed yet (409 not_cancelable afterwards). A filled position is reduced with a sell order, or from the connection screen in the browser.

Korean manual section →

TradingView · alert hook

TradingView: hook URL → alert() JSON → fill

  1. Create the connection and copy the hook URL — Same connection screen as the REST path (My → Connections → New connection). Right after Approve & create the hook URL https://weltiq.ai/hooks/tv-orders/<token> is shown once — copy it. If you lose it, revoke the connection and create a new one. One connection is free; Pro has three.
  2. Build the order JSON in Pine with alert() — TradingView placeholders cannot produce an increasing integer sequence or a unique event_id, so the script builds the body. Use bar_index for both, str.format_time for emitted_at in UTC, and the rule_ids you allowed on the connection.
    //@version=5
    strategy("weltiq hook", overlay=true)
    fast = ta.sma(close, 20), slow = ta.sma(close, 50)
    msg(action, rule) => '{"schema_version":1,"event_id":"tv-' + str.tostring(bar_index) + '-' + action +
         '","sequence":' + str.tostring(bar_index) + ',"emitted_at":"' + str.format_time(timenow, "yyyy-MM-dd'T'HH:mm:ss'Z'", "UTC") +
         '","action":"' + action + '","qty":"0.001","rule_id":"' + rule + '"}'
    if ta.crossover(fast, slow)
        alert(msg("buy", "entry"), alert.freq_once_per_bar_close)
    if ta.crossunder(fast, slow)
        alert(msg("sell", "exit"), alert.freq_once_per_bar_close)
  3. Create the alert — Add the strategy to the chart → Create alert → condition "alert() function calls only", Webhook URL = the hook URL from step 1, leave the message box empty (the alert() text is sent as is), expiration none, 2FA on. TradingView sends webhooks on its paid plans only.
  4. Watch the first fill — Open the connection in My → Connections: the event appears as queued, then filled with fill price, fee and the protection stop, or rejected with a code. The same data is at GET /v1/paper/connections/{cid}/orders/{event_id} and in the MCP tool paper_order_status. Free plan: filled on the first closed 1-minute bar after emitted_at; Pro: on the live quote.
  5. When nothing arrives — 404 or 410: wrong or revoked token. 422 event_expired: emitted_at is more than 60 s old — check the alert frequency. 409 position_exists: a long is already open or queued on this connection. 200 duplicate: the same alert was delivered twice and was ignored. TradingView does not guarantee delivery; compare its alert log with the connection's order list.

Korean manual section →

Free plan: orders fill on the first closed 1-minute bar after the order time (exec_mode "delayed"), so allow one to two minutes. Pro fills on the live quote. Markets: crypto spot for external connections; crypto spot and perpetuals for direct orders.

Your first experiment starts with one order.

Check availability, then choose how you want to connect.

Open external order connectionsGetting started →