KeyBay KeyBay Capital Bitcoin L1 Yield Launch App
Products KBY Token Docs Security Blog Team Launch App
Developer Reference · KeyBay Capital

s402 Developer Docs

Agent access to Bitcoin DeFi infrastructure. Protocol specification, SDK reference, paid endpoint catalog, payment flow, and error codes for the KeyBay s402 integration layer.

Overview

s402 is an HTTP 402-based protocol for machine-to-machine access to Bitcoin DeFi infrastructure. When an agent or automated client requests a paid resource, the server responds with HTTP 402 Payment Required along with headers describing the payment terms. The client settles the payment on Bitcoin, then retries the request with a proof-of-payment header to receive the data.

KeyBay Capital implements s402 as its primary agent access layer. The current production surface is centered on s402, with x402, L402, and OP_NET-native payment flows planned as future expansions. Agents, LLM tool-use integrations, and automated trading systems can consume vault data, oracle prices, and credit parameters without browser sessions or API keys — payment is the authentication.

Design Principles

  • Payment is auth — No API keys, no OAuth tokens. A valid Bitcoin payment is the only credential required.
  • Extensible — The current rollout uses s402, and the endpoint surface is designed to add more payment proofs over time.
  • Satoshi-denominated — All prices are quoted in satoshis. Sub-cent micropayments are first-class.
  • Stateless — Each request is independently verifiable. No session state, no cookies, no rate-limit counters.

Quick Start

Install the SDK

npm install @keybay/sdk

SDK Usage

import { KeyBay } from "@keybay/sdk";

const kb = new KeyBay({ apiBaseUrl: "https://api.keybaycapital.com" });

// Yield vault summary
const summary = await kb.vault.getSummary();
if (summary.ok) {
  console.log("Total active:", summary.data.totalActiveSats, "sats");
  console.log("Depositors:", summary.data.depositorCount);
}

// Credit risk parameters
const rates = kb.credit.getRiskParameters();
console.log("Max LTV:", rates.maxLtvBps, "bps");      // 4000n (40%)
console.log("Interest:", rates.interestRateBps, "bps"); // 1000n (10% APR)

Agent Access via cURL

Agents interact with paid endpoints directly over HTTP. The first request returns 402 with payment instructions. After paying, the agent retries with the proof-of-payment header.

# Step 1: Request the resource (receives 402)
curl -i https://api.keybaycapital.com/api/s402/oracle/price

# HTTP/1.1 402 Payment Required
# X-Payment-Required: true
# X-Payment-Amount: 10
# X-Payment-Currency: sats
# X-Payment-Address: bc1q...treasury
# X-Payment-Protocol: s402

# Step 2: Pay and retry with proof
curl -H "X-Payment: s402:<tx_id>:10:<signature>" \
     https://api.keybaycapital.com/api/s402/oracle/price

# HTTP/1.1 200 OK
# { "price_usd_cents": 9402000, "block": 887421, "stale": false }

Pricing Tiers

KeyBay s402 uses a 3-tier pricing model. All prices are environment-variable driven and denominated in satoshis. s402 revenue is additive to primary vault/lending revenue.

Tier 1 — Free (Rate Limited)

Basic vault, oracle, and credit data. Rate limited to 10 requests per minute per IP. On 429, the response includes an s402 upsell with a link to the paid discovery endpoint.

Endpoint Price Description
/api/public/vault/summary Free Basic vault TVL, deposit count, APY, and network status.
/api/public/oracle/price Free Live BTC/USD price snapshot.
/api/public/credit/params Free Credit engine parameters: max LTV, liquidation LTV, interest rate.

Tier 2 — Paid (s402 Micropayment)

Full data access via s402 payment. Prices are set via environment variables (format: S402_PRICE_*) and auto-convert to satoshis using the live BTC/USD rate. All paid endpoints follow the same 402 handshake.

Endpoint Price (USD) Env Var Description
/api/s402/oracle/price $0.01 S402_PRICE_ORACLE_PRICE Live BTC/USD oracle price with staleness indicator.
/api/s402/oracle/history $0.01 S402_PRICE_ORACLE_HISTORY 24h historical BTC/USD oracle snapshots.
/api/s402/vault/stats $0.02 S402_PRICE_VAULT_STATS Vault TVL, depositor count, APY, exchange rate.
/api/s402/vault/performance $0.05 * S402_PRICE_VAULT_PERFORMANCE Historical performance: yield, Sharpe ratio, drawdowns.
/api/s402/vault/allocation $0.02 S402_PRICE_VAULT_ALLOCATION Current vault allocation breakdown by strategy.
/api/s402/vault/reserves $0.05 S402_PRICE_VAULT_RESERVES Reserve proof and solvency data.
/api/s402/credit/rates $0.01 S402_PRICE_CREDIT_RATES Credit vault interest rates and risk parameters.
/api/s402/credit/positions $0.02 S402_PRICE_CREDIT_POSITIONS Aggregate credit vault positions and system LTV.
/api/s402/credit/liquidations $0.10 * S402_PRICE_CREDIT_LIQUIDATIONS Liquidation events: trigger prices, penalties, recovery.
/api/s402/credit/simulate $0.02 S402_PRICE_CREDIT_SIMULATE Credit vault simulation: LTV, interest, liquidation scenarios.
/api/s402/yield/calculator $0.01 S402_PRICE_YIELD_CALCULATOR Yield projection calculator by strategy and duration.

* Endpoints marked with asterisk (*) are never free and cannot be bypassed via Tier 3 premium deposit status. Vault performance and liquidation data represent the highest-value intelligence feeds.

Tier 3 — Premium Deposit Bypass

Vault depositors with 0.01+ BTC deposited in KeyBay receive free access to all Tier 2 endpoints (except those marked as never-free). Include your depositor address in the X-Keybay-Address header. Deposit status is cached for 5 minutes.

# Premium bypass — no payment required if you have 0.01+ BTC deposited
curl -H "X-Keybay-Address: bc1q...your_depositor_address" \
     https://api.keybaycapital.com/api/s402/vault/stats

# HTTP/1.1 200 OK
# { "totalValueLockedBtc": "12.34567890", "_tier": "premium", ... }

# Never-free endpoints still require payment even for depositors:
# /api/s402/vault/performance ($0.05)
# /api/s402/credit/liquidations ($0.10)

Payment Flow

The s402 payment flow is a two-step HTTP handshake. Every paid endpoint follows the same pattern:

  1. GET the endpoint — The server responds with HTTP 402 Payment Required. Response headers include X-Payment-Amount (satoshis), X-Payment-Address (treasury Bitcoin address), and X-Payment-Protocol (s402 in the current rollout).
  2. Parse payment instructions — The response body contains a JSON object with the same payment parameters plus a human-readable description of the resource being purchased.
  3. Send payment — Transfer the required satoshi amount to the treasury address via any Bitcoin payment method (on-chain, Lightning, or OP_NET).
  4. Retry with proof — Re-send the original GET request with the X-Payment header containing the payment proof.
  5. Receive data — The server validates the payment proof and returns HTTP 200 with the requested data.

X-Payment Header Format

X-Payment: s402:<tx_id>:<amount_sats>:<signature>

# Fields:
#   s402         Protocol identifier used by the current rollout
#   tx_id        Bitcoin transaction ID (hex, 64 chars)
#   amount_sats  Amount paid in satoshis (must match or exceed required amount)
#   signature    Signature proving ownership of the paying address

402 Response Example

HTTP/1.1 402 Payment Required
Content-Type: application/json
X-Payment-Required: true
X-Payment-Amount: 10
X-Payment-Currency: sats
X-Payment-Address: bc1q...treasury
X-Payment-Protocol: s402

{
  "error": "payment_required",
  "amount": 10,
  "currency": "sats",
  "address": "bc1q...treasury",
  "protocol": "s402",
  "description": "Live BTC/USD oracle price",
  "endpoint": "/api/s402/oracle/price"
}

SDK Reference

The @keybay/sdk package provides typed access to vault and credit operations. All public methods return Result<T> — the SDK never throws.

Core Classes

  • KeyBay — Main entry point. Instantiate with { apiBaseUrl }. Provides .vault (VaultClient) and .credit (CreditClient) accessors, plus static KeyBay.utils for pure computation.
  • VaultClient — Yield vault operations: getSummary(), getPosition(address), getOraclePrice(), getHealth(), getActivity(limit), getStablecoinRegistry(), validateDeposit(sats).
  • CreditClient — Credit vault operations: getVaults(address), getVault(id, address), openVault(...), repay(...), getMaxBorrow(...), getLTV(...), getLiquidationPrice(...), getLiquidationInfo(...), getPendingInterest(...), getRiskParameters().

Utility Functions

Available via KeyBay.utils or as named imports. All functions are pure — no side effects, no network calls.

  • Amount conversionbtcToSats(str), satsToBtcString(sats), usdToCents(str), centsToUsdString(cents)
  • BPS conversionbpsToPercentString(bps), percentToBps(str)
  • Exchange ratecalculateShares(btcSats, rate), sharesToBtc(shares, rate)
  • LTV mathcalculateLTV(collateral, debt, price), calculateLiquidationPrice(collateral, debt), calculateMaxBorrow(collateral, price, existingDebt)
  • Interest & liquidationcalculateAccruedInterest(debt, blocks), calculateLiquidationPenalty(collateral), calculateSeizedCollateral(collateral, debt, price)
  • ValidationisValidBitcoinAddress(addr), validateDepositAmount(sats), validateCollateralAmount(sats), validateRail(rail)
  • FormattingformatBtc(sats), formatUsd(cents), formatLtv(bps)

Amount Conventions

All amounts use bigint. There are no floating-point values in any public API surface.

  • BTC — satoshis (1 BTC = 100,000,000n)
  • USD — cents ($1.00 = 100n)
  • BPS — basis points (1% = 100n, 100% = 10,000n)
  • Exchange rate — 8 decimal places (1:1 = 100,000,000n)

Result<T> Pattern

The SDK never throws exceptions. All public methods that can fail return Result<T>, which is a discriminated union:

type Result<T> =
  | { ok: true;  data: T }
  | { ok: false; error: KeyBayError };

// Usage:
const result = await kb.vault.getSummary();
if (result.ok) {
  console.log(result.data.totalActiveSats);
} else {
  console.error(result.error.code, result.error.message);
}

Contract Registry

The contract registry endpoint returns live contract addresses and status for all deployed OP_NET contracts. This is a free (unpaid) endpoint.

GET /api/contracts.json

{
  "network": "mainnet",
  "lastUpdated": "2025-06-15T00:00:00Z",
  "contracts": [
    { "name": "KeyBayVault", "address": "bc1q...", "status": "active", "dataSource": "config" },
    { "name": "CreditVault", "address": "bc1q...", "status": "active", "dataSource": "config" },
    { "name": "Oracle",      "address": "bc1q...", "status": "active", "dataSource": "config" },
    { "name": "kbBTC",       "address": "bc1q...", "status": "active", "dataSource": "config" },
    { "name": "WithdrawalQueue", "address": "bc1q...", "status": "active", "dataSource": "config" },
    { "name": "ReserveProof",    "address": "bc1q...", "status": "undeployed", "dataSource": "config" }
  ],
  "stablecoinRails": [
    { "id": "op20s", "name": "OP_20S (L1)", "railType": 0, "active": false, "tokens": [] },
    { "id": "taproot-usdt", "name": "Taproot USDT (Lightning)", "railType": 1, "active": true, "tokens": ["USDT"] }
  ]
}

Use the SDK helper functions to consume this data programmatically:

import { fetchContractRegistry, extractAddresses } from "@keybay/sdk";

const config = { apiBaseUrl: "https://api.keybaycapital.com" };
const registry = await fetchContractRegistry(config);

if (registry.ok) {
  const addrs = extractAddresses(registry.data);
  console.log("Vault:", addrs.keyBayVault);
  console.log("Credit:", addrs.creditVault);
  console.log("Oracle:", addrs.oracle);
}

Each contract entry includes a status field: active (deployed and operational), paused (deployed but temporarily halted), or undeployed (address reserved, contract not yet on-chain). The dataSource field indicates whether the address comes from static configuration or was resolved from the chain.

Error Codes

All errors returned by the SDK use the KeyBayErrorCode enum. The error object includes a machine-readable code, a human-readable message, and an optional details field.

Code Category Description
NETWORK_ERROR Network HTTP request failed (DNS, connection refused, etc.)
RPC_UNAVAILABLE Network OP_NET RPC node is unreachable.
RPC_TIMEOUT Network Request exceeded timeout (default 30s).
VAULT_PAUSED Vault Vault operations are temporarily paused by the operator.
BELOW_MINIMUM_DEPOSIT Vault Deposit amount is below the minimum (10,000 sats for vault, 50,000 sats for credit).
INSUFFICIENT_BALANCE Vault Insufficient BTC balance for the requested operation.
INSUFFICIENT_SHARES Vault Insufficient kbBTC shares for withdrawal.
VAULT_NOT_CONFIGURED Vault Vault contract has not been initialized by the operator.
LTV_EXCEEDED Credit Borrow would push LTV above the 40% maximum.
BELOW_LIQUIDATION_THRESHOLD Credit Position LTV has reached the 50% liquidation threshold.
NO_COLLATERAL Credit No collateral deposited for this address.
OUTSTANDING_DEBT Credit Cannot withdraw collateral while debt is outstanding.
POSITION_LIQUIDATED Credit Position has already been liquidated.
NO_ACTIVE_LOAN Credit No active loan exists for this address.
ORACLE_STALE Oracle Oracle price has not been updated within 6 blocks.
ORACLE_PRICE_ZERO Oracle Oracle returned a zero price (not initialized).
ORACLE_NOT_CONFIGURED Oracle Oracle contract address not set in configuration.
INVALID_ADDRESS Validation Bitcoin address format is invalid.
INVALID_AMOUNT Validation Amount string is malformed or negative.
INVALID_RAIL Validation Unknown stablecoin rail type (must be 0 or 1).
API_ERROR API Server returned a non-2xx status code.
NOT_FOUND API Requested resource does not exist (HTTP 404).
UNAUTHORIZED API Payment proof invalid or insufficient (HTTP 403).
CONTRACT_REVERT Contract OP_NET smart contract call reverted.
TRANSACTION_FAILED Contract Bitcoin transaction failed to broadcast or confirm.
SDK_NOT_CONFIGURED Config SDK was instantiated without a required config field (e.g., missing apiBaseUrl).