Elysium mainnet launches November 9. Pours open at launch; until then the home page runs a preview with no real HYPE.

SPOUT
Developer API

The same live data, over REST.

The public API serves exactly what the app renders: every pour, tap, receipt and risk score, straight from the SPOUT ledger and the chain. It is read only, needs no key and returns JSON.

base url
https://usespout.com/api/v1

Conventions

Amounts

Fields ending in _hype are decimal strings in whole HYPE so no precision is lost. Settlement objects carry raw wei strings. Rates are percent. Times are unix seconds of chain time.

Pagination

List endpoints take limit (1 to 100) and return next_cursor. Pass it back as cursor for the next page; null means you have everything.

Rate limits

120 requests per minute per IP (30 for the risk endpoint). Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset.

Caching

Live endpoints are cached for 3 seconds at the edge. Poll no faster than that; the keeper ticks every few seconds anyway.

GET/pours

Every pour, newest first by default.

ParameterInDescription
statusqueryfunding, filling, flowing, settling, spring, ended, shutoff, cancelled, or live (the first four)
tokenqueryToken address
projectqueryProject wallet
sortquerynewest, oldest, water_line, flow_rate, ending
limitquery1 to 100, default 20
cursorquerynext_cursor from the previous page
curl -s "https://usespout.com/api/v1/pours?status=filling&sort=flow_rate&limit=10"
Response
typescript
{ data: Pour[]; next_cursor: string | null }
GET/pours/{id}

One pour with its latest receipts and tick depth readings.

ParameterInDescription
idpathPour id, 10 hex characters
curl -s "https://usespout.com/api/v1/pours/$POUR_ID"
Response
typescript
{
  data: Pour
  events: { at: number; kind: string; message: string; tx_hash: string | null }[]   // newest first, up to 50
  depth: { at: number; price_hype: number; twap_hype: number; spout_hype: number; organic_hype: number }[]   // one per minute, up to 288
}
GET/pours/{id}/taps

Every tap in one pour, oldest first.

ParameterInDescription
idpathPour id
curl -s "https://usespout.com/api/v1/pours/$POUR_ID/taps"
Response
typescript
{ data: Tap[] }
GET/taps?owner={address}

Every tap a wallet opened, across pours, newest first.

ParameterInDescription
ownerqueryWallet address, required
limitquery1 to 100, default 50
cursorqueryPagination cursor
curl -s "https://usespout.com/api/v1/taps?owner=$WALLET"
Response
typescript
{ data: (Tap & { pour: { id: string; status: string; token_symbol: string; token: string; ends_at: number | null } })[]; next_cursor: string | null }
GET/stats

Protocol totals, the same numbers the board shows.

curl -s "https://usespout.com/api/v1/stats"
Response
typescript
{ data: {
  pours: { live: number; flowing: number; filling: number; springs: number; shutoffs: number; ended: number; total: number }
  hype_flowing: string; reserve_tanks_hype: string; paid_to_taps_hype: string
  unique_lps: number; rent_per_second_hype: number; at: number
} }
GET/tokens/{address}/risk

Eligibility and the live risk score for any token. If the token has a pour, its own terms are used. Rate limited to 30 requests a minute because it reads the chain.

ParameterInDescription
addresspathToken address
reserve_pctqueryCover to score against when there is no pour, default 15
water_linequeryHYPE water line to score against, default 500
curl -s "https://usespout.com/api/v1/tokens/$TOKEN/risk?reserve_pct=20&water_line=300"
Response
typescript
{ data: {
  token: { address: string; name?: string; symbol?: string; decimals?: number; total_supply?: string }
  eligible: boolean
  reasons: string[]
  launchpad: { name: string; factory: string; creation_tx: string; deployer: string } | null
  risk: Risk | null
  pour_id: string | null
} }

type Risk = {
  score: number                 // 0 safest, 100 riskiest
  grade: "Low" | "Medium" | "High"
  factors: { key: "cover" | "holders" | "launchpad" | "dev" | "history"; label: string; value: string; points: number; note: string }[]
  computedAt: number
}

Types

typescript
type Pour = {
  id: string                    // 10 hex characters
  status: "funding" | "filling" | "flowing" | "settling" | "spring" | "ended" | "shutoff" | "cancelled"
  status_label: string
  end_reason: string | null     // spring, mains, term, floor, fault_dump, fault_supply, fault_token_pulled, cancelled
  token: { address: string; symbol: string; name: string; decimals: number; launchpad: string }
  project: string               // project wallet
  venue: "uniswap-v3" | "hybra-cl"
  pool: string
  pool_key: number              // fee tier or tick spacing
  vault: string                 // the pour's vault wallet
  water_line_hype: string       // decimal string, 18 decimals of precision
  filled_hype: string
  fill_ratio: number            // filled / water line
  taps: number
  band_pct: number
  term_days: number
  spring_target_hype: string
  flow_rate_apr: number         // percent, current (rising while filling, locked after)
  start_apr: number
  max_apr: number
  clearing_apr: number | null
  meter: { hype_per_second: number; rent_streamed_hype: string; rent_streamed_net_hype: string }
  rent_prepaid_hype: string
  reserve_tank_hype: string
  cover_ratio: number
  token_side: string
  listing_fee_hype: string
  gas_deposit_hype: string
  protocol_rent_cut: number
  floor_pct: number
  open_price_hype: number | null   // HYPE per token when flow started
  floor_price_hype: number | null
  spring_since: number | null      // unix seconds organic depth first held the target
  spring_hold_secs: number
  risk: Risk | null
  times: { created_at: number; funded_at: number | null; fill_ends_at: number | null;
           flow_started_at: number | null; ends_at: number | null; ended_at: number | null }
  settlement: Settlement | null
  keeper: { last_tick_at: number | null; last_error: string | null }
}
typescript
type Tap = {
  id: string
  pour_id: string
  owner: string
  status: "queued" | "flowing" | "closed" | "refunded"
  principal_hype: string
  deposit_tx: string
  position: { token_id: string; tick_lower: number; tick_upper: number; liquidity: string } | null
  rent_earned_hype: string         // net of the protocol share
  rent_paid_hype: string
  rent_per_second_hype: number
  flow_rate_apr: number | null
  settlement: {                     // wei strings, set once the pour closes
    principal: string; hypeBack: string; tokenBack: string; feesHype: string; feesToken: string
    valueHype: string; loss: string; rentNet: string; bonus: string; cover: string
    payHype: string; payToken: string
  } | null
  created_at: number
}

Errors

Every error has the same envelope.

json
{ "error": { "code": "not_found", "message": "No pour with id 0a1b2c3d4e" } }
StatusCodeMeaning
400invalid_parameterA query or path value is missing or malformed
401unauthorizedThe request needs a signed in wallet
404not_foundNo pour, tap or token with that id
422deposit_rejected, not_eligibleThe chain says no: wrong recipient, reverted, or the token fails eligibility
429rate_limitedToo many requests; wait for X-RateLimit-Reset
503chain_unavailableThe deployment cannot reach Elysium right now