Agent API
Integration contract (DAY-291/292): 41-integration-contract.md · Full route table: 44-route-catalog.md · OpenAPI:
/api/v1/openapi.jsonAPI series: v1 · version:1.0.0· DAY-280
Preferred base:https://dayprotocol.com/api/v1
Legacy (still works):https://dayprotocol.com/api/v1/day/*
OpenAPI:https://dayprotocol.com/api/v1/openapi.json(also/openapi.json)
SDK:npm install github:dayprotocol/sdk· package@dayprotocol/sdk
Docs site: https://docs.dayprotocol.com
Machine source of truth for paths + auth = api/routes-manifest.mjs.
OpenAPI is generated from that manifest (runtime/config/openapi.mjs). CI fails if docs drift.
Under /api/v1, paths mirror the unversioned table:
/api/v1/day/status ≡ /api/day/status, /api/v1/wallets/{address}/position ≡ /api/v1/wallets/{address}/position.
0. Read this first (phase-1 realities)
Section titled “0. Read this first (phase-1 realities)”| Fact | Detail |
|---|---|
| Auth header | X-API-Key only for roles. X-Role is ignored (spoofable). |
| Roles | owner / agent / keeper from server allowlists (DAY_OWNER_API_KEYS, DAY_AGENT_API_KEYS, DAY_KEEPER_API_KEYS). |
| strategyId | Bare venue id: suilend, navi, kamino, aave-v3. Not suilend-sui-usdc. form-suilend accepted as alias. |
| Amounts | Micros strings ("1000000" = 1 USDC). Never floats. |
| Fees | 0 bps on principal (deposit/withdraw/route). 500 bps skim on yield only at harvest. |
| Writes | Return prepared plans. ownerMustSign: true, submitted: false unless broadcast env produces a real digest. |
| Harvest | Does not invent yield. No stake → mode: "no_op_harvest", reason: "no_staked_position". |
| Identity | Wallet address only (DAY-294). Canonical money surface: /api/v1/wallets/{address}/*. No characters/accounts as first-class DAY concepts. |
Execution modes (from GET /api/v1/day/venues)
Section titled “Execution modes (from GET /api/v1/day/venues)”executionMode | Meaning |
|---|---|
disabled | Plans still prepare; notes may include execution_disabled |
owner_sign_prepare | OPEN_YIELD_EXECUTION_ENABLED=1 — owner signs; no server broadcast |
broadcast | execution + OPEN_YIELD_ALLOW_BROADCAST=1 — server may submit only with real digest |
1. Auth model (correct)
Section titled “1. Auth model (correct)”X-API-Key: <your-key>| Role | Env allowlist | Typical use |
|---|---|---|
| owner | DAY_OWNER_API_KEYS | Mutations: route, withdraw, auto-pay, bridge rescue, set policy |
| agent | DAY_AGENT_API_KEYS | Reads: position, preview, funding, GET auto-yield (wallet scope may apply) |
| keeper | DAY_KEEPER_API_KEYS | Survival, harvest batch, some refresh routes |
| public / permissionless | (none) | status, venues, strategies, harvest poke, deposit plan |
| HTTP | When |
|---|---|
401 INVALID_API_KEY | Key present but not in any allowlist |
403 UNAUTHORIZED | Missing key or wrong role |
403 WALLET_SCOPE | Key not allowed for this wallet address |
SDK:
import { DayClient } from "@dayprotocol/sdk";
// baseUrl: origin OR https://dayprotocol.com/api/v1 — SDK never double-prefixesconst day = new DayClient({ baseUrl: "https://dayprotocol.com", // recommended: origin only apiKey: process.env.DAY_OWNER_API_KEY, // → X-API-Key});sessionToken (optional) sets Authorization: Bearer … for future session auth — not how owner roles work today. Do not document Bearer as the primary model.
Local/dev: day-dev-owner / day-dev-agent / day-dev-keeper only when DAY_AUTH_ALLOW_DEV_KEYS=1 and not production.
2. Getting started (< 5 minutes)
Section titled “2. Getting started (< 5 minutes)”export DAY_KEY="$DAY_OWNER_API_KEY" # real owner keyexport BASE=https://dayprotocol.com/api/v1 # preferred v1 prefixexport WALLET=0xYOUR_WALLET_OR_DEMO
# 1) statuscurl -sS "$BASE/day/status" | jq '{phase,launchHomes,protocolYieldSkimBps,executionEnabled}'
# 2) strategies (bare ids)curl -sS "$BASE/day/strategies" | jq '.strategies[:3] | .[] | {strategyId,chain,ready,grossApyBps}'
# 3) deposit plan (prepare-only, fee 0)curl -sS -X POST "$BASE/day/strategies/deposit/plan" \ -H 'content-type: application/json' \ -d '{"strategyId":"suilend","amountMicros":"1000000"}' \ | jq '{status,ownerMustSign,submitted,feeMicros,executionMode}'
# 4) position (owner or agent key)curl -sS -H "X-API-Key: $DAY_KEY" "$BASE/wallets/$WALLET/position" | jq .import { DayClient } from "@dayprotocol/sdk";
// Either form works (SDK never double-prefixes /api/v1):// baseUrl: "https://dayprotocol.com"// baseUrl: "https://dayprotocol.com/api/v1"const day = new DayClient({ baseUrl: "https://dayprotocol.com", // recommended: origin only apiKey: process.env.DAY_OWNER_API_KEY,});await day.readiness();await day.listStrategies();await day.prepareStrategyDeposit({ strategyId: "suilend", amountMicros: "1000000" });await day.getPosition(process.env.DAY_WALLET_ADDRESS || "0xdemo");3. Endpoint reference (integrator set)
Section titled “3. Endpoint reference (integrator set)”3.1 GET /api/v1/day/status · public · SDK readiness()
Section titled “3.1 GET /api/v1/day/status · public · SDK readiness()”No body. Returns phase, launchHomes, protocolYieldSkimBps (500), execution flags.
3.2 GET /api/v1/day/venues · public · SDK listVenues()
Section titled “3.2 GET /api/v1/day/venues · public · SDK listVenues()”Query: ?chain=sui|solana|base|arbitrum, ?live=1 (optional live APY; fail-closed if live reader fails).
Success fields (top-level): executionMode, executionEnabled, broadcastEnabled, launchHomes, venues[] with venueId, ready, writeReady, gross_apy_bps, chain, liveYieldReader.
3.3 GET /api/v1/day/strategies · public · SDK listStrategies()
Section titled “3.3 GET /api/v1/day/strategies · public · SDK listStrategies()”strategyId === venueId. Prefer over /forms for product UI.
3.4 GET /api/v1/day/strategies/{id} · public · SDK getStrategy(id)
Section titled “3.4 GET /api/v1/day/strategies/{id} · public · SDK getStrategy(id)”id = suilend or form-suilend. Unknown → 404.
3.5 POST /api/v1/day/strategies/deposit/plan · public · SDK prepareStrategyDeposit
Section titled “3.5 POST /api/v1/day/strategies/deposit/plan · public · SDK prepareStrategyDeposit”{ "strategyId": "suilend", "amountMicros": "1000000", "owner": "0x…", "autoYieldEnabled": true }| Field | Type | Required | Notes |
|---|---|---|---|
| strategyId | string | yes | bare venue id |
| amountMicros | string | yes | micros |
| owner | string | no | optional plan field |
| autoYieldEnabled | boolean | no | default true for supply allow |
Success example:
{ "schemaVersion": "day-strategy-deposit-plan.v1", "status": "prepared", "submitted": false, "ownerMustSign": true, "feeMicros": "0", "protocolYieldSkimBps": 500, "executionMode": "owner_sign_prepare", "strategyId": "suilend", "amountMicros": "1000000"}3.6 POST /api/v1/day/strategies/withdraw/plan · public · SDK prepareStrategyWithdraw
Section titled “3.6 POST /api/v1/day/strategies/withdraw/plan · public · SDK prepareStrategyWithdraw”Same id rules; principal fee 0.
3.7 GET /api/v1/wallets/{address}/position · owner|agent · SDK getPosition
Section titled “3.7 GET /api/v1/wallets/{address}/position · owner|agent · SDK getPosition”curl -sS -H "X-API-Key: $DAY_KEY" \ https://dayprotocol.com/api/v1/wallets/demo/position200 body includes liquidMicros, stakedMicros, byChain, estimates, autoYieldEnabled.
3.7b GET /api/v1/wallets/{address}/portfolio · owner|agent · SDK getPortfolio
Section titled “3.7b GET /api/v1/wallets/{address}/portfolio · owner|agent · SDK getPortfolio”Balances + byChain + byVenue + asOf + freshness. Wallet-keyed.
3.7c GET /api/v1/wallets/{address}/performance · owner|agent · SDK getPerformance
Section titled “3.7c GET /api/v1/wallets/{address}/performance · owner|agent · SDK getPerformance”Realized yield since inception, net 30d, current APY per venue (null if unavailable — never fabricated), blended APY.
3.7d POST /api/v1/wallets/batch/positions · owner|agent · SDK batchPositions
Section titled “3.7d POST /api/v1/wallets/batch/positions · owner|agent · SDK batchPositions”{ "wallets": ["0xabc…", "So1…"] }Max 50. Each result is { walletAddress, ok, position|error }.
3.7e GET /api/v1/day/venues/apy · public · SDK venueApyTable
Section titled “3.7e GET /api/v1/day/venues/apy · public · SDK venueApyTable”Every DAY venue with grossApyBps or status: "unavailable". Fail-closed on live read failure.
3.7f GET /api/v1/day/errors · public · SDK errorCatalog
Section titled “3.7f GET /api/v1/day/errors · public · SDK errorCatalog”Versioned error + blocker enum (enumVersion). Envelope: { code, message, retryable, blockers[] }. Renaming a code is breaking.
3.8 POST /api/v1/wallets/{address}/preview · owner|agent · SDK previewRoute
Section titled “3.8 POST /api/v1/wallets/{address}/preview · owner|agent · SDK previewRoute”{ "amountMicros": "1000000", "stake": false, "token": "USDC" }Never mutates. planStatus: "prepared".
3.9 POST /api/v1/wallets/{address}/route · owner · SDK routeYield
Section titled “3.9 POST /api/v1/wallets/{address}/route · owner · SDK routeYield”Credits liquid (and optional stake if Auto Yield on). Idempotency-Key supported.
{ "amountMicros": "1000000", "token": "USDC", "stake": false, "chain": "sui" }Agent key → 403. Principal fee 0.
3.10 POST /api/v1/wallets/{address}/harvest · permissionless · SDK harvest
Section titled “3.10 POST /api/v1/wallets/{address}/harvest · permissionless · SDK harvest”{ "compound": true, "execute": true }| Situation | Response |
|---|---|
| No staked balance | HTTP 422, mode: "no_op_harvest", outcome: "blocked", gross "0" |
| Live claim unavailable | gross "0", reason yield_unavailable / etc. |
| Real claim micros | skim 500 bps → protocolFeeMicros / netYieldMicros / compound |
Never accept client-invented gross without fixture flags (disabled in prod).
3.11 POST /api/v1/wallets/{address}/withdraw · owner · SDK withdraw
Section titled “3.11 POST /api/v1/wallets/{address}/withdraw · owner · SDK withdraw”{ "amountMicros": "500000", "token": "USDC", "unstakeFirst": true }Principal fee 0. Agent → 403.
3.12 POST /api/v1/wallets/{address}/auto-pay · owner · SDK enableAutoPay
Section titled “3.12 POST /api/v1/wallets/{address}/auto-pay · owner · SDK enableAutoPay”{ "enabled": true, "percentage": 30, "targets": ["storage", "inference"] }3.13 POST /api/v1/day/bridge/plan · public · SDK bridgePlan
Section titled “3.13 POST /api/v1/day/bridge/plan · public · SDK bridgePlan”{ "sourceChain": "sui", "destChain": "solana", "amountMicros": "1000000", "sourceAddress": "0xOWNER", "destinationAddress": "So1…1112"}Aliases: fromChain/toChain, amount, from/to.
Blocked responses always include blockers[], blockerDetails, requiredFields, supportedLanes.
DAY-251 lifecycle: prepare → owner_sign → submit → delivery_tracking → credit_after_delivery.
ownerMustSign: true, custody.teamIntermediateWallet: false, credit only after confirmed delivery.
DAY-254 disclosures: every plan includes fees (protocol bridge fee 0, venue pass-through) and risks (codes + summary + timeout).
3.14 POST /api/v1/day/bridge/rescue · owner · SDK bridgeRescuePlan
Section titled “3.14 POST /api/v1/day/bridge/rescue · owner · SDK bridgeRescuePlan”Failed / timeout / under-minOut delivery → funds destination always owner (DAY-253).
Cannot redirect: destinationAddress ≠ ownerAddress → blocked + destination_not_owner.
Response includes statusSurface (timeout, refundEligible, destinationLockedToOwner).
3.14b POST /api/v1/day/bridge/delivery · owner|keeper
Section titled “3.14b POST /api/v1/day/bridge/delivery · owner|keeper”Credit gate: actual ≥ minOut + destination proof. Timeout/refund → rescue, never credit.
statusSurface on every response. Idempotent on bridgeTxId.
3.14c POST /api/v1/wallets/{address}/autopilot/decide · owner|agent
Section titled “3.14c POST /api/v1/wallets/{address}/autopilot/decide · owner|agent”DAY-255: within-chain only. decide() never emits cross-chain REBALANCE or bridge legs.
Bridge is an explicit owner/agent Mayan plan (/bridge/plan), not an autopilot action.
3.15 POST /api/v1/day/gas-sponsor/plan · public
Section titled “3.15 POST /api/v1/day/gas-sponsor/plan · public”Prepare-only gas sizing.
3.16 GET /api/v1/day/packages · public
Section titled “3.16 GET /api/v1/day/packages · public”On-chain package ids (day-packages.v1). Base and Arbitrum include live vs target blocks: DayRegistry live ≠ execution home.
| Field | Meaning |
|---|---|
phase1Homes | ["sui","solana"] — Executable route homes |
expansionHomes | ["base","arbitrum"] — Map / discovery (registry may be live) |
labels | Per-chain Map | Executable |
chains.*.status | Contract/program deploy status — not adapter write-readiness |
honesty | Map-vs-Executable rules; fee 500 bps yield / 0 principal |
Arbitrum/Base enablement: stub adapters → broadcastEnabled is always false even when the global broadcast flag is on.
3.16b Base cage (DAY-231) · prepare-only until Base GO
Section titled “3.16b Base cage (DAY-231) · prepare-only until Base GO”Offchain OwnerPolicy + capability parity on Base (DayRegistry-bound). Wallet-only identity. Day never holds keys; ownerMustSign: true, submitted: false.
| Method | Path | Auth |
|---|---|---|
GET | /api/v1/day/base/cage | public — action vocabulary + invariants |
GET | /api/v1/wallets/{address}/base/cage | owner|agent |
GET/PUT | /api/v1/wallets/{address}/base/policy | owner|agent / owner — venue + payee allowlists, caps |
GET | /api/v1/wallets/{address}/base/capability | owner|agent |
POST | /api/v1/wallets/{address}/base/capability/grant | owner |
POST | /api/v1/wallets/{address}/base/capability/revoke | owner (immediate total) |
POST | /api/v1/wallets/{address}/base/action | owner — prepare ROUTE|EXIT|REBALANCE|HARVEST|COMPOUND|AUTOPAY |
Destination-lock: venues and payees must be owner-allowlisted; EXIT destination is the owner only; free-form transfer addresses are rejected. Capability scopes: route, exit, rebalance, harvest, compound, autopay.
Arbitrum honesty (DAY-237): chains.arbitrum.status=live means DayRegistry is deployed
(0x00f09EEdfF406217D5CF7adf60E8873760F67e38, chainId 42161). It does not mean live
deposits — writeReady / liveMoneyPath stay false while adapters are stubs. Superseded
registry (no fee caps): 0x342d57cf3d9cf7d35267b834327b37A1f9638752.
3.16c GET /api/v1/day/arbitrum · public · SDK arbitrumProfile
Section titled “3.16c GET /api/v1/day/arbitrum · public · SDK arbitrumProfile”Arbitrum expansion profile. goNoGo is NO_GO_EXPANSION or PREPARE_OK_STUBS — never imply live write.
3.16d GET /api/v1/day/arbitrum/enablement · public · SDK arbitrumEnablement
Section titled “3.16d GET /api/v1/day/arbitrum/enablement · public · SDK arbitrumEnablement”DAY-243 write gate: broadcastEnabled stays false until chain writeReady +
OPEN_YIELD_ARBITRUM_WRITE_GO. Per-adapter writeReady: false for stubs. UI must not treat
PREPARE_OK_STUBS as live deposits.
3.16e GET /api/v1/day/arbitrum/wallet-balance?address= · public · SDK arbitrumWalletBalance
Section titled “3.16e GET /api/v1/day/arbitrum/wallet-balance?address= · public · SDK arbitrumWalletBalance”DAY-242 read-only ETH + USDC for a wallet address (identity = wallet only, DAY-294).
On RPC fail each leg is N/A — never invent balances. No keys / no broadcast.
3.17 GET /api/v1/day/discover · public · SDK listOpportunities
Section titled “3.17 GET /api/v1/day/discover · public · SDK listOpportunities”Public DefiLlama map / discovery (also POST /api/v1/day/discover with filters). Not execution truth — adapters own APY.
3.18 GET /api/v1/day/base · public · SDK baseProfile()
Section titled “3.18 GET /api/v1/day/base · public · SDK baseProfile()”Base expansion profile (role: expansion_discovery). DayRegistry may be live; execution is off until write adapters + OPEN_YIELD_BASE_EXECUTION.
3.19 GET /api/v1/day/base/enablement · public · SDK baseEnablement()
Section titled “3.19 GET /api/v1/day/base/enablement · public · SDK baseEnablement()”Enablement gate (DAY-230): goNoGo=NO_GO_EXPANSION, executionEnabled=false today. Response includes live vs target. Do not claim Base as an execution home until write adapters are ready.
3.20 GET /api/v1/day/base/wallet-balance?address= · public · SDK baseWalletBalance(address)
Section titled “3.20 GET /api/v1/day/base/wallet-balance?address= · public · SDK baseWalletBalance(address)”Read-only ETH + Circle USDC on Base (DAY-235). Fail-closed: RPC failure → null balances / 502, never fabricates amounts.
curl -sS "$BASE/day/base/wallet-balance?address=0x0000000000000000000000000000000000000001" | jq '{status,eth,usdc,blockers}'Also: GET /api/v1/day/sui/wallet-balance?address= · GET /api/v1/day/solana/wallet-balance?address=.
3.21 GET /openapi.json · public
Section titled “3.21 GET /openapi.json · public”Full OpenAPI 3.1 for codegen.
4. Full deposit walkthrough
Section titled “4. Full deposit walkthrough”BASE=https://dayprotocol.com/api/v1KEY=$DAY_OWNER_API_KEYWALLET=walkthrough-1
# Discovercurl -sS "$BASE/day/strategies" | jq '.strategies[] | select(.strategyId=="suilend")'
# Preview credit (no chain submit)curl -sS -X POST -H "X-API-Key: $KEY" -H 'content-type: application/json' \ -d '{"amountMicros":"1000000","stake":false}' \ "$BASE/wallets/$WALLET/preview" | jq .
# Route credit liquidcurl -sS -X POST -H "X-API-Key: $KEY" -H 'content-type: application/json' \ -H "Idempotency-Key: oy_route_${WALLET}_1" \ -d '{"amountMicros":"1000000","token":"USDC","stake":false,"chain":"sui"}' \ "$BASE/wallets/$WALLET/route" | jq '{success,depositedAmountMicros,feeOnDepositMicros,staked}'
# Positioncurl -sS -H "X-API-Key: $KEY" "$BASE/wallets/$WALLET/position" | jq '{liquidMicros,stakedMicros}'
# Venue deposit plan (owner signs offchain)curl -sS -X POST -H 'content-type: application/json' \ -d '{"strategyId":"suilend","amountMicros":"1000000"}' \ "$BASE/day/strategies/deposit/plan" | jq '{status,ownerMustSign,submitted,feeMicros}'
# Harvest (no stake → no_op)curl -sS -X POST -H "X-API-Key: $KEY" -H 'content-type: application/json' \ -d '{"execute":true}' \ "$BASE/wallets/$WALLET/harvest" | jq '{mode,reason,grossYieldMicros,protocolFeeMicros}'
# Withdraw principalcurl -sS -X POST -H "X-API-Key: $KEY" -H 'content-type: application/json' \ -d '{"amountMicros":"1000000"}' \ "$BASE/wallets/$WALLET/withdraw" | jq .Fee check: route/withdraw → fee micros 0. Harvest with real yield → 5% of gross.
5. Bridge walkthrough (Mayan Sui ↔ Sol)
Section titled “5. Bridge walkthrough (Mayan Sui ↔ Sol)”# Preparedcurl -sS -X POST https://dayprotocol.com/api/v1/day/bridge/plan \ -H 'content-type: application/json' \ -d '{ "sourceChain":"sui", "destChain":"solana", "amountMicros":"1000000", "sourceAddress":"0xOWNER_SUI", "destinationAddress":"So11111111111111111111111111111111111111112" }' | jq '{status,rail,blockers,supportedLanes}'
# Missing field → blocked with requiredFieldscurl -sS -X POST https://dayprotocol.com/api/v1/day/bridge/plan \ -H 'content-type: application/json' \ -d '{"sourceChain":"sui","destChain":"solana"}' | jq '{status,blockers,requiredFields,blockerDetails}'
# Rescue (owner key) — destination locked to ownercurl -sS -X POST https://dayprotocol.com/api/v1/day/bridge/rescue \ -H "X-API-Key: $DAY_KEY" -H 'content-type: application/json' \ -d '{"ownerAddress":"0xOWNER","asset":"USDC","amountMicros":"1000000"}' | jq .await day.bridgePlan({ sourceChain: "sui", destChain: "solana", amountMicros: "1000000", sourceAddress: "0x…", destinationAddress: "So1…",});await day.bridgeRescuePlan({ ownerAddress: "0x…", asset: "USDC", amountMicros: "1000000" });5b. In-chain swap plans (Jupiter / Turbos / EVM)
Section titled “5b. In-chain swap plans (Jupiter / Turbos / EVM)”Prepare-only owner-sign paths. Never custody. ownerMustSign: true, submitted: false.
| Endpoint | Chain | Venue |
|---|---|---|
POST /api/v1/day/jupiter/plan | Solana | Jupiter |
POST /api/v1/day/turbos/plan | Sui | Turbos |
POST /api/v1/day/evm/swap/plan | Base / Arbitrum | Uniswap-v3 class |
Fees (disclosed as feeLineItems):
| Line | Default |
|---|---|
| Protocol swap fee | 100 bps (protocolSwapFeeBps, from bps.mjs) |
| Pool / venue fee | estimate (poolFeeBps, default 30; stables 5 on EVM) |
Slippage: default slippageBps=100, hard max 500 (blocked above max).
Idempotency: body idempotencyKey or header — shape oy_<op>_<walletAddress>_<nonce> (e.g. oy_jupiter_So1…_1).
# Solana Jupiter (DAY-245)curl -sS -X POST "$BASE/day/jupiter/plan" \ -H 'content-type: application/json' \ -d '{ "mintIn":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "mintOut":"So11111111111111111111111111111111111111112", "amountIn":"1000000", "ownerAddress":"So1…", "slippageBps":100, "idempotencyKey":"oy_jupiter_So1_1" }' | jq '{status,ownerMustSign,protocolSwapFeeBps,feeLineItems,slippageBps,submitted}'
# Sui Turbos (DAY-246)curl -sS -X POST "$BASE/day/turbos/plan" \ -H 'content-type: application/json' \ -d '{"coinIn":"USDC","coinOut":"SUI","amountIn":"1000000","ownerAddress":"0x…"}' \ | jq '{status,feeLineItems,ownerMustSign}'
# Base / Arb EVM (DAY-247) — USDC↔native or stable↔stable; prepare-only until chain GOcurl -sS -X POST "$BASE/day/evm/swap/plan" \ -H 'content-type: application/json' \ -d '{"chain":"base","tokenIn":"USDC","tokenOut":"native","amountIn":"1000000","ownerAddress":"0x…"}' \ | jq '{status,pairKind,executionMode,feeLineItems,ownerMustSign,submitted}'Response always includes feeLineItems (protocol + pool estimate), amountInAfterProtocolFee, and never sets submitted: true from this API.
6. Error envelope
Section titled “6. Error envelope”{ "code": "UNAUTHORIZED", "message": "owner required" }| code | HTTP | Meaning |
|---|---|---|
| UNAUTHORIZED | 403 | Missing/wrong role |
| INVALID_API_KEY | 401 | Unknown key |
| WALLET_SCOPE | 403 | Character not in key scope |
| NOT_FOUND | 404 | Unknown route / strategy / form |
| RATE_LIMITED | 429 | Rate limit |
| INTERNAL_ERROR | 500 | Server fault (no internal leak) |
Many plan endpoints return HTTP 200 with status: "blocked" and blockers: ["…"] (not 4xx) — check status / blockers in the body.
7. Fees (concrete)
Section titled “7. Fees (concrete)”| Action | Fee |
|---|---|
| deposit / route / withdraw principal | 0 |
| strategy deposit/withdraw plan | feeMicros: "0" |
| harvest yield | 500 bps of gross → protocolFeeMicros |
| swap plan (Jupiter/Turbos/EVM) | 100 bps protocol + pool fee line items |
| gas sponsor plan | 100 bps (plan field) |
Example: gross yield 20000 micros → protocol 1000, net 19000.
8. SDK (DayClient) essentials
Section titled “8. SDK (DayClient) essentials”| Method | HTTP |
|---|---|
listVenues / listStrategies | GET venues / strategies |
getStrategy | GET strategies/{id} |
prepareStrategyDeposit / prepareStrategyWithdraw | POST …/plan |
getPosition | GET …/position |
previewRoute / routeYield | POST preview / route |
harvest / withdraw / enableAutoPay | POST harvest / withdraw / auto-pay |
bridgePlan / bridgeRescuePlan | POST bridge/plan · rescue |
readiness / sdkRelease / apiVersion | meta |
Constructor: { baseUrl, apiKey, sessionToken?, fetchImpl?, checkUpdate? }.
Client sends X-DAY-API-Client-Version. Server returns X-DAY-API-Version*.
9. Changelog (public API)
Section titled “9. Changelog (public API)”| Ver | Date | Notes |
|---|---|---|
| v1 / 1.0.0 | 2026-07-11 | First formal DAY API v1 — OpenAPI 3.1, /api/v1/* prefix, X-API-Key auth, owner|agent reads, executionMode, live claim opt-in, bridge contract, bare strategyId |
Related: DAY-264–269 (XEL rail), DAY-140/143 (auth), DAY-280 (docs/OpenAPI), XEL-182.
10. All routes
Section titled “10. All routes”GET /api/v1/day/routes returns the full machine manifest.
GET /openapi.json is the OpenAPI 3.1 expansion with request schemas for integrator endpoints.