Yieldbay Public API

Base URL: https://api.yieldbay.fi

Yieldbay exposes curated health monitoring data for Solana yield protocols, the live protocol yield overview, and the same wallet portfolio and rebalance engine that powers the Yieldbay dashboard. The public API is built for dashboards, health feeds, monitors, bots, and LLM/agent integrations.

Authentication

Use one of:

Authorization: Bearer yb_live_<key_id>.<secret>
X-API-Key: yb_live_<key_id>.<secret>

API keys are owned by a connected Solana wallet. There are no email-based API users. Get or rotate an API key from the API page at https://app.yieldbay.fi/developers. The raw API key is shown only when it is created or rotated. If the key is lost, rotate it from the Yieldbay app with the owning wallet.

Scopes

Every endpoint under /v1 declares one scope:

A key carries the scopes chosen when it was created (all of them by default). The wallet's tier decides which scopes are entitled; a request needs both. 403 tier_upgrade_required means the tier lacks the scope, 403 missing_scope means the key does.

Tiers and Limits

Limits come from the wallet's tier (wallet_limits.tier) plus optional per-wallet overrides. Every call counts once against the global limits and once against its endpoint group:

The current public tier is free_beta:

Every monthly window, global and per group, is anchored to the moment the wallet first got API access. If a wallet gets API access on April 25 at 10:30 UTC, its monthly windows reset on May 25 at 10:30 UTC. Month-end dates are clamped when needed.

Successful authenticated responses include:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1777098000
X-RateLimit-Month-Limit: 300000
X-RateLimit-Month-Remaining: 299999
X-RateLimit-Month-Reset: 1779689400

Routes in a group with windows add the group's headers (only the windows the tier defines):

X-RateLimit-Group: portfolio
X-RateLimit-Group-Limit: 2
X-RateLimit-Group-Remaining: 1
X-RateLimit-Group-Reset: 1777098000
X-RateLimit-Group-Month-Limit: 300
X-RateLimit-Group-Month-Remaining: 299
X-RateLimit-Group-Month-Reset: 1779689400

Error Format

{
  "error": { "code": "rate_limited", "message": "API rate limit exceeded" },
  "request_id": "..."
}

Public

GET /health

No API key required.

Response:

{
  "ok": true,
  "service": "yieldbay-api",
  "timestamp": 1777097429754,
  "request_id": "..."
}

GET /docs

Returns a human-readable HTML documentation page.

GET /docs.md

Returns this markdown document for agents and CLI clients.

GET /llms.txt

Returns a short LLM discovery file.

Health Data

API key required. Scope: health:read. Protocol filter values: spl_stake_pools, meteora_dv, jupiter_borrow, jupiter_earn, perena, kamino, meteora_amm_tx.

GET /v1/health/summary

Returns current system state and one row for every monitored protocol.

Response shape:

{
  "data": {
    "status": "ok|warning|critical|stale",
    "freshness": "fresh|stale",
    "critical_open": 0,
    "warning_open": 0,
    "info_open": 0,
    "visible_events": 0,
    "last_run": {
      "run_id": 5970,
      "status": "ok",
      "started_at": "2026-04-25T10:00:00.000Z",
      "duration_ms": 1234,
      "protocols": ["spl_stake_pools"]
    },
    "protocols": [
      {
        "protocol": "perena",
        "protocol_name": "Perena USD*",
        "status": "ok",
        "critical_open": 0,
        "warning_open": 0,
        "info_open": 0,
        "links": {
          "app": "https://app.yieldbay.fi/health",
          "protocol": "https://app.perena.org/portfolio"
        },
        "display": {
          "protocol_name": "Perena USD*",
          "protocol_name_key": "protocol.perena.name",
          "status_label": "Operational",
          "status_label_key": "health_status.ok.label"
        }
      }
    ],
    "display": {
      "title": "Yieldbay health: Operational",
      "summary": "0 critical, 0 warning, 0 info open incidents. 0 visible feed events.",
      "status_label": "Operational",
      "status_label_key": "health_status.ok.label",
      "freshness_label": "Fresh",
      "freshness_label_key": "freshness.fresh.label"
    }
  },
  "meta": { "as_of": "2026-04-25T10:00:00.000Z", "stale_after_ms": 900000 },
  "request_id": "..."
}

GET /v1/health/insight

Returns the latest saved AI health insight as text/plain.

Example:

All monitored protocols are operational. No critical incidents are open.

GET /v1/health/events

Latest public feed events. Query params:

GET /v1/health/incidents

Current open incidents. Query params:

Events and incidents response shape:

{
  "data": [
    {
      "id": "incident-key",
      "kind": "incident",
      "source_kind": "incident",
      "type": "SUPPLY_DROP",
      "alert_type": "SUPPLY_DROP",
      "title": "Balance dropped",
      "summary": "Vault balance is down 15.20% from its reference level.",
      "protocol": "kamino",
      "protocol_name": "Kamino kVaults",
      "entity": { "name": "Vault", "address": "...", "type": "vault" },
      "severity": "warning",
      "status": "open",
      "field": {
        "name": "shares_supply",
        "label": "Shares supply",
        "label_key": "field.shares_supply.label"
      },
      "display": {
        "title": "Balance dropped",
        "title_key": "alert.SUPPLY_DROP.title",
        "summary": "Vault balance is down 15.20% from its reference level.",
        "protocol_name": "Kamino kVaults",
        "protocol_name_key": "protocol.kamino.name",
        "entity_name": "Vault",
        "severity_label": "Warning",
        "severity_label_key": "severity.warning.label",
        "status_label": "Open",
        "status_label_key": "status.open.label",
        "field_label": "Shares supply",
        "field_label_key": "field.shares_supply.label"
      },
      "values": {
        "reference": "1,000.00",
        "current": "850.00",
        "delta": "-150.00",
        "delta_pct": "-15.00%",
        "worst": "800.00",
        "worst_delta": "-200.00",
        "worst_delta_pct": "-20.00%"
      },
      "raw_values": {
        "reference": "1000",
        "current": "850",
        "delta": -150,
        "delta_pct": -15
      },
      "started_at": "2026-04-25T10:00:00.000Z",
      "updated_at": "2026-04-25T10:05:00.000Z",
      "resolved_at": null,
      "sticky_until": "2026-04-26T10:05:00.000Z",
      "run_id": 5970,
      "links": {
        "app": "https://app.yieldbay.fi/health",
        "explorer": "https://solscan.io/account/...",
        "protocol": "https://kamino.com/lend/usdc-prime"
      }
    }
  ],
  "meta": {
    "limit": 50,
    "cursor": null,
    "next_cursor": null,
    "sort": "severity",
    "as_of": "2026-04-25T10:05:00.000Z",
    "offset": 0
  },
  "request_id": "..."
}

For /v1/health/events, item kind is event. For /v1/health/incidents, item kind is incident. source_kind identifies the underlying source.

Yields

API key required. Scope: yields:read.

GET /v1/yields

Protocol-level yield overview, refreshed every 5 minutes: SOL options (Jito, Meteora Dynamic Vault, The Vault), Perena USD*, every enabled Meteora Dynamic Vault, Jupiter Lend Earn vaults and Kamino Earn vaults. Pair-scoped pools (DLMM, DAMM) are wallet-dependent and only appear in the wallet portfolio.

Response shape:

{
  "data": {
    "generated_at": "2026-09-09T07:15:00.000Z",
    "sol": {
      "jito": { "apy": 4.86, "sol_per_jitosol": "1.3003" },
      "meteora_dv": { "token_mint": "So111...", "virtual_price": "1.1264", "lp_mint": "...", "apy_7d": 0.56, "average_apy": 0.55, "closest_apy": 0.55 },
      "the_vault": { "mint": "EUWoT...", "apy": 8.18, "apy_7d": 8.9, "apy_30d": 8.18, "exchange_rate": 0.996, "total_balance_sol": 6139.7, "updated_at": "..." }
    },
    "perena": { "mint": "star9...", "price": 1.0937, "apy_24h": 10.76, "apy_7d": 9.62 },
    "meteora_dv": [ { "token_address": "...", "symbol": "USDC", "pubkey": "...", "lp_mint": "...", "closest_apy": 3.1, "average_apy": 3.0, "long_apy": 3.2, "usd_rate": 1 } ],
    "jupiter_lend": [ { "asset_mint": "...", "jl_token": "...", "symbol": "jlUSDC", "name": "...", "decimals": 6, "supply_rate": 5.08, "rewards_rate": 0.99, "total_apy": 6.07, "tvl": null, "liquidity": "..." } ],
    "kamino": [ { "address": "...", "name": "USDC Prime", "url": "https://kamino.com/lend/usdc-prime", "token_mint": "...", "shares_mint": "...", "apy": 6.2, "apy_7d": 0.06, "apy_30d": 0.06, "tvl": 133820000, "share_price": 1.05 } ]
  },
  "meta": { "as_of": "2026-09-09T07:15:00.000Z", "cache": "hit|miss", "engine_version": "v1" },
  "request_id": "..."
}

APY values are percentages (4.86 = 4.86%). Rates that are exact on-chain ratios are decimal strings.

GET /v1/yields/tokens/:mint

Yield options for one token, without a wallet: the same registries the wallet scan loads, ranked by the same rule the dashboard uses to pick a token's best option. Query params: min_pool_tvl (default 10000).

{
  "data": {
    "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "symbol": "USDC",
    "name": "USD Coin",
    "decimals": 6,
    "usd_price": 0.9999,
    "logo": "https://...",
    "settings": { "minPoolTvl": 10000, "minSolThreshold": 0.1, "bpsThreshold": 0.005 },
    "best": { "type": "dlmm", "apy": 306.8 },
    "links": { "meteora_dv": "https://app.meteora.ag/vaults", "dlmm": "https://app.meteora.ag/dlmm/<pool>", "damm_v2": "https://app.meteora.ag/dammv2/<pool>", "jupiter_lend": "https://jup.ag/lend/earn/USDC/deposit", "kamino": "https://kamino.com/lend/elemental-usdc-turbo", "perena": "https://app.perena.org/portfolio" },
    "meteora_dv": { "pubkey": "...", "lp_mint": "...", "closest_apy": 3.1, "average_apy": 3.0 },
    "dlmm": { "best": { "address": "...", "name": "SOL-USDC", "apy": 306.8, "liquidity": 5625978 }, "pools": [] },
    "damm_v2": { "best": null, "pools": [] },
    "damm_v1": { "best": null, "pools": [] },
    "jupiter_lend": { "jlTokenAddress": "...", "totalApy": 4.2, "supplyRate": 3.8, "rewardsRate": 0.4 },
    "kamino": { "best": { "address": "...", "name": "Elemental USDC Turbo", "url": "https://kamino.com/lend/elemental-usdc-turbo", "apy": 7.9, "tvl": 6000000 }, "vaults": [] },
    "perena": { "apy_7d": 9.37, "price": 1.0937, "mint": "star9..." },
    "the_vault": null,
    "jito": null
  },
  "meta": { "as_of": "2026-09-09T08:00:00.000Z", "engine_version": "v1" },
  "request_id": "..."
}

links is only present for protocols the token can actually use. perena is set only for USDC; the_vault and jito only for SOL. Pool and vault objects are the registry records as the dashboard uses them (camelCase for Jupiter Lend and Kamino, snake_case for Meteora).

Wallet Portfolio

API key required. Scope: portfolio:read. Every /portfolio call counts against the portfolio group windows as well as the global limits. Results for the same wallet are cached for 60 seconds (meta.cache); cached responses count like any other call.

GET /v1/wallets/:wallet/portfolio

Runs the Yieldbay dashboard engine for any Solana wallet: balances across Token and Token-2022 accounts, positions in Jito, Meteora Dynamic Vaults, DLMM, Jupiter Lend, Kamino Earn, Perena and The Vault, the best yield opportunity per token, the rebalance suggestions, and the single headline recommendation for SOL. It is the same computation the app shows, returned as JSON.

Query params (all optional, defaults are the dashboard defaults):

Response shape (token and opportunity objects mirror the app's internal model and use camelCase):

{
  "data": {
    "engine_version": "v1",
    "network": "solana:mainnet-beta",
    "wallet": "<solana-wallet>",
    "scanned_at": 1788938122456,
    "settings": { "minPoolTvl": 10000, "minSolThreshold": 0.1, "bpsThreshold": 0.005 },
    "tokens": [
      {
        "mint": "So11111111111111111111111111111111111111112",
        "symbol": "SOL",
        "name": "Wrapped SOL",
        "decimals": 9,
        "isNative": true,
        "walletBalance": 0.0064,
        "usdPrice": 104.86,
        "lpBalance": 0,
        "jupiterLendBalance": 0.0205,
        "kaminoBalance": 0,
        "dlmmBalance": 0,
        "hasDV": true, "hasDLMM": true, "hasDammV2": true, "hasDammV1": false,
        "hasJupiterLend": true, "hasKamino": true, "hasTheVault": true,
        "bestType": "dlmm",
        "apy": 278.5,
        "dlmmPair": { "address": "...", "name": "SOL-USDC", "apy": 278.5, "liquidity": 1234567 },
        "jupiterLendVault": { "jlTokenAddress": "...", "totalApy": 3.9 },
        "kaminoVault": { "address": "...", "name": "Allez SOL", "apy": 4.5 },
        "dlmmPositions": [], "kaminoPositions": []
      }
    ],
    "rates": { "jito": "1.3003", "meteora": "1.1264" },
    "growth": { "jito": "0.00082", "meteora": "0.00011" },
    "apys": { "jito": 4.86, "meteora": 0.56, "perena": 9.62, "dlmm": 278.5, "kamino": 0, "theVault": 8.18 },
    "sol_price": 104.86,
    "balances": { "sol": 0.0064, "jitoSol": 0.0079, "meteoraLp": 0, "perenaUsdStar": 0.028, "theVaultVlp": 0.0205 },
    "totals": { "total_usd": 6.48, "total_sol": 0.0618, "weighted_apy": 5.79 },
    "snapshot": { "total_usd": 6.48, "wallet_usd": 1.07, "jito_usd": 1.08, "meteora_usd": 0, "perena_usd": 0.03, "the_vault_usd": 2.14, "jupiter_lend_usd": 2.15, "dlmm_usd": 0, "kamino_usd": 0 },
    "protocol_values": { "walletUsd": 1.07, "jitoUsd": 1.08, "meteoraUsd": 0, "perenaUsd": 0.03, "theVaultUsd": 2.14, "jupiterLendUsd": 2.15, "jupiterLendPositionsCount": 1, "dlmmUsd": 0, "dlmmPositionsCount": 0, "kaminoUsd": 0, "kaminoPositionsCount": 0 },
    "active_protocols": ["Jito", "Perena", "The Vault", "Jupiter Lend"],
    "portfolio_sources": ["Wallet", "Jito", "Perena", "The Vault"],
    "opportunities": [
      { "symbol": "USDC", "opportunityType": "deposit", "action": "deposit_dlmm", "fromState": "idle", "toState": "dlmm", "currentApy": 0, "targetApy": 278.5, "apyGain": 278.5, "displayBalance": 0.39 },
      { "symbol": "JitoSOL", "opportunityType": "rebalance", "action": "rebalance_jito_to_the-vault", "fromState": "jito", "toState": "the-vault", "currentApy": 4.86, "targetApy": 8.18, "apyGain": 3.32, "displayBalance": 0.0103, "displaySymbol": "SOL" }
    ],
    "recommendation": {
      "action": "switch",
      "target": "the-vault",
      "from": "jito",
      "enabled": true,
      "label": "Switch to The Vault",
      "steps": ["unstake_jito", "deposit_the_vault"],
      "tooltip": null,
      "recommendation": "Switch 0.01 SOL: JitoSOL (4.9%) → The Vault (8.2%)"
    }
  },
  "meta": { "as_of": "2026-09-09T07:15:29.166Z", "scanned_at": "2026-09-09T07:15:22.456Z", "cache": "miss", "engine_version": "v1" },
  "request_id": "..."
}

Token objects carry the full per-token detail the dashboard uses (registry entries for the best DLMM/DAMM pool, Jupiter Lend and Kamino vault records, DLMM and Kamino position lists); the example above is abbreviated. Opportunity objects are the token object plus the fields shown.

Every token also carries links (one URL per protocol it can use, same shape as in /v1/yields/tokens/:mint), every opportunity carries links: { withdraw, deposit } (withdraw is null for idle-balance deposits; each is { url, label }), and the recommendation carries links: { from, target }. These are the exact URLs the Yieldbay dashboard buttons open.

data.health is the position-health section: incidents and recent events from the Yieldbay health monitor that touch the protocols and entities this wallet is exposed to (Jito stake pool, its Meteora vaults, Jupiter Earn vaults, Kamino vaults, the DLMM program, Perena).

{
  "health": {
    "exposure": true,
    "targets": {
      "exact": [ { "protocol": "spl_stake_pools", "entity_address": "Jito4AP...", "label": "JitoSOL" } ],
      "protocol_level": [ { "protocol": "perena", "label": "Perena USD*" } ]
    },
    "items": [
      {
        "dashboard_source": "incident",
        "id": "...", "protocol": "jupiter_earn", "entity_address": "...", "entity_name": null,
        "alert_type": "SUPPLY_DROP", "severity": "warning", "field": "tvl",
        "prev_value": "...", "curr_value": "...", "delta": -1.2, "delta_pct": -3.4,
        "timestamp": 1788938000000, "time": 1788938000000,
        "labels": { "protocol": "Jupiter Earn", "entity": "Jupiter Earn SOL", "type": "Balance dropped", "field": "TVL", "state": "Open" },
        "links": { "protocol": { "url": "https://jup.ag/lend/earn/SOL/deposit", "label": "Open earn" } }
      }
    ]
  }
}

exposure is false (with empty targets and items) when the wallet holds nothing a monitor covers. Items are sorted critical first, then newest. Incident items carry the fields of health_open_incidents; event items (dashboard_source: "event") carry the fields of the public events feed plus status.

GET /v1/wallets/:wallet/snapshots

Portfolio value history for that wallet, oldest first. A point is saved after every fresh scan, by the Yieldbay app on a dashboard load and by /v1/wallets/:wallet/portfolio on a cache miss, merged into one point per five minutes. Any wallet accumulates history from its first scan.

{
  "data": {
    "wallet": "<solana-wallet>",
    "snapshots": [
      { "timestamp": 1788938122456, "at": "2026-09-09T07:15:22.456Z", "total_usd": 6.48, "wallet_usd": 1.07, "jito_usd": 1.08, "meteora_usd": 0, "perena_usd": 0.03, "the_vault_usd": 2.14, "jupiter_lend_usd": 2.15, "dlmm_usd": 0, "kamino_usd": 0 }
    ]
  },
  "meta": { "as_of": "2026-09-09T07:15:29.166Z", "count": 1 },
  "request_id": "..."
}

API Key Self-Service

Connected-wallet access state is read-only and does not require a signature. Mutating key actions use signed Solana messages.

GET /v1/wallets/:wallet/api-access

No API key or wallet signature required. Returns the wallet's tier and effective limits, active key metadata, and current minute/month/daily-scan usage. The raw API key secret is never returned. Usage is returned once at data.usage; individual key rows do not include usage counters.

Response shape:

{
  "data": {
    "wallet": "<solana-wallet>",
    "wallet_limits": {
      "wallet": "<solana-wallet>",
      "tier": "free_beta",
      "tier_name": "Free beta",
      "scopes": ["health:read", "yields:read", "portfolio:read"],
      "rate_limit_per_minute": 60,
      "quota_per_month": 300000,
      "max_active_keys": 1,
      "group_limits": { "portfolio": { "per_minute": 2, "per_month": 300 }, "yields": { "per_minute": 30 }, "snapshots": { "per_minute": 30 } },
      "overrides": null,
      "created_at": "2026-04-25T10:00:00.000Z",
      "updated_at": "2026-04-25T10:00:00.000Z"
    },
    "usage": {
      "minute": { "scope": "wallet", "used": 0, "limit": 60, "remaining": 60, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" },
      "month": { "scope": "wallet", "used": 0, "limit": 300000, "remaining": 300000, "rate_limited": 0, "period_start": "2026-04-25T10:00:00.000Z", "reset_at": "2026-05-25T10:00:00.000Z" },
      "groups": {
        "portfolio": {
          "minute": { "scope": "wallet", "used": 0, "limit": 2, "remaining": 2, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" },
          "month": { "scope": "wallet", "used": 0, "limit": 300, "remaining": 300, "rate_limited": 0, "period_start": "2026-04-25T10:00:00.000Z", "reset_at": "2026-05-25T10:00:00.000Z" }
        },
        "yields": { "minute": { "scope": "wallet", "used": 0, "limit": 30, "remaining": 30, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" } },
        "snapshots": { "minute": { "scope": "wallet", "used": 0, "limit": 30, "remaining": 30, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" } }
      }
    },
    "active_key": {
      "key_id": "ak...",
      "wallet": "<solana-wallet>",
      "label": "Yieldbay API",
      "scopes": ["health:read"],
      "status": "active",
      "allowed_origins": [],
      "origin_required": false,
      "wallet_limits": {
        "wallet": "<solana-wallet>",
        "tier": "free_beta",
        "tier_name": "Free beta",
        "scopes": ["health:read", "yields:read", "portfolio:read"],
        "rate_limit_per_minute": 60,
        "quota_per_month": 300000,
        "max_active_keys": 1,
        "group_limits": { "portfolio": { "per_minute": 2, "per_month": 300 }, "yields": { "per_minute": 30 }, "snapshots": { "per_minute": 30 } },
        "overrides": null,
        "created_at": "2026-04-25T10:00:00.000Z",
        "updated_at": "2026-04-25T10:00:00.000Z"
      },
      "created_at": "2026-04-25T10:00:00.000Z",
      "expires_at": null,
      "revoked_at": null,
      "last_used_at": null,
      "last_origin": null,
      "username": null,
      "nft_address": null,
      "source": null
    },
    "keys": []
  },
  "meta": { "as_of": "2026-04-25T10:00:00.000Z" },
  "request_id": "..."
}

For create, rotate, and revoke: first request a nonce, sign the returned message, then submit the signed payload.

POST /v1/auth/nonce

No API key required.

Body:

{ "wallet": "<solana-wallet>", "action": "create_api_key|rotate_api_key|revoke_api_key", "resource": "ak..." }

resource is omitted or null for create_api_key; it is required for rotate_api_key and revoke_api_key.

Response:

{
  "data": {
    "wallet": "<solana-wallet>",
    "action": "create_api_key",
    "resource": null,
    "nonce": "...",
    "message": "Yieldbay API key request\nWallet: ...",
    "expires_at": "2026-04-25T10:05:00.000Z"
  },
  "request_id": "..."
}

POST /v1/me/api-keys

Create a key for the signing wallet.

Body:

{
  "wallet": "<solana-wallet>",
  "nonce": "...",
  "message": "...",
  "signature": "...",
  "label": "Production monitor",
  "scopes": ["health:read"],
  "allowed_origins": ["https://example.com"],
  "origin_required": false,
  "expires_at": 1777098000000
}

scopes may be any subset of health:read, yields:read, portfolio:read; when omitted the key gets all three. expires_at is optional and must be a future millisecond timestamp. The raw key is returned only in the create response. Store it securely. If it is lost, rotate the key.

Response:

{
  "data": {
    "key": "yb_live_ak...<secret>",
    "key_id": "ak...",
    "wallet": "<solana-wallet>",
    "label": "Production monitor",
    "scopes": ["health:read"],
    "status": "active",
    "wallet_limits": {
      "wallet": "<solana-wallet>",
      "tier": "free_beta",
      "tier_name": "Free beta",
      "scopes": ["health:read", "yields:read", "portfolio:read"],
      "rate_limit_per_minute": 60,
      "quota_per_month": 300000,
      "max_active_keys": 1,
      "group_limits": { "portfolio": { "per_minute": 2, "per_month": 300 }, "yields": { "per_minute": 30 }, "snapshots": { "per_minute": 30 } },
      "overrides": null,
      "created_at": "2026-04-25T10:00:00.000Z",
      "updated_at": "2026-04-25T10:00:00.000Z"
    },
    "allowed_origins": ["https://example.com"],
    "origin_required": false,
    "created_at": "2026-04-25T10:00:00.000Z",
    "expires_at": null,
    "wallet_usage": {
      "minute": { "scope": "wallet", "used": 0, "limit": 60, "remaining": 60, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" },
      "month": { "scope": "wallet", "used": 0, "limit": 300000, "remaining": 300000, "rate_limited": 0, "period_start": "2026-04-25T10:00:00.000Z", "reset_at": "2026-05-25T10:00:00.000Z" },
      "groups": {
        "portfolio": {
          "minute": { "scope": "wallet", "used": 0, "limit": 2, "remaining": 2, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" },
          "month": { "scope": "wallet", "used": 0, "limit": 300, "remaining": 300, "rate_limited": 0, "period_start": "2026-04-25T10:00:00.000Z", "reset_at": "2026-05-25T10:00:00.000Z" }
        },
        "yields": { "minute": { "scope": "wallet", "used": 0, "limit": 30, "remaining": 30, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" } },
        "snapshots": { "minute": { "scope": "wallet", "used": 0, "limit": 30, "remaining": 30, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" } }
      }
    },
    "warning": "Copy this key now and store it securely. If it is lost, rotate the key from the Yieldbay app."
  },
  "request_id": "..."
}

POST /v1/me/api-keys/:keyId/rotate

Revokes one active key owned by the signing wallet and returns a new raw key. This requires a fresh signed nonce with action = "rotate_api_key" and resource = keyId. The new key is issued with every scope (like a freshly created key), so rotating is how a key created before newer scopes existed picks them up; the wallet's tier still decides what each request may use. Label, allowed origins and expiry carry over unless the body overrides them. The response also includes wallet_usage for the owning wallet. The request body is the same signed payload as create. Optional key settings follow create semantics. Response shape is the same as create and adds rotated_from.

POST /v1/me/api-keys/:keyId/revoke

Revokes one key owned by the signing wallet. The request body must include wallet, nonce, message, and signature for action = "revoke_api_key" and resource = keyId.

Response:

{
  "data": { "key_id": "ak...", "revoked": true },
  "request_id": "..."
}

Authenticated Usage

GET /v1/me/usage

API key required. The key authenticates the wallet, then the endpoint returns wallet-level limits, current wallet-scoped minute/month usage, wallet-level rollup totals, and metadata for the authenticated key. It does not return key-scoped usage totals.

Query params:

Response:

{
  "data": {
    "wallet": "<solana-wallet>",
    "wallet_limits": {
      "wallet": "<solana-wallet>",
      "tier": "free_beta",
      "tier_name": "Free beta",
      "scopes": ["health:read", "yields:read", "portfolio:read"],
      "rate_limit_per_minute": 60,
      "quota_per_month": 300000,
      "max_active_keys": 1,
      "group_limits": { "portfolio": { "per_minute": 2, "per_month": 300 }, "yields": { "per_minute": 30 }, "snapshots": { "per_minute": 30 } },
      "overrides": null,
      "created_at": "2026-04-25T10:00:00.000Z",
      "updated_at": "2026-04-25T10:00:00.000Z"
    },
    "usage": {
      "minute": { "scope": "wallet", "used": 1, "limit": 60, "remaining": 59, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" },
      "month": { "scope": "wallet", "used": 10, "limit": 300000, "remaining": 299990, "rate_limited": 0, "period_start": "2026-04-25T10:00:00.000Z", "reset_at": "2026-05-25T10:00:00.000Z" },
      "groups": {
        "portfolio": {
          "minute": { "scope": "wallet", "used": 1, "limit": 2, "remaining": 1, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" },
          "month": { "scope": "wallet", "used": 2, "limit": 300, "remaining": 298, "rate_limited": 0, "period_start": "2026-04-25T10:00:00.000Z", "reset_at": "2026-05-25T10:00:00.000Z" }
        },
        "yields": { "minute": { "scope": "wallet", "used": 0, "limit": 30, "remaining": 30, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" } },
        "snapshots": { "minute": { "scope": "wallet", "used": 0, "limit": 30, "remaining": 30, "rate_limited": 0, "reset_at": "2026-04-25T10:01:00.000Z" } }
      }
    },
    "totals": [
      {
        "period_start_ms": 1777065600000,
        "period_start": "2026-04-25T00:00:00.000Z",
        "granularity": "day",
        "request_count": 10,
        "error_count": 0,
        "rate_limited_count": 0,
        "duration_ms_avg": 120,
        "duration_ms_max": 350,
        "response_bytes_sum": 4096
      }
    ],
    "authenticated_key": {
      "key_id": "ak...",
      "wallet": "<solana-wallet>",
      "label": "Yieldbay API",
      "scopes": ["health:read"],
      "status": "active",
      "allowed_origins": [],
      "origin_required": false,
      "wallet_limits": {
        "wallet": "<solana-wallet>",
        "tier": "free_beta",
        "tier_name": "Free beta",
        "scopes": ["health:read", "yields:read", "portfolio:read"],
        "rate_limit_per_minute": 60,
        "quota_per_month": 300000,
        "max_active_keys": 1,
        "group_limits": { "portfolio": { "per_minute": 2, "per_month": 300 }, "yields": { "per_minute": 30 }, "snapshots": { "per_minute": 30 } },
        "overrides": null,
        "created_at": "2026-04-25T10:00:00.000Z",
        "updated_at": "2026-04-25T10:00:00.000Z"
      },
      "created_at": "2026-04-25T10:00:00.000Z",
      "expires_at": null,
      "revoked_at": null,
      "last_used_at": "2026-04-25T10:00:30.000Z",
      "last_origin": null,
      "username": null,
      "nft_address": null,
      "source": null
    }
  },
  "meta": { "as_of": "2026-04-25T10:00:30.000Z" },
  "request_id": "..."
}