API reference
The REST API behind Norr's MCP tools. Every /v1 route needs the vault's agent token as Authorization: Bearer <token>; a token is scoped to one vault and no route can withdraw, change rules or choose a destination. The MCP endpoint (/mcp on the MCP host) exposes the same operations as tools. /health, /attestation and /info are public.
The machine-readable spec is openapi.json (OpenAPI 3.1.0); this page is generated from it.
Servers
https://api.norr.finance: Hosted service. TLS terminates inside the attested CVM (check the certificate with scripts/verify-domain.mts). Runs on demand during the pilot.https://85e1d6a557dae81985c9e30e28270f91bee5c0e9-8787.dstack-pha-prod5.phala.network: The same CVM through Phala's gateway.http://localhost:8787: Local mock mode (pnpm dev:mock): fixed prices, no funds.
Authentication
Send the vault's agent token on every /v1 request: Authorization: Bearer <agent token>. Create one in the dashboard (Connect). A token works for one vault only.
Assets
What can be traded, and what is known about it.
GET /v1/assets
List tradable assets. Crypto by symbol and chain; tokenized stocks and ETFs by ticker, with every issuer that offers it and the smallest order that has been quoting. MCP tool: list_assets.
| Query parameter | Type | |
|---|---|---|
class |
crypto, equity |
Only crypto, or only tokenized stocks and ETFs. |
Response 200 (AssetList):
| Field | Type | |
|---|---|---|
crypto |
object[] | |
equities |
object[] | |
equityNotice |
string | |
equityMinimumNote |
string | |
notice |
string |
Other responses: 400, 401.
GET /v1/assets/check
Risk or eligibility verdict for one asset. Crypto: Scam Shield's risk level with reasons. Stocks: whether this vault may trade them, and the notice. Also any active NEAR Intents security incident touching the asset. MCP tool: check_asset.
| Query parameter | Type | |
|---|---|---|
asset |
string | required. A symbol (SOL), a ticker (NVDA: routed to the best-priced issuer) or a NEAR Intents asset id. |
Response 200 (AssetCheck):
| Field | Type | |
|---|---|---|
found |
boolean | required |
message |
string | |
class |
crypto, equity |
|
ticker |
string | |
versions |
object[] | |
eligible |
boolean | |
notice |
string |
Other responses: 400, 401.
GET /v1/market
Market data for one asset. Listed price and, for crypto, the read-only signals Scam Shield scores (liquidity, market cap, age) with its risk level. For stocks: price per issuer and the quoting minimum. Facts, not advice. MCP tool: get_market_data.
| Query parameter | Type | |
|---|---|---|
asset |
string | required. A symbol (SOL), a ticker (NVDA: routed to the best-priced issuer) or a NEAR Intents asset id. |
Response 200 (MarketData):
| Field | Type | |
|---|---|---|
found |
boolean | required |
message |
string | |
class |
crypto, equity |
|
ticker |
string | |
source |
string | |
versions |
object[] |
Other responses: 400, 401.
Trading
Price a trade (dry run) or request one.
POST /v1/quote
Price a trade without trading. Dry run: no funds move. Runs the same checks as a trade, so a trade that would be blocked returns the same blocked decision. MCP tool: get_quote.
Request body (TradeInput):
| Field | Type | |
|---|---|---|
side |
buy, sell |
required |
asset |
string | required |
amountUsd |
number | required |
reason |
string | The agent's reasoning, sealed to the owner's key; the service cannot read it back. |
Response 200 (Quote or Blocked):
One of: Quote
One of: Blocked
Other responses: 400, 401.
POST /v1/trade
Request a trade. Checks the rules and the asset's risk, quotes, executes through NEAR Intents (in the confidential layer when the vault's funds are there), and verifies the result. Funds always stay in the vault. A blocked answer names the rule; adjust the request instead of resending it. MCP tool: trade.
Request body (TradeInput):
| Field | Type | |
|---|---|---|
side |
buy, sell |
required |
asset |
string | required |
amountUsd |
number | required |
reason |
string | The agent's reasoning, sealed to the owner's key; the service cannot read it back. |
Response 200 (Decision):
One of: Executed
One of: Blocked
One of: PendingApproval
One of: Failed
Other responses: 400, 401.
Vault
Holdings, rules, results and history.
GET /v1/portfolio
Holdings in USD. Every holding with its layer (public or confidential), valued in USD, and the split between crypto and tokenized stocks. MCP tool: get_portfolio.
Response 200 (Portfolio):
| Field | Type | |
|---|---|---|
holdings |
object[] | required |
totalUsd |
number | required |
byClass |
object | required |
Other responses: 401, 503.
GET /v1/policy
The rules the agent must stay within. Planning view of the vault's rules, including what is left of today's spending cap. MCP tool: get_policy.
Response 200 (PolicyView):
| Field | Type | |
|---|---|---|
maxTradeUsd |
number | required |
dailySpendCapUsd |
number | required |
spentTodayUsd |
number | required |
spendRemainingTodayUsd |
number | required |
dailyLossCapUsd |
number | required |
maxEquityPct |
number | required |
allowedCrypto |
"any_safe" or string[] | required |
allowedEquities |
string[] | required |
cooldownSec |
number | required |
allowMediumRisk |
boolean | required |
equitiesEnabled |
boolean | required |
privacy |
public, prefer, require |
required |
paused |
boolean | required |
Other responses: 401.
GET /v1/pnl
Profit and loss since the first trade. Per asset and in total: realized (sells at average cost) and unrealized (what is still held from Norr's buys, at today's listed price). Deposits have no known cost and are not counted. MCP tool: get_pnl.
Response 200 (Pnl):
| Field | Type | |
|---|---|---|
since |
string or null | required |
sinceMs |
number or null | |
scope |
string | required |
assets |
object[] | required |
totals |
object | required |
unpriced |
string[] | required |
Other responses: 401.
GET /v1/activity
Recent requests and outcomes. The last 20 trade requests, newest first. Swaps waiting for the owner's approval are settled here once approved. MCP tool: get_activity.
Response 200 (Activity):
| Field | Type | |
|---|---|---|
activity |
object[] | required |
Other responses: 401.
Public
Health and attestation; no token.
GET /health
Is the service up.
No token needed.
Response 200 (object):
| Field | Type | |
|---|---|---|
ok |
boolean | required |
mock |
boolean | required |
pricing |
ready, retrying |
required |
mockOwner |
string | Mock mode only. |
GET /attestation
A fresh TDX quote bound to your nonce. The quote's report data is your nonce, padded with zeros. Check it with the dashboard's Verify screen or scripts/verify-attestation.mts.
No token needed.
| Query parameter | Type | |
|---|---|---|
nonce |
string | required. 1 to 64 bytes of hex. |
Response 200 (object):
| Field | Type | |
|---|---|---|
attested |
true | required |
nonce |
string | required |
quote |
string | required. Hex TDX quote. |
eventLog |
||
commit |
string or null |
Other responses: 400, 429, 503.
GET /info
The measured app configuration.
No token needed.
Response 200 (object):
| Field | Type | |
|---|---|---|
attested |
true | required |
appId |
string | |
composeHash |
string | |
appCompose |
string | |
commit |
string or null |
Other responses: 503.
Decisions
What POST /v1/trade answers (Decision), by status:
Executed
| Field | Type | |
|---|---|---|
status |
"executed" | required |
txRef |
string | required |
filled |
object | required |
venue |
public, confidential |
|
verification |
independent, custody-reported |
|
warnings |
string[] |
Blocked
| Field | Type | |
|---|---|---|
status |
"blocked" | required |
code |
BlockCode | required |
message |
string | required |
suggestedUsd |
number |
PendingApproval
| Field | Type | |
|---|---|---|
status |
"pending_approval" | required |
requestId |
string | required |
message |
string | required |
Failed
| Field | Type | |
|---|---|---|
status |
failed, refunded |
required |
message |
string | required |
Block codes and what they mean: MCP tools.