Docs · updated 2 Nov 2026
The strategy contract
Your bot keeps its strategy. It sends Nevarn intents - the terms it would like traded - never orders and never keys. Nevarn asks Decionis whether each intent is allowed and records the answer. A key with intents gets shadow mode: every intent is ruled and recorded, and nothing is sent to a venue. A key an owner gives execute has its intents executed under Decionis policy, within the limits set on the key: on paper in Sandbox, live in Production.
Shadow mode for API keys is switched on per deployment. If reading your bounds shows "available": false, it is not on for yours yet; write to support@nevarn.com.
Executions go where your account is: on paper in Sandbox, live in Production. Accounts start in Sandbox; an owner switches the account to Production in the console.
Who does what
| Step | Who | Shadow (intents) | Sandbox (execute) | Production (execute) |
|---|---|---|---|---|
| Decide what to trade | Your bot | Yes | Yes | Yes |
| Send an intent: terms only | Your bot | POST /machine/intents | POST /machine/executions | POST /machine/executions |
| Check the terms, the key's limits, halts and replays | Nevarn | Terms only | Yes | Yes |
| Rule on the intent | Decionis, asked by Nevarn | In shadow mode | In shadow mode | In enforcement, right before the venue |
| Turn the ruling into an order, sign, submit | Nevarn | Never | A paper fill at your terms | Yes, with your own venue credentials |
| Book it and issue a receipt | Nevarn | Never | Never | Yes |
The policies, the rulings and their proofs belong to Decionis. Nevarn forwards the intent, records the answer and enforces it; it does not author policies. Executing intents from your own bot takes a key with execute, which an owner grants by name with its limits.
Keys and scopes
Every call carries an API key: Authorization: Bearer nvk_…. An owner or admin mints keys in the console; the secret is shown once and kept only as a hash. A key belongs to one account and does only what its scopes say.
| Scope | Lets the key | Route |
|---|---|---|
| intents | Propose intents for a shadow ruling | POST /machine/intents |
| execute | Have intents executed within the key's limits: on paper in Sandbox, live in Production | POST /machine/executions, GET /machine/executions/{id} |
| read | Read your bounds and your execution receipts | GET /machine/mandate, GET /machine/receipts/{id} |
| halt | Turn all of your signing off | POST /machine/halt |
| invoices | File supplier invoices | POST /machine/invoices |
| facilitator | Verify and settle machine payments | POST /machine/verify, /machine/settle |
No scope can resume signing, change a limit, mint a key, add a supplier or approve anything: those take a signed-in owner.
execute is never part of the console's For a bot preset. An owner ticks it by name and sets the key's limits - orders a minute, the largest order and a 24-hour total, in USDC - which stay fixed for the key's life; to change them, mint a new key. Your account's own largest-order limit, signing grants and kill switch apply on top.
POST /machine/intents
{
"strategy": "polymarket",
"intent_key": "momentum-1",
"intent": {
"token_id": "<outcome token id>",
"side": "BUY",
"maker_amount": 5000000,
"taker_amount": 10000000,
"observed_at": "2026-11-01T12:00:00Z"
}
}- strategy: polymarket, sports, capital or arbitrage.
- intent_key: your idempotency key, 1-160 characters of letters, digits and _ . : -. The same key with the same terms returns the first ruling (200) and is not asked again, so retrying after a timeout is safe. The same key with other terms is refused (409).
- intent: the terms, in the exact shape the strategy's runtime adapter accepts. Any other field is refused, so there is nowhere to put a key, a signature, calldata or a URL.
- observed_at: when your bot saw the price, with a timezone. No older than the strategy's max_intent_age_seconds (60 unless your bounds say otherwise), and not in the future.
| Strategy | Required terms | Optional |
|---|---|---|
| polymarket, sports | token_id (decimal string), side (BUY or SELL), maker_amount and taker_amount (integers, 6-decimal units), observed_at | neg_risk; order_type FOK (default) or GTD for an expiring post-only BUY with expiration and post_only; producer_evidence |
| capital | epic, side, quantity, limit_price, stop_level (decimal strings), observed_at | take_profit, producer_evidence |
| arbitrage | asset (token contract), amount, min_intermediate, min_return, builder_bribe_bps, entry_kind, entry_fee, exit_kind, exit_fee, observed_at | producer_evidence |
producer_evidence lets your bot state facts a policy can use - drawdown, kernel state, strategy mode - and must name your own account.
The ruling
{
"id": "…",
"intent_key": "momentum-1",
"strategy": "polymarket",
"mode": "shadow",
"verdict": "block",
"would_execute": false,
"executed": false,
"reasons": ["…"],
"decision_id": "…",
"rulings": [{ "pack_id": "…", "version": "…", "verdict": "block", "reasons": ["…"] }],
"receipt_id": null,
"created_at": "2026-11-01T12:00:01Z"
}| verdict | Meaning | would_execute |
|---|---|---|
| execute | Every policy bound to the strategy would allow it | true |
| block | A policy would refuse it | false |
| escalate | A policy would send it to a person | false |
| do_nothing | A policy would hold it | false |
| unavailable | No ruling could be had; read it as not allowed | false |
Nevarn asks each policy bound to the strategy in turn and stops at the first that would not execute. unavailable carries its reason: policy_not_published (no policy is bound to the strategy yet), policy_mapping_unpublished, authority_not_configured, or a transport reason. executed is always false in shadow mode and receipt_id always null.
A shadow allow is not a promise. In shadow mode the ruling sees the intent as your bot sent it. When execution comes, Nevarn's runtime adapter adds live venue evidence and asks again in enforcement just before it signs, and your limits, signing grants and the kill switch still apply.
What Decionis sees: the order terms exactly (a policy that bounds size has to see the size), your account as a keyed stand-in rather than its id, addresses as stand-ins, and the observation time as an age.
POST /machine/executions
The same body as POST /machine/intents, so your bot moves from shadow to execution by changing the route. polymarket and sports intents can be executed: their terms state the order's size in USDC, which the key's limits count. capital and arbitrage are refused with strategy_not_executable for now.
- Before anything is ruled, filled or queued, Nevarn checks the terms, the intent key, the key's limits, that your signing is not halted, your account's largest-order limit, the observation's age, in Production that the key was minted from a wallet sign-in, and that these exact terms were not executed before.
- Sandbox: your strategy's policies and the Runtime adapters policy are asked in shadow mode, and the order is filled on paper - in full, at the terms you stated. would_execute says whether Production would have placed it. Nothing reaches a venue.
- Production: the order is queued under your key's identity. Right before it is sent, Decionis rules on it in enforcement under your strategy's policies and the Runtime adapters policy, and each ruling's single-use grant is claimed. Anything but a claimed allow blocks it with a reason and nothing is sent. It goes out with your own venue credentials, and the strategy must be started in your console.
- The same intent_key and terms return the first execution (200). Read it back, with its current state, at GET /machine/executions/{id}.
{
"id": "…",
"intent_key": "momentum-2",
"strategy": "polymarket",
"mode": "execute",
"environment": "sandbox",
"state": "paper_filled",
"verdict": "execute",
"would_execute": true,
"executed": false,
"notional_minor": 5000000,
"paper": { "venue": "paper", "status": "filled", "price": "0.500000" },
"execution_id": null,
"receipt_id": null
}In Production environment is production and state is the order's: queued at first, then prepared, sending, submitted and confirmed, or blocked with a reason. executed turns true once the venue has the order, and receipt_id is set once it is confirmed.
GET /machine/mandate
Read-only: your limits (including trading_enabled, the kill switch), your signing grants (never key material), your supplier-payment policy, under intents whether shadow mode is available and, per strategy, max_intent_age_seconds and the Decionis policy references that rule its intents, under executions your account's environment and the reading key's own limits, and under governed_actions how many actions the key and your account put under Decionis this month.
POST /machine/halt
Turns all of your account's signing off at once, and stops every execution your bots asked for that has not been sent: it is refused at its next step, even after an owner resumes signing. The body is {} or {"reason": "…"} (500 characters at most); any other field is refused. Halting twice is harmless. There is no resume call: only an owner can turn signing back on, from the console.
Receipts
Every executed trade has one receipt linking the Decionis ruling to the order, the fill transaction, settlement, the ledger entries and the balance after, each with its status. GET /machine/receipts/{id} with a read key returns one, by the execution's id. Shadow intents never execute, so they never have a receipt, and neither does a paper fill in Sandbox.
Limits and errors
| Status | Meaning |
|---|---|
| 401 | No key, an unknown key, or a revoked key |
| 403 | The key lacks the scope |
| 409 | An intent_key reused for other terms, or shadow mode is off for this deployment. For an execution, error.code names the refusal: key_order_limit_exceeded, key_daily_limit_exceeded, tenant_order_limit_exceeded, tenant_halted, intent_replayed, intent_key_reused, key_minted_without_wallet, strategy_not_executable, policy_not_published, policy_mapping_unpublished, runtime_adapter_unpinned or authority_not_configured. Nothing was sent. |
| 422 | Terms outside the strategy's shape, a stale or future observed_at, or evidence for another account |
| 429 | Over the rate limit: per key, 60 a minute for intents, executions, bounds and receipts, 120 for reading an execution, 10 for halt, and an execute key's own orders a minute (key_rate_limit_exceeded). Retry-After says when. |
The weekly summary
Each week Nevarn counts your bot's rulings: how many were checked, how many would have been stopped and why, and how often no ruling could be had. The console shows it beside your latest rulings.