Skip to content

API reference

Series: v1 · version: 1.0.0
Preferred base: https://dayprotocol.com/api/v1
OpenAPI 3.1: dayprotocol.com/api/v1/openapi.json
Machine routes: GET /api/v1/day/routes
Error catalog: GET /api/v1/day/errors
Identity: wallet address only (DAY-294). No characters or accounts as first-class DAY concepts.

Under /api/v1, paths mirror the internal table:
/api/v1/day/status/api/day/status, /api/v1/wallets/{address}/position/api/wallets/{address}/position.

Legacy /api/v1/characters/{id}/… may still resolve as compat aliases — do not use in new clients.


X-API-Key: <key>
RoleEnvEndpoints
ownerDAY_OWNER_API_KEYSroute, withdraw, auto-pay, bridge rescue, PUT auto-yield, webhooks, cage policy
agentDAY_AGENT_API_KEYSGET position/portfolio/performance/funding/preview, GET auto-yield
keeperDAY_KEEPER_API_KEYSsurvival, harvest/batch, map/stats refresh
public / permissionlessstatus, venues, strategies, deposit plans, harvest poke, balances
HTTPcodeWhen
401INVALID_API_KEY / UNAUTHORIZEDKey missing or not in allowlist
403UNAUTHORIZEDWrong role
403WALLET_SCOPEWallet not allowed for this key

X-Role is ignored. Do not send it for privilege.

import { DayClient } from "@dayprotocol/sdk";
const day = new DayClient({
baseUrl: "https://dayprotocol.com", // origin only — SDK never double-prefixes /api/v1
apiKey: process.env.DAY_OWNER_API_KEY,
});

TopicRule
identityWallet address only. Consumers map character/account → wallet outside DAY.
strategyIdBare venue id: suilend, navi, kamino, jito, aave-v3, morpho-blue, … Not suilend-sui-usdc.
amountsInteger micros strings ("1000000" = 1 USDC).
feesPrincipal 0; harvest yield skim 500 bps; swap fee default 100 bps (disclosed).
plansPrepare-only: ownerMustSign: true, submitted: false unless broadcast + real digest.
APYLive or null — never fabricated.
status codes200 done · 202 prepared · 422 blocked · 401/403 auth · 429 rate limit
HomesLabel
Sui, SolanaExecutable (phase-1 route homes)
Base, ArbitrumMap (discovery / prepare; broadcast off until GO + writeReady)

Terminal window
curl -sS https://dayprotocol.com/api/v1/day/status

Codegen source. Alias: /openapi.json.

Sui / Solana / Base / Arbitrum package ids + Map vs Executable labels.

Versioned error + blocker enum. Renaming a code is breaking.

Per-venue APY table; status: "unavailable" when live read fails.


GET /api/v1/day/venues · public · listVenues()

Section titled “GET /api/v1/day/venues · public · listVenues()”
Terminal window
curl -sS 'https://dayprotocol.com/api/v1/day/venues' | jq '.executionMode,.launchHomes,(.venues|length)'

GET /api/v1/day/strategies · public · listStrategies()

Section titled “GET /api/v1/day/strategies · public · listStrategies()”
Terminal window
curl -sS https://dayprotocol.com/api/v1/day/strategies | jq '.strategies[] | {strategyId,chain,ready}'

GET /api/v1/day/strategies/{id} · public · getStrategy(id)

Section titled “GET /api/v1/day/strategies/{id} · public · getStrategy(id)”

Bare id or form-* alias. Unknown → 404.

POST /api/v1/day/strategies/deposit/plan · public · prepareStrategyDeposit

Section titled “POST /api/v1/day/strategies/deposit/plan · public · prepareStrategyDeposit”
Terminal window
curl -sS -X POST https://dayprotocol.com/api/v1/day/strategies/deposit/plan \
-H 'content-type: application/json' \
-d '{"strategyId":"suilend","amountMicros":"1000000"}'

Principal fee 0. Same shape for every venue (venue-agnostic).

POST /api/v1/day/strategies/withdraw/plan · public · prepareStrategyWithdraw

Section titled “POST /api/v1/day/strategies/withdraw/plan · public · prepareStrategyWithdraw”

Canonical paths (no /day/ segment under wallets):

MethodPathAuthSDK
GET/api/v1/wallets/{address}/positionowner|agentgetPosition
GET/api/v1/wallets/{address}/portfolioowner|agentgetPortfolio
GET/api/v1/wallets/{address}/performanceowner|agentgetPerformance
GET/api/v1/wallets/{address}/fundingowner|agentgetFunding
POST/api/v1/wallets/{address}/previewowner|agentpreviewRoute
POST/api/v1/wallets/{address}/routeownerrouteYield
POST/api/v1/wallets/{address}/harvestpermissionlessharvest
POST/api/v1/wallets/{address}/withdrawownerwithdraw
POST/api/v1/wallets/{address}/auto-payownerenableAutoPay
POST/api/v1/wallets/{address}/rebalanceowner
GET/PUT/api/v1/wallets/{address}/auto-yieldowner|agent / ownergetAutoYield / setAutoYield
POST/api/v1/wallets/batch/positionsowner|agentbatchPositions
Terminal window
export BASE=https://dayprotocol.com/api/v1
export KEY=$DAY_OWNER_API_KEY
export W=0xYOUR_WALLET
curl -sS -H "X-API-Key: $KEY" "$BASE/wallets/$W/portfolio"
curl -sS -H "X-API-Key: $KEY" "$BASE/wallets/$W/performance"
curl -sS -X POST -H "X-API-Key: $KEY" -H 'content-type: application/json' \
-d "{\"amountMicros\":\"1000000\"}" "$BASE/wallets/$W/preview"
SituationHTTPBody
No stake / no yield422mode: "no_op_harvest", outcome: "blocked"
Successful ledger harvest200gross / fee (500 bps) / net
Prepare-only edge202prepared: true

Never invent gross yield from client body in production.


PathAssets
GET /api/v1/day/sui/wallet-balance?address=Sui assets
GET /api/v1/day/solana/wallet-balance?address=SOL + USDC
GET /api/v1/day/base/wallet-balance?address=ETH + USDC
GET /api/v1/day/arbitrum/wallet-balance?address=ETH + USDC

RPC failure → leg N/A (never invent).

Enablement: GET /api/v1/day/base/enablement, GET /api/v1/day/arbitrum/enablement.


PathChain
POST /api/v1/day/jupiter/planSolana
POST /api/v1/day/turbos/planSui
POST /api/v1/day/evm/swap/planBase / Arbitrum

Fee line items + slippage bounds (default 100 bps, max 500). ownerMustSign: true. No custody.


PathAuth
POST /api/v1/day/bridge/planpublic
POST /api/v1/day/bridge/deliveryowner|keeper
POST /api/v1/day/bridge/rescueowner

Lifecycle: prepare → owner sign → delivery tracking → credit only after proof.
Rescue destination locked to owner. Fee/risk disclosure on every plan.
Autopilot is within-chain only — never silent cross-chain rebalance.


PathAuth
GET /api/v1/day/webhooks/events/typespublic
POST /api/v1/day/webhooksowner (returns hmacKey once)
GET /api/v1/day/webhooksowner
POST /api/v1/day/webhooks/{id}/rotateowner
DELETE /api/v1/day/webhooks/{id}owner
GET /api/v1/day/webhooks/eventsowner|agent

Events: deposit.settled, withdraw.settled, harvest.completed, bridge.delivered, bridge.failed, position.updated, apy.updated.

HMAC: sign `$\{timestamp\}.$\{rawBody\}` with hmacKey; header X-DAY-Signature: t=<unix>,v1=<hex>.


Six actions: ROUTE · EXIT · REBALANCE · HARVEST · COMPOUND · AUTOPAY.
Owner signs; Day never holds keys; destination-lock on venues / payees / owner.

Base: /api/v1/day/base/cage, /api/v1/wallets/\{address\}/base/*
Arbitrum: /api/v1/day/arbitrum/cage, POST …/cage/prepare


Terminal window
export BASE=https://dayprotocol.com/api/v1
export KEY=$DAY_OWNER_API_KEY
export W=demo-wallet-1
# 1) discover
curl -sS "$BASE/day/strategies" | jq '.strategies[:3]'
# 2) deposit plan (prepare)
curl -sS -X POST "$BASE/day/strategies/deposit/plan" \
-H 'content-type: application/json' \
-d '{"strategyId":"suilend","amountMicros":"1000000"}' | jq '{status,feeMicros,ownerMustSign}'
# 3) position / portfolio
curl -sS -H "X-API-Key: $KEY" "$BASE/wallets/$W/position"
curl -sS -H "X-API-Key: $KEY" "$BASE/wallets/$W/portfolio"
# 4) harvest (permissionless poke)
curl -sS -X POST -H 'content-type: application/json' \
-d '{}' "$BASE/wallets/$W/harvest" | jq '{httpStatus,mode,grossYieldMicros,protocolFeeMicros}'
const day = new DayClient({ baseUrl: "https://dayprotocol.com", apiKey: process.env.DAY_OWNER_API_KEY });
await day.listStrategies();
await day.prepareStrategyDeposit({ strategyId: "suilend", amountMicros: "1000000" });
await day.getPortfolio(process.env.DAY_WALLET_ADDRESS!);
await day.getPerformance(process.env.DAY_WALLET_ADDRESS!);
await day.harvest(process.env.DAY_WALLET_ADDRESS!, { execute: false });

Terminal window
npm install github:dayprotocol/sdk
# package name: @dayprotocol/sdk
MethodRoute
getPosition(wallet)GET …/position
getPortfolio(wallet)GET …/portfolio
getPerformance(wallet)GET …/performance
batchPositions(wallets)POST …/batch/positions
previewRoute / routeYieldPOST …/preview · …/route
harvest / withdrawPOST …/harvest · …/withdraw
venueApyTable / errorCatalogGET …/venues/apy · …/errors
bridgePlan / bridgeRescuePlanbridge/*
baseWalletBalance / arbitrumWalletBalancechain balances

When paths, auth, or examples change, update in the same change:

  1. api/routes-manifest.mjs
  2. runtime/config/openapi.mjs
  3. This page + day repo docs/02-agent-api.md
  4. npm run check:docs-openapi

Live OpenAPI always wins for machines: openapi.json.