---
title: "Token depth / price impact (per pool)"
method: GET
path: "/tokens/{mint}/depth"
tags: ["Tokens"]
---

# Token depth / price impact (per pool)

`GET /tokens/{mint}/depth`

## Request

- Base URL: `https://madeonsol.com/api/v1`
- URL: `https://madeonsol.com/api/v1/tokens/{mint}/depth`
- Auth: HTTP bearer

Per-pool **price-impact / slippage** — "how much SOL to move price N%" and the impact + tokens received for each buy size. For every pool: `spot_price_sol`, `quotes[]` per requested SOL size (`tokens_out`, `avg_price_sol`, `price_impact_pct`), and `to_move_price` (SOL to move price 1%/5%/10%). Exact for constant-product AMMs (PumpSwap, Raydium v4/CPMM, Meteora DAMM — served from streamed reserves, `source: "stream"`); pump.fun / bonk bonding curves priced from one live read of the curve's virtual reserves (`source: "live_rpc"`). Impact is per-pool, not router-optimal; concentrated-liquidity pools (Raydium CLMM, Orca, Meteora DLMM) and unclassified pools return under `unsupported_pools[]` with a `reason` instead of a wrong number. **Concentrated depth models (rollout behind server flags, off by default):** when enabled, Meteora DLMM pools are quoted with the program's own integer bin math from one same-slot snapshot of the pair and a bounded bin-array window (`model: "concentrated"`, `model_detail: "meteora_dlmm_bins"`, `fee_basis: "dynamic_fee_at_quote_time"`, `bins_window`), at most 3 DLMM pools per request; Raydium CLMM pools likewise with the program's own integer tick math (Q64.64 sqrt price, tick arrays, AmmConfig trade fee) from one same-slot snapshot of the pool, its config and the tick arrays in the buy direction (`model_detail: "raydium_clmm_ticks"`, `fee_basis: "amm_config_at_quote_time"`, `ticks_window`), at most 3 CLMM pools per request; Meteora DAMM v2 pools get a number only when their Pool account is proven and full-range (`model_detail: "meteora_damm_v2_full_range"`, `pool_account`, fee = the venue default, not the pool's own fee schedule), otherwise they return under `unsupported_pools[]` with a `damm_v2_*` reason, never a generic constant-product number; a size that would cross past the loaded ticks has `status: "exceeds_loaded_ticks"`; every quote then carries a `status`, and a size the loaded window cannot fill has `status: "exceeds_loaded_bins"` with null numbers (never a constant-product fallback). The response then also carries `pool_selection` (largest known pool vs the pool depth is reported for; `routing: "single_pool_only"`, multi-pool routing is not computed). PRO+.

## Path parameters

- `mint` string, required

## Query parameters

- `sizes` string

## Response `200`

OK

- object
  - `mint` string
  - `found` boolean: false = no depth-computable pool (pools may still appear in unsupported_pools)
  - `sol_usd` number, nullable
  - `sizes_sol` number[]
  - `primary_pool` string, nullable: Deepest depth-available pool
  - `pools` object[]
    - `pool_address` string
    - `dex` string
    - `quote_mint` string
    - `pool_model` string: constant_product | curve
    - `liquidity_usd` number, nullable
    - `is_active` boolean
    - `depth_available` boolean
    - `model` string: constant_product | curve | concentrated (concentrated only with a concentrated depth model enabled)
    - `model_detail` 'meteora_dlmm_bins' | 'raydium_clmm_ticks' | 'meteora_damm_v2_full_range': Which program-exact model produced the numbers: concentrated pools (DLMM bins, CLMM ticks), or meteora_damm_v2_full_range = a Meteora DAMM v2 pool whose Pool account is proven (owner, layout, vault) and full-range, quoted constant-product (Meteora DAMM v2 model enabled).
    - `pool_account` string: Meteora DAMM v2 only (model_detail meteora_damm_v2_full_range): the proven DAMM v2 Pool account. pool_address is the token vault.
    - `fee_pct` number: Swap fee, %. Meteora DLMM: base + variable fee at quote time (fee_basis).
    - `fee_basis` 'observed_event' | 'dynamic_fee_at_quote_time' | 'amm_config_at_quote_time': observed_event = PumpSwap fee observed on the pool's swap events (virtual-reserve model); dynamic_fee_at_quote_time = Meteora DLMM base + variable fee with the reference decayed to the quote time; amm_config_at_quote_time = Raydium CLMM trade fee read from the pool's AmmConfig in the same snapshot. Absent = the venue's static fee.
    - `bins_window` object: Meteora DLMM only: the bin range loaded in the snapshot and its slot. Quotes never walk outside it.
      - `from_bin` integer
      - `to_bin` integer
      - `slot` integer
    - `ticks_window` object: Raydium CLMM only: the loaded tick range [from_tick, to_tick) in the buy direction (the current tick array plus 4) and its slot. Quotes never cross a tick outside it.
      - `from_tick` integer
      - `to_tick` integer
      - `slot` integer
    - `source` string: stream (DB reserves) | live_rpc (curve virtual reserves)
    - `reserves_age_ms` number
    - `spot_price_sol` number
    - `quotes` object[]
      - `size_sol` number
      - `status` 'filled' | 'pool_liquidity_exhausted' | 'exceeds_loaded_bins' | 'exceeds_loaded_ticks' | 'price_out_of_range': Concentrated models only. filled = fully quoted; pool_liquidity_exhausted = the pool's own liquidity range ends first (partial fill reported); exceeds_loaded_bins (DLMM) / exceeds_loaded_ticks (CLMM) = the size needs liquidity outside the loaded window (numbers null); price_out_of_range = the program's price math is undefined there (numbers null).
      - `available` boolean: Concentrated models only. true = the whole size fills inside the loaded window with output > 0; false = this size has no usable quote (see status). A pool is listed here only when at least one requested size is available; a concentrated pool where no size is available is under unsupported_pools[] (dlmm_insufficient_liquidity_in_loaded_bins / clmm_insufficient_liquidity_in_loaded_ticks).
      - `fillable_up_to_sol` number, nullable: Meteora DLMM, unavailable sizes only: SOL input (incl. fees) the loaded bins can absorb before the walk stops. null when available.
      - `tokens_out` number, nullable: null when status is exceeds_loaded_bins or price_out_of_range
      - `avg_price_sol` number, nullable
      - `price_impact_pct` number, nullable
    - `to_move_price` object
      - `1pct` number, nullable: SOL to move price +1% (null on a concentrated pool when the loaded window does not reach that price, or when no liquidity lies between the current and the target price: a move is never reported as costing 0)
      - `5pct` number, nullable
      - `10pct` number, nullable
  - `universe` object: Only the deepest max_pools pools by stored liquidity are evaluated (audit F19); pools past that cut are not listed. truncated=true = the cut dropped pools.
    - `kind` 'top_by_liquidity'
    - `max_pools` integer
    - `evaluated` integer
    - `truncated` boolean
  - `unsupported_pools` object[]
    - `pool_address` string
    - `dex` string
    - `quote_mint` string
    - `pool_model` string, nullable
    - `liquidity_usd` number, nullable
    - `is_active` boolean
    - `fillable_up_to_sol` number: With reason dlmm_insufficient_liquidity_in_loaded_bins: the largest SOL input (incl. fees) the loaded bins can absorb (0 = no buy-side liquidity in the window).
    - `reason` string: e.g. concentrated_liquidity_depth_not_supported, pool_model_unknown, curve_graduated_use_amm_pool, reserves_unavailable. With the Meteora DLMM model enabled also: dlmm_lb_pair_unknown, dlmm_lb_pair_not_found, dlmm_lb_pair_unreadable, dlmm_pair_disabled, dlmm_rpc_unavailable, dlmm_not_evaluated_pool_budget (past the per-request pool budget), dlmm_depth_uncomputable, dlmm_insufficient_liquidity_in_loaded_bins (no requested size fills inside the loaded bin window, e.g. a one-sided or drained pair; carries fillable_up_to_sol and bins_window), dlmm_active_bin_not_loaded, dlmm_bin_array_unreadable, dlmm_bin_array_mismatch, dlmm_bin_array_window_gap, dlmm_no_bin_arrays, dlmm_snapshot_invalid, pool_mint_mismatch, exotic_quote_depth_not_supported, token_mint_unreadable, token2022_transfer_fee_not_modeled, sol_usd_unavailable_for_stable_quote. With the Raydium CLMM model enabled also: clmm_pool_state_unknown, clmm_pool_not_found (the stored pool is not a Raydium CLMM account), clmm_pool_unreadable, clmm_config_unreadable, clmm_config_mismatch, clmm_swap_disabled, clmm_pool_not_open, clmm_unknown_pool_extension, clmm_rpc_unavailable, clmm_not_evaluated_pool_budget, clmm_depth_uncomputable, clmm_insufficient_liquidity_in_loaded_ticks (no requested size fills inside the loaded tick window; carries ticks_window), clmm_current_tick_not_loaded, clmm_tick_price_mismatch, clmm_tick_array_missing, clmm_tick_array_unreadable, clmm_tick_array_mismatch, clmm_tick_array_window_gap, clmm_tick_index_mismatch, clmm_tick_bitmap_mismatch, clmm_liquidity_negative, clmm_snapshot_invalid. Shared concentrated-depth budget (DLMM + CLMM together): concentrated_depth_busy (process-wide concurrent snapshot limit reached), concentrated_depth_budget_exhausted (per-minute RPC budget reached). With the Meteora DAMM v2 model enabled (rows under the DAMM v2 vault authority, whatever their dex label): damm_v2_pool_unknown (no proven Pool account stored), damm_v2_pool_unavailable (live read failed), damm_v2_pool_not_found, damm_v2_pool_wrong_owner, damm_v2_unknown_layout, damm_v2_pool_vault_mismatch, damm_v2_single_range (proven but concentrated price range; no depth model yet)
  - `note` string
  - `pool_selection` object: Only with a concentrated depth model enabled. Which pool is the largest we know of vs the pool depth is reported for; multi-pool routing is not computed or promised.
    - `largest_known_pool` string: Largest evaluated pool by stored liquidity, supported or not.
    - `largest_known_pool_supported` boolean: false = the largest known pool is in unsupported_pools; the primary pool is a smaller one.
    - `primary_pool` string, nullable: Deepest pool with depth available (same as the top-level primary_pool).
    - `routing` 'single_pool_only'

## Other responses

- `400`: Invalid sizes parameter
- `401`: Missing or invalid API key, or an expired free-tier key. Authentication-stage error: no `X-RateLimit-*` headers, no `_rid`.
- `403`: Forbidden. One of: the key's tier is below this endpoint's or parameter's gate (`tier_required` with an `upgrade` block); the public demo key used outside its allow-list (`demo_key_endpoint_not_allowed`); an invalid or revoked key; an origin-restricted key called from a disallowed origin (`code` `origin_not_allowed` / `origin_required`). `X-RateLimit-*` headers are present only on `tier_required`.
- `429`: Too many requests. Every 429 carries `Retry-After`. A quota 429 (`rate_limit_exceeded`, with `X-RateLimit-*`), a heavy-query concurrency 429 (`error_kind` `concurrency`/`capacity`), or the per-IP authentication-failure block (30 failed auths/min; plain `error` + `retry_after_seconds`, no `X-RateLimit-*`).
- `500`: Unexpected server error from the route (`Internal server error`, with `_rid`). Safe to retry with backoff. A failed API-key lookup is a 503 `auth_backend_unavailable`, never a 500.
- `503`: The API-key or subscription lookup could not be answered (authentication stage). Retryable and not your fault: it is never counted as a failed authentication. Honour `Retry-After`; no `X-RateLimit-*`, no `_rid`.

---

[API](https://skmtc.dev/madeonsol/apis/madeonsol-api.md) · [All operations](https://skmtc.dev/madeonsol/apis/madeonsol-api/llms.txt) · [OpenAPI document](https://skmtc.dev/madeonsol/apis/madeonsol-api/revisions/d9531a28d83b?raw)
