# Vurto AI API Guide

This document is the machine-operator guide for AI agents (Clawbot/OpenClaw style) to execute Vurto actions directly via API.

## 1. Base URLs

- Production: `https://ana.vurto.cc/api/v1`
- OpenAPI Spec: `https://ana.vurto.cc/api/v1/openapi.json`

Health check:

```bash
curl -sS https://ana.vurto.cc/api/v1/health
```

Public call template (no API key required):

```bash
curl -sS https://ana.vurto.cc/api/v1/donator-status \
  -H 'content-type: application/json' \
  --data '{"walletAddress":"0x1111111111111111111111111111111111111111","chainId":137}'
```

## 2. Agent Contract (Clawbot/OpenClaw Friendly)

For each command, the agent should always keep this contract:

1. Validate intent + required params.
2. Resolve donor status (`/donator-status`) before quote/build.
3. Quote first if command requires swap math (`/quote/*`).
4. Build tx payload (`/build/*`) and inspect `to`, `data`, `value`, `feeBps`, `feeAmount`.
5. Sign and send onchain.
6. Report status to tracking endpoint (`/transactions/:id/*`) when `transactionId` exists.
7. Return final result with tx hash, chain, token amounts, and effective fee.

## 3. Common Rules

- All token amounts are integer strings in raw units (wei-like, token decimals).
- Token object shape:

```json
{
  "address": "0x...",
  "decimals": 6,
  "symbol": "USDC"
}
```

- Minimum shared fields in most calls:
  - `chainId`
  - `walletAddress`
  - `userAddress` (required for quote/build swap routes)
- Pool routes require `poolAddress`.
- Default interest mode for borrow/repay: variable (`2`).
- Public routes (no credential): `GET /health` and docs/root guide.
- Sensitive routes are also public on `ana.vurto.cc` and `ana.vurto.cc`:
  - `POST /donator-status`
  - `POST /quote/*`
  - `POST /build/*`
- Anti-flood rate limits are layered by IP + credential + wallet + route + method.
- On limit hit, API returns `429` with headers:
  - `retry-after`
  - `x-ratelimit-limit`
  - `x-ratelimit-remaining`
  - `x-ratelimit-reset`
  - `x-ratelimit-scope`
- Extra telemetry header: `x-ratelimit-source` (`edge`, `edge_local`, or `local`).
- Agent behavior on `429`: wait `retry-after` seconds and retry with backoff; avoid parallel bursts.
- OpenAPI contract guard is active on sensitive routes: unknown/missing fields are rejected.
- Kill-switch can temporarily disable specific routes and returns `503 api_route_disabled`.

## 3.1 APY History (Self-Collected + DeFi Llama)

Vurto independently collects supply and borrow APY rates every 12 hours (00:00 and 12:00 UTC). This self-collected data is combined with DeFi Llama where available, and over time will provide full 365-day coverage without external dependencies.

Endpoints:

- `GET /apy/history?chainId=<id>` — current rates (supply + borrow) from DeFi Llama bulk
- `GET /apy/history/rolling?chainId=<id>&days=365` — rolling averages from self-collected + DeFi Llama charts

Recommended query for agents:

```bash
curl -sS "https://ana.vurto.cc/api/v1/apy/history/rolling?chainId=42161&days=365"
```

How to read the response:

- `source`: data source mode — `vurto_collected`, `defillama+vurto_collected`, or `defillama+rolling_chart`
- `coverageDays`: max coverage across supply and borrow for that token
- `supplyCoverageDays`: days of supply APY history available
- `borrowCoverageDays`: days of borrow APY history available (from self-collection)
- `supply.avg30d|avg90d|avg180d|avg365d` — supply APY rolling averages
- `borrow.avg30d|avg90d|avg180d|avg365d` — borrow APY rolling averages
- `collection.collectedDays`: number of unique daily snapshots Vurto has recorded
- `collection.notice`: human-readable status of the collection progress

Important rules for agents:

- Consider `30d/90d/180d/365d` values valid only when `coverageDays >= window` (or the specific `supplyCoverageDays`/`borrowCoverageDays`).
- If coverage is insufficient, treat that window as unavailable (`N/A`) instead of extrapolating.
- Prefer token lookup by underlying address; use `symbol:<SYMBOL>` alias only as fallback.
- Rolling endpoint is capped at `days=365`.
- Use `collection.collectedDays` to know how mature the borrow average data is.

Background collection:

- APY snapshots (both supply and borrow current rates) are persisted in Vurto KV every 12 hours.
- Borrow averages grow daily as more snapshots accumulate — goal is full 365-day independence within one year.

## Support Error Reporting for AI Agents

- Purpose: allow agents to report runtime issues and retrieve aggregated incident context for debugging loops.
- Write endpoint (public intake): `POST /support/tickets`
- Read endpoints (private): `GET /support/tickets`, `GET /support/tickets/:id`, `GET /support/analysis`
- Privacy rule: support reads require valid credential; unauthenticated reads return `401 support_read_auth_required`.

Recommended agent flow:

1. On execution failure, call `POST /support/tickets` with `message`, optional `contactEmail`, and optional `screenshotDataUrl`.
2. For triage sessions, call `GET /support/analysis` (with credential) to cluster recurring signatures.
3. If needed, fetch detailed incidents via `GET /support/tickets` and `GET /support/tickets/:id`.

## 4. Fee and Donor Policy

- Base fee: `2.5 bps` = `0.025%`.
- If wallet is verified donor: fee = `0`.
- Verify donor:

```bash
curl -sS https://ana.vurto.cc/api/v1/donator-status \
  -H 'content-type: application/json' \
  --data '{
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "chainId":137
  }'
```

Expected key fields:

- `donator.isDonator`
- `donator.discountPercent`
- `donator.validUntil`
- `donatorPolicy.minimumDonationUsd`
- `donatorPolicy.walletAddressByChain`

### Important: How to Donate Correctly

To register donor status onchain, donation must use contract method `donate` (or `donateFor`).

- Correct: call `donate(token, amount)` on donation registry contract for that network.
- Not enough: direct ERC20 transfer to the contract (this does not update donor state in registry logic).

Donation ABI methods:

- `donate(address token, uint256 amount)`
- `donateFor(address beneficiary, address token, uint256 amount)`
- `isDonorNow(address account)`

Network note:

- Registry contract can differ by chain. Use `GET /dapp-vurto/config` and read:
  - `donationPolicy.walletAddressByChain`
  - `donationPolicy.acceptedTokensByNetwork`

### Donor Tier Matrix (Current Policy)

Current configured tiers in backend policy:

| Tier | Minimum donation (USD) | Donor validity |
|---|---:|---:|
| 1 | 0.99 | 30 days |
| 2 | 1.95 | 60 days |
| 3 | 5.00 | 180 days |
| 4 | 10.00 | 365 days |

Important behavior:

- Base platform fee is `0.025%` (2.5 bps).
- Verified donor gets `100%` discount on platform fee (effective fee `0`).
- A qualifying donation sets/extends donor validity (`donator.validUntil`) according to its tier.
- Higher qualifying donation tiers can increase validity window.
- Confirm active state from API fields: `donator.isDonator`, `donator.validUntil`, `donator.activeTierMinUsd`, `donator.activeTierValidityDays`.

After onchain donation confirmation, refresh donor state:

```bash
curl -sS https://ana.vurto.cc/api/v1/donator-status \
  -H 'content-type: application/json' \
  --data '{
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "chainId":137,
    "force":true
  }'
```

## 5. Command Index

**Same-chain operations** (single transaction on one chain):

1. `supply_collateral` — deposit token as collateral
2. `supply_collateral_zap_in` — swap token A → supply token B as collateral
3. `borrow` — borrow token against collateral
4. `withdraw_supplied` — withdraw collateral
5. `withdraw_supplied_zap_out` — withdraw collateral → swap to another token
6. `switch_supplied` — swap supplied collateral to a different token
7. `repay_borrowed` — repay debt with the same token
8. `switch_borrowed` — swap debt to a different token (repay-with-swap)
9. `dual_swap` — switch both collateral AND debt in one transaction

**Crosschain operations** (non-atomic, multi-step across two chains via bridge):

10. `crosschain_supply` — withdraw from chain A → bridge → supply on chain B
11. `crosschain_repay` — borrow on chain A → bridge → repay debt on chain B
12. `position_migration` — alternate crosschain supply + crosschain repay cycles to move an entire position from chain A to chain B

---

## 6. Commands and Examples

### 6.1 Supply de collateral (`supply_collateral`)

Endpoint:

- `POST /build/supply`

Example:

```bash
curl -sS https://ana.vurto.cc/api/v1/build/supply \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "poolAddress":"0x794a61358d6845594f94dc1db02a252b5b4814ad",
    "token":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "amount":"1000000"
  }'
```

### 6.2 Supply com zap in (`supply_collateral_zap_in`)

Flow:

1. `POST /quote/collateral`
2. `POST /build/collateral/paraswap` (swap)
3. `POST /build/supply` (deposit target token)

Quote:

```bash
curl -sS https://ana.vurto.cc/api/v1/quote/collateral \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "userAddress":"0x1111111111111111111111111111111111111111",
    "fromToken":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "toToken":{"address":"0xc2132d05d31c914a87c6611c10748aeb04b58e8f","decimals":6,"symbol":"USDT"},
    "srcAmount":"1000000"
  }'
```

Build swap (use `priceRoute` from quote):

```bash
curl -sS https://ana.vurto.cc/api/v1/build/collateral/paraswap \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "userAddress":"0x1111111111111111111111111111111111111111",
    "fromToken":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "toToken":{"address":"0xc2132d05d31c914a87c6611c10748aeb04b58e8f","decimals":6,"symbol":"USDT"},
    "srcAmount":"1000000",
    "slippageBps":3,
    "priceRoute": {"...":"from quote"}
  }'
```

Then build supply with target token amount (`destAmount` or conservative min output):

```bash
curl -sS https://ana.vurto.cc/api/v1/build/supply \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "poolAddress":"0x794a61358d6845594f94dc1db02a252b5b4814ad",
    "token":{"address":"0xc2132d05d31c914a87c6611c10748aeb04b58e8f","decimals":6,"symbol":"USDT"},
    "amount":"995000"
  }'
```

### 6.3 Borrow (`borrow`)

Endpoint:

- `POST /build/borrow`

```bash
curl -sS https://ana.vurto.cc/api/v1/build/borrow \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "poolAddress":"0x794a61358d6845594f94dc1db02a252b5b4814ad",
    "token":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "amount":"1000000",
    "interestRateMode":2
  }'
```

### 6.4 Withdrawn de supplied (`withdraw_supplied`)

Endpoint:

- `POST /build/withdraw`

```bash
curl -sS https://ana.vurto.cc/api/v1/build/withdraw \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "poolAddress":"0x794a61358d6845594f94dc1db02a252b5b4814ad",
    "token":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "amount":"1000000",
    "recipient":"0x1111111111111111111111111111111111111111"
  }'
```

For full balance where supported:

- add `"useMaxAmount": true`

### 6.5 Withdrawn de supplied com zap out (`withdraw_supplied_zap_out`)

Flow:

1. `POST /build/withdraw`
2. `POST /quote/collateral`
3. `POST /build/collateral/paraswap`

Withdraw build:

```bash
curl -sS https://ana.vurto.cc/api/v1/build/withdraw \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "poolAddress":"0x794a61358d6845594f94dc1db02a252b5b4814ad",
    "token":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "amount":"1000000",
    "recipient":"0x1111111111111111111111111111111111111111"
  }'
```

Then quote/build collateral swap from withdrawn token to desired token.

### 6.6 Switch de supplied (`switch_supplied`)

Flow:

1. `POST /quote/collateral`
2. `POST /build/collateral/paraswap`

```bash
curl -sS https://ana.vurto.cc/api/v1/quote/collateral \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "userAddress":"0x1111111111111111111111111111111111111111",
    "fromToken":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "toToken":{"address":"0xc2132d05d31c914a87c6611c10748aeb04b58e8f","decimals":6,"symbol":"USDT"},
    "srcAmount":"1000000"
  }'
```

### 6.7 Repay de borrowed (`repay_borrowed`)

Endpoint:

- `POST /build/repay`

```bash
curl -sS https://ana.vurto.cc/api/v1/build/repay \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "poolAddress":"0x794a61358d6845594f94dc1db02a252b5b4814ad",
    "token":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "amount":"1000000",
    "interestRateMode":2
  }'
```

### 6.8 Switch de borrowed (`switch_borrowed`)

Flow:

1. `POST /quote/debt`
2. `POST /build/debt/paraswap`

```bash
curl -sS https://ana.vurto.cc/api/v1/quote/debt \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "userAddress":"0x1111111111111111111111111111111111111111",
    "fromToken":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
    "toToken":{"address":"0xc2132d05d31c914a87c6611c10748aeb04b58e8f","decimals":6,"symbol":"USDT"},
    "destAmount":"1000000"
  }'
```

### 6.9 Dual swap (`dual_swap`)

Preferred flow:

1. `POST /quote/dual`
2. `POST /build/dual/aave-adapter`
3. Fallback: `POST /build/dual/executor` if adapter route is unavailable on chain.

Dual quote:

```bash
curl -sS https://ana.vurto.cc/api/v1/quote/dual \
  -H 'content-type: application/json' \
  --data '{
    "chainId":137,
    "walletAddress":"0x1111111111111111111111111111111111111111",
    "userAddress":"0x1111111111111111111111111111111111111111",
    "collateral":{
      "fromToken":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
      "toToken":{"address":"0xc2132d05d31c914a87c6611c10748aeb04b58e8f","decimals":6,"symbol":"USDT"},
      "srcAmount":"1000000"
    },
    "debt":{
      "fromToken":{"address":"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359","decimals":6,"symbol":"USDC"},
      "toToken":{"address":"0xc2132d05d31c914a87c6611c10748aeb04b58e8f","decimals":6,"symbol":"USDT"},
      "destAmount":"1000000"
    }
  }'
```

Dual build payload accepts backward-compatible quote-driven shape with `priceRoute` for both legs.

### 6.10 Crosschain Supply (`crosschain_supply`) — Non-Atomic

> **Do not confuse with same-chain operations.** `build_supply`, `build_borrow`, `build_withdraw`, and `build_repay` operate on a single chain. Crosschain Supply and Crosschain Repay are **multi-chain** operations that move funds between two different chains via a bridge.

**Crosschain Supply** withdraws collateral from the source chain, bridges it, and supplies it on the destination chain. Use `intent: "supply"` with `sourceFunding.mode: "withdraw"` (or `"withdraw_and_zap_out"` if the token is not bridge-compatible).

This is the fundamental building block for moving collateral from one chain to another.

Flow overview:

1. `POST /quote/longshot` — get crosschain route quote (auto-selects bridge provider: Across or USDT0)
2. `POST /build/longshot` — build multi-step execution with quoteId
3. Execute **source step**: sign and send the borrow/withdraw tx on source chain
4. Report: `POST /longshot/executions/:id/event` with `event: source_submitted` + `txHash`
5. Wait for source confirmation and report: `event: source_confirmed`
6. Execute **bridge step**: sign approve + deposit txs on source chain (if zap-out needed, also sign swap txs first; if non-donor, execute fee transfer before deposit)
7. Poll: `GET /longshot/executions/:id/bridge-check` until `bridged: true`
8. Execute **destination step**: sign and send supply tx on destination chain
9. Report: `event: destination_submitted` + `txHash`, then `event: destination_confirmed`

**Important rules for agents:**

- This is a **non-atomic** operation — each step is a separate onchain transaction.
- The execution may need **zap-out** (source token → bridge stable) and/or **zap-in** (bridge stable → destination token) if the tokens are not the same stablecoin family.
- The `projectedSourceHealthFactor` must be >= ~1.08 or the quote will be rejected.
- Quote expires in ~5 minutes from creation.
- If any step fails, use `POST /longshot/executions/:id/recover` with the appropriate action (`retry_source`, `retry_bridge`, `retry_destination`, or `mark_abandoned`).
- Bridge fee: non-donors pay 2.5 bps bridge fee transfer before the deposit. Donors pay 0.

Quote:

```bash
curl -sS https://ana.vurto.cc/api/v1/quote/longshot \
  -H 'content-type: application/json' \
  --data '{
    "walletAddress": "0x1111111111111111111111111111111111111111",
    "intent": "supply",
    "sourceChainId": 42161,
    "destinationChainId": 137,
    "sourceFunding": {
      "mode": "borrow",
      "token": {"address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831", "decimals": 6, "symbol": "USDC"},
      "amount": "1000000",
      "poolAddress": "0x794a61358d6845594f94dc1db02a252b5b4814ad",
      "projectedSourceHealthFactor": 1.5,
      "interestRateMode": 2
    },
    "destinationAction": {
      "token": {"address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359", "decimals": 6, "symbol": "USDC"},
      "amount": "990000",
      "poolAddress": "0x794a61358d6845594f94dc1db02a252b5b4814ad"
    },
    "slippageBps": 30
  }'
```

Build from quote:

```bash
curl -sS https://ana.vurto.cc/api/v1/build/longshot \
  -H 'content-type: application/json' \
  --data '{
    "quoteId": "lq_...",
    "walletAddress": "0x1111111111111111111111111111111111111111"
  }'
```

Response contains `executionId`, `steps` array (source, bridge, destination), `statusUrl`, and `recoverUrl`.

Report source tx submitted:

```bash
curl -sS https://ana.vurto.cc/api/v1/longshot/executions/lex_.../event \
  -H 'content-type: application/json' \
  --data '{
    "walletAddress": "0x1111111111111111111111111111111111111111",
    "event": "source_submitted",
    "txHash": "0xabc..."
  }'
```

Check bridge arrival:

```bash
curl -sS "https://ana.vurto.cc/api/v1/longshot/executions/lex_.../bridge-check?walletAddress=0x1111111111111111111111111111111111111111"
```

Poll until `bridged: true`, then execute destination tx and report `destination_submitted` → `destination_confirmed`.

Get execution status:

```bash
curl -sS "https://ana.vurto.cc/api/v1/longshot/executions/lex_.../status?walletAddress=0x1111111111111111111111111111111111111111"
```

Recover from failure:

```bash
curl -sS https://ana.vurto.cc/api/v1/longshot/executions/lex_.../recover \
  -H 'content-type: application/json' \
  --data '{
    "walletAddress": "0x1111111111111111111111111111111111111111",
    "action": "retry_source"
  }'
```

### 6.11 Crosschain Repay (`crosschain_repay`) — Non-Atomic

**Crosschain Repay** borrows on the source chain, bridges the funds, and repays debt on the destination chain. Use `intent: "repay"` with `sourceFunding.mode: "borrow"`.

This is the complement of Crosschain Supply — it allows paying down debt on one chain using borrowing capacity from another.

Same execution flow as Crosschain Supply (quote → build → source step → bridge → destination step).

Quote example:

```bash
curl -sS https://ana.vurto.cc/api/v1/quote/longshot \
  -H 'content-type: application/json' \
  --data '{
    "walletAddress": "0x1111111111111111111111111111111111111111",
    "intent": "repay",
    "sourceChainId": 42161,
    "destinationChainId": 137,
    "sourceFunding": {
      "mode": "withdraw",
      "token": {"address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831", "decimals": 6, "symbol": "USDC"},
      "amount": "2000000",
      "poolAddress": "0x794a61358d6845594f94dc1db02a252b5b4814ad",
      "projectedSourceHealthFactor": 2.0,
      "interestRateMode": 2
    },
    "destinationAction": {
      "token": {"address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359", "decimals": 6, "symbol": "USDC"},
      "amount": "1950000",
      "poolAddress": "0x794a61358d6845594f94dc1db02a252b5b4814ad",
      "interestRateMode": 2
    },
    "slippageBps": 30
  }'
```

### 6.12 Position Migration — Moving an Entire Position Between Chains

When a user has both collateral and debt on chain A and wants to move everything to chain B, use alternating **Crosschain Supply** and **Crosschain Repay** cycles:

1. **Crosschain Supply** — withdraw a safe portion of collateral from A → bridge → supply on B.
2. **Crosschain Repay** — borrow on B (now possible thanks to step 1 collateral) → bridge → repay debt on A. This restores chain A's health factor.
3. **Repeat** steps 1–2, each cycle moving more collateral and reducing more debt.
4. **Final step is always a Crosschain Supply** — once all debt on A is repaid, withdraw the remaining collateral from A and supply it on B.

**Key rules:**
- Call `GET /position` on both chains between cycles to recalculate safe withdrawal/borrow amounts and health factors.
- The `projectedSourceHealthFactor` must stay >= ~1.08 at every step.
- The number of cycles depends on the position's loan-to-value ratio — higher leverage requires more, smaller cycles.
- Each Crosschain Supply or Crosschain Repay is a full multi-step execution (source tx → bridge → destination tx) that must complete before starting the next.

### Crosschain Execution States

| State | Meaning |
|---|---|
| `awaiting_source_signature` | Waiting for agent to sign source tx |
| `source_submitted` | Source tx sent, awaiting confirmation |
| `source_confirmed` | Source tx confirmed onchain |
| `source_failed` | Source tx reverted — recoverable via `retry_source` |
| `bridge_pending` | Bridge deposit in progress |
| `bridge_confirmed` | Funds arrived on destination chain |
| `bridge_failed` | Bridge issue — recoverable via `retry_bridge` |
| `awaiting_destination_signature` | Waiting for agent to sign destination tx |
| `destination_submitted` | Destination tx sent |
| `destination_confirmed` | Destination tx confirmed — operation complete |
| `destination_failed` | Destination tx failed — recoverable via `retry_destination` |
| `completed` | Full crosschain operation finished |
| `abandoned` | User abandoned the execution |

### Crosschain Error Classes

- `422 longshot_source_hf_guardrail` — projected source health factor too low
- `422 longshot_destination_guardrail` — destination reserve frozen or disabled
- `422 longshot_no_route` — no bridge route available for chain pair
- `422 longshot_provider_override_unavailable` — forced provider not available
- `410 longshot_quote_expired` — quote TTL exceeded (re-quote needed)
- `403 longshot_wallet_mismatch` — build/event wallet differs from quote wallet
- `503 longshot_disabled` — crosschain feature disabled by runtime config

## 7. Transaction Tracking Hooks (Optional but Recommended)

If build response includes `transactionId`, track state:

- Sent hash:

```bash
curl -sS https://ana.vurto.cc/api/v1/transactions/123/send-hash \
  -H 'content-type: application/json' \
  --data '{"txHash":"0xabc..."}'
```

- Confirmed:

```bash
curl -sS https://ana.vurto.cc/api/v1/transactions/123/confirm \
  -H 'content-type: application/json' \
  --data '{"gasUsed":"210000","actualPaid":"1000000"}'
```

- Rejected:

```bash
curl -sS https://ana.vurto.cc/api/v1/transactions/123/reject \
  -H 'content-type: application/json' \
  --data '{"reason":"user_rejected"}'
```

- Failed:

```bash
curl -sS https://ana.vurto.cc/api/v1/transactions/123/fail \
  -H 'content-type: application/json' \
  --data '{"reason":"execution_failed"}'
```

History:

- `GET /transactions/user/:walletAddress?limit=50`

## 8. Minimum Pre-Trade Checklist for Agent

Before any build:

1. `POST /position` to get user exposure and available assets.
2. `POST /donator-status` to resolve fee profile.
3. `GET /dapp-vurto/config` to read donation policy, supported dual chains, and runtime limits.
4. For swap flows, always run quote right before build.
5. Reject execution if route impact is too high or payload is missing required addresses.

## 9. Common Error Classes

- `400 invalid_payload` or `invalid_amount`: malformed input.
- `400 unsupported_chain`: dual mode not configured on selected chain.
- `403 cors_origin_not_allowed`: origin not allowed by backend policy.
- `403 target_not_allowed` / `aggregator_not_allowed` / `spender_not_allowed`: dual allowlist enforcement.
- `422 quote_impact_too_high`: risk guardrail triggered.
- `429 rate_limited`: request throttle.

## 10. Response Fields Agents Should Persist

For every successful build, store at least:

- `to`
- `data`
- `value`
- `transactionId`
- `feeBps`
- `feeAmount`
- `_meta` (contains backend mode and donation policy context)
