# 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

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

Health check:

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

Stage call template (no API key required in stage):

```bash
curl -sS https://ana-stage.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.
- Stage note: on `ana-stage.vurto.cc`, sensitive routes are currently open (no API key required).
- Sensitive routes:
  - `POST /donator-status`
  - `POST /quote/*`
  - `POST /build/*`
- Production (`ana.vurto.cc`) is currently also public without API key.
- 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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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-stage.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` and `build_borrow` are same-chain, single-transaction tools.
> **Crosschain Supply** and **Crosschain Repay** (sections 6.10–6.11) are multi-step, multi-chain operations that use bridges.

**Crosschain Supply** withdraws collateral from the source chain, bridges it to the destination chain, and supplies it as collateral there.

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-stage.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-stage.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-stage.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-stage.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-stage.vurto.cc/api/v1/longshot/executions/lex_.../status?walletAddress=0x1111111111111111111111111111111111111111"
```

Recover from failure:

```bash
curl -sS https://ana-stage.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 to the destination chain, and repays debt there. It is the complement of Crosschain Supply: one moves collateral across chains, the other moves debt.

Uses `intent: "repay"` in the quote request. The destination step executes a repay instead of supply.

Quote example:

```bash
curl -sS https://ana-stage.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

To migrate a full lending position (collateral + debt) from chain A to chain B, alternate **Crosschain Supply** and **Crosschain Repay** cycles:

1. **Crosschain Supply** — move part of the collateral from A → B (must keep source health factor ≥ 1.08).
2. **Crosschain Repay** — use the new collateral on B to borrow, bridge back, and repay part of the debt on A.
3. **Repeat** steps 1–2 until all debt on A is repaid.
4. **Final Crosschain Supply** — move remaining collateral from A → B.

**Key rules:**
- Always call `POST /position` on both chains between cycles to recalculate available amounts.
- The source health factor guardrail (≥ 1.08) limits how much can be moved per cycle.
- The last step is always a Crosschain Supply (once debt is zero, all remaining collateral can move).
- Each cycle is a separate `quote → build → execute` flow.

---

### 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-stage.vurto.cc/api/v1/transactions/123/send-hash \
  -H 'content-type: application/json' \
  --data '{"txHash":"0xabc..."}'
```

- Confirmed:

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

- Rejected:

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

- Failed:

```bash
curl -sS https://ana-stage.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)
