Docs

Morpho Midnight

How to query Morpho Midnight data with the API?

Discovery & listing

List all markets

Returns all Midnight markets, optionally filtered by chain, loan token, or collateral. Supported chains: Ethereum (1), Base (8453), Arc (5042) and Robinhood Chain (4663).

GET /v0/midnight/markets

All markets:

# All markets on Ethereum mainnet
curl "https://api.morpho.org/v0/midnight/markets?chain_ids=1"

Filtered by token:

# USDC markets on Base with wETH as collateral
curl "https://api.morpho.org/v0/midnight/markets\
  ?chain_ids=8453\
  &loan_assets=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
  &collateral_assets=0x4200000000000000000000000000000000000006"

Get market detail

Immutable configuration for a single market: market family, loan token, maturity, collaterals (with LLTV, liquidation cursor, oracle), and gates. Does not include fees or total units (those live on the state endpoint).

GET /v0/midnight/markets/{market-id}

Each entry in the response's collaterals list carries exactly these fields:

token, lltv, liquidation_cursor, oracle

curl "https://api.morpho.org/v0/midnight/markets/0xcc9418ea594c6e658650aedd205ce4544b266b69493f56fd2adc65c14bd06738"

// Response - immutable market definition:
{
  "data": {
    "chain_id": 8453,
    "market_id": "0xcc9418ea594c6e658650aedd205ce4544b266b69493f56fd2adc65c14bd06738",
    "market_family_id": "0x9a6ece688006fb810141501154acfd1aa29ae7ac3753452f4931a092f2653f1f",
    "loan_token": "0x4200000000000000000000000000000000000006", // WETH on Base
    "maturity": 1784300400, // July 17, 2026 at 15:00 UTC
    "rcf_threshold": "0",
    "enter_gate": "0x0000000000000000000000000000000000000000",
    "liquidator_gate": "0x0000000000000000000000000000000000000000",
    "collaterals": [
      {
        "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "lltv": "860000000000000000",
        "liquidation_cursor": "300000000000000000",
        "oracle": "0xD09048c8B568Dbf5f189302beA26c9edABFC4858"
      }
    ]
  }
}

Market state & metrics

Get market state

Live market state: total units outstanding, fee configuration, and tick granularity. Separated from the market definition because these values change over time.

GET /v0/midnight/markets/{market-id}/state

curl "https://api.morpho.org/v0/midnight/markets/0xcc9418ea594c6e658650aedd205ce4544b266b69493f56fd2adc65c14bd06738/state"

// Response:
{
  "data": {
    "chain_id": 8453,
    "market_id": "0xcc9418ea594c6e658650aedd205ce4544b266b69493f56fd2adc65c14bd06738",
    "market_family_id": "0x9a6ece688006fb810141501154acfd1aa29ae7ac3753452f4931a092f2653f1f",
    "last_indexed_block": "48408699",
    "total_units": "1481439992020013", // total units outstanding
    "tick_granularity": 4, // valid ticks must be multiples of this
    "settlement_fee_schedule": [
      { "time_to_maturity_days": 0, "fee_cbp": "0" },
      { "time_to_maturity_days": 1, "fee_cbp": "0" },
      { "time_to_maturity_days": 7, "fee_cbp": "0" },
      { "time_to_maturity_days": 30, "fee_cbp": "0" },
      { "time_to_maturity_days": 90, "fee_cbp": "0" },
      { "time_to_maturity_days": 180, "fee_cbp": "0" },
      { "time_to_maturity_days": 360, "fee_cbp": "0" }
    ],
    "current_settlement_fee_wad": "0",
    "current_settlement_fee_cbp": "0", // interpolated for current TTM
    "continuous_fee_rate": "0" // per-second, WAD-scaled
  }
}

Offers & rates

List policy-admitted books

The endpoint returns only active maturities admitted by the current policy. Unlisted and past maturities stay excluded even when requested with ids; if a maturity leaves the policy, its books disappear immediately, including books with existing offers.

Each book includes the top 3 ask and bid levels. Sorting: Sort by comma-separated fields (`id`, `ask`, `bid`, `maturity`). Prefix a field with `-` for descending. Max 3 fields.

GET /v0/midnight/books

By maturity:

curl "https://api.morpho.org/v0/midnight/books\
  ?chain_ids=8453\
  &loan_tokens=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
  &sort=maturity"

By best lend rate:

# Sort by best ask (lowest price = highest lend rate)
curl "https://api.morpho.org/v0/midnight/books\
  ?chain_ids=8453\
  &loan_tokens=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\
  &sort=ask"

Get full book for a market

Each level sums all offers at that tick. Levels returned per side: Maximum levels returned per side. Default: 100. Maximum: 6745 (ticks 0 through 6744, inclusive).

GET /v0/midnight/books/{market-id}

Each price level carries exactly these fields:

tick, price, units, assets, count

curl "https://api.morpho.org/v0/midnight/books/0xcc9418ea594c6e658650aedd205ce4544b266b69493f56fd2adc65c14bd06738?depth=50"

// Response:
{
  "data": {
    "market_id": "0xcc9418ea594c6e658650aedd205ce4544b266b69493f56fd2adc65c14bd06738",
    "chain_id": 8453,
    "midnight": "0x2F7a3AA739ba5792Ce1b4eA046117f2C0095BCA6",
    "loan_token": "0x4200000000000000000000000000000000000006",
    "collaterals": [
      {
        "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "lltv": "860000000000000000",
        "liquidation_cursor": "300000000000000000",
        "oracle": "0xD09048c8B568Dbf5f189302beA26c9edABFC4858"
      }
    ],
    "maturity": 1784300400,
    "rcf_threshold": "0",
    "enter_gate": "0x0000000000000000000000000000000000000000",
    "liquidator_gate": "0x0000000000000000000000000000000000000000",
    "asks": [
      { "tick": 42, "price": "952380952380952380", "units": "10000000000", "assets": "9523809523", "count": 3 },
      { "tick": 43, "price": "948000000000000000", "units": "18500000000", "assets": "17538000000", "count": 5 }
    ],
    "bids": [
      { "tick": 41, "price": "956937000000000000", "units": "8000000000", "assets": "7655497000", "count": 2 }
    ]
  }
}

Compute rates from prices (TTM = seconds to maturity):

// lend rate (from asks):   (1 / (price / 1e18) - 1) × 365×86400 / TTM
// borrow rate (from bids): (1 / (price / 1e18) - 1) × 365×86400 / TTM

Get one side of the book

{side} is one of asks, bids.

GET /v0/midnight/books/{market-id}/{side}

# Just the asks (lender opportunities)
curl "https://api.morpho.org/v0/midnight/books/0xd92d...7614/asks?depth=100"

# Just the bids (borrower opportunities)
curl "https://api.morpho.org/v0/midnight/books/0xd92d...7614/bids?depth=100"

Quotes & execution

Get a quote (execution plan)

Given a target amount (in assets or units) and a side, the Router returns execution-ready takeable offers sorted by best price with fallback excess.

GET /v0/midnight/books/{market-id}/{side}/quote

Each takeable offer's offer struct carries exactly these fields:

market, buy, maker, max_units, start, expiry, tick, group, callback, callback_data, receiver_if_maker_is_seller, ratifier, reduce_only, max_assets, continuous_fee_cap

Lend (take asks):

// "I want to lend 10,000 USDC" → take asks
curl "https://api.morpho.org/v0/midnight/books/0xd92d...7614/asks/quote\
  ?assets=10000000000\
  &slippage=0.5\
  &limit=10000"

// Response:
{
  "data": {
    "average_best_price": "947619047619047619", // realized target fill, using onchain per-offer rounding and rounded against the taker
    "average_worst_price": "952300000000000000", // conservative adverse-placement bound across returned caps; not the caller's guard
    "available_assets": "15000000000",
    "available_units": "15750000000",
    "takeable_offers": [
      {
        "market_id": "0xd92d...7614",
        "units": "5000000000",
        "offer": {
          "market": {
            "chain_id": 8453,
            "midnight": "0x2F7a3AA739ba5792Ce1b4eA046117f2C0095BCA6",
            "loan_token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
            "collaterals": [
              {
                "token": "0x4200000000000000000000000000000000000006",
                "lltv": "860000000000000000",
                "liquidation_cursor": "300000000000000000",
                "oracle": "0x45093658BE7f90B63D7c359e8f408e503c2D9401"
              }
            ],
            "maturity": 1798761600,
            "rcf_threshold": "0",
            "enter_gate": "0x0000000000000000000000000000000000000000",
            "liquidator_gate": "0x0000000000000000000000000000000000000000"
          },
          "buy": false,
          "maker": "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
          "max_units": "0",
          "start": 1761922790,
          "expiry": 1798761600,
          "tick": 42,
          "group": "0x000000000000000000000000000000000000000000000000000000000008b8f4",
          "callback": "0x0000000000000000000000000000000000000000",
          "callback_data": "0x",
          "receiver_if_maker_is_seller": "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
          "ratifier": "0x0000000000000000000000000000000000000002",
          "reduce_only": false,
          "max_assets": "5000000000",
          "continuous_fee_cap": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
        },
        "ratifier_data": "0x4a8b...f201",
        "valid_until": 1761922799,
        "warning": null
      }
    ]
  }
}

Borrow (take bids):

# "I want to borrow 5,000 USDC" → take bids
curl "https://api.morpho.org/v0/midnight/books/0xd92d...7614/bids/quote\
  ?assets=5000000000\
  &slippage=0.5\
  &limit=10000"

# Same response shape - but offers have buy=true (lenders' buy-offers)

By units:

# Quote by units instead of assets
curl "https://api.morpho.org/v0/midnight/books/0xd92d...7614/asks/quote\
  ?units=10500000000"

List takeable offers (raw)

Individual executable offers with the full offer struct and ratifier data. Use when building custom routing or analysis.

By market side:

GET /v0/midnight/books/{market-id}/{side}/takeable-offers

Across markets, by maker:

GET /v0/midnight/takeable-offers

By market side:

curl "https://api.morpho.org/v0/midnight/books/0xd92d...7614/asks/takeable-offers"

By maker:

# All active offers from a specific maker
curl "https://api.morpho.org/v0/midnight/takeable-offers\
  ?maker=0xMakerAddress...\
  &limit=100"

Takeability warnings

The warning field explains why only part of an offer, or none of it, can be taken right now. Makers get it on their own offers from GET /v0/midnight/takeable-offers. A null value means the offer's complete remaining capacity is takeable. A non-null value gives the primary reason why more of the active offer is not currently takeable. On the book listing (GET /v0/midnight/books/{market-id}/{side}/takeable-offers) and quote (GET /v0/midnight/books/{market-id}/{side}/quote) endpoints, warning is deprecated: it will become null, then be removed. Use units there instead. On the book listing, it gives how much of each offer can be taken. On a quote, it's a per-offer cap, and the caps together can exceed the requested size. See Takeability warnings for how to read and surface them.

CodeMeaning
Limit how much can be taken (possibly to zero)
MAKER_LIQUIDITYMaker-controlled liquidity cannot back more units.
MAKER_ALLOWANCEThe maker's loan-token approval cannot back more units.
SOURCE_LIQUIDITYThe underlying protocol cannot currently release more liquidity.
REDUCE_ONLYMore units would increase rather than reduce the maker's position.
POSITION_CAPACITYThe maker's credit or debt position has no room for more units.
AMOUNT_ROUNDINGAsset and unit rounding prevents another meaningful unit from executing.
SINGLE_TAKE_LIMITThe offer exceeds the maximum units allowed in one take.
None of it can be taken right now
CALLBACK_NOT_REGISTEREDThe callback was not registered to the maker before the offer was submitted.
RATIFIER_NOT_AUTHORIZEDThe maker does not currently authorize the offer's ratifier.
SIMULATION_FAILEDRouter simulation failed for the offer's group and market.
RESTRICTED_TAKERThe offer is reserved for a specific taker and cannot be taken publicly. Only the reserved taker can take it.
ROOT_CANCELEDThe offer's Ecrecover Merkle root was permanently canceled.
ROOT_NOT_RATIFIEDThe maker has not currently ratified the offer's Setter Merkle root.
SIGNER_NOT_AUTHORIZEDThe maker does not currently authorize the offer tree's signer.
BELOW_MINIMUM_SIZEThe offer was removed after its supported size fell below policy minimum.

For codes in the "Limit how much can be taken" group, the offer's units on GET /v0/midnight/takeable-offers shows how much can still be taken.

Some codes also return extra fields (limit_units, root, signer, observed_assets, minimum_assets). They're deprecated and not listed here, so rely on code alone.

Example:

// One takeable offer (excerpt; other fields omitted, values illustrative)
{
  "market_id": "0xa249f0b3ffe8891c96ec93fd9c7d00e479da04e4ffe2f2502ea0e5db8eabc75d",
  "units": "1000000",
  // offer, ratifier_data, ...
  "warning": {
    "code": "MAKER_ALLOWANCE"
  }
}

Position tracking

List user positions

Returns all positions for a user across markets. Includes cost_basis and effective_rate_wad inline. Position types: lend, borrow, collateral_only.

GET /v0/midnight/users/{user-address}/positions

All positions:

curl "https://api.morpho.org/v0/midnight/users/0xAlice.../positions"

// Response:
{
  "cursor": null,
  "data": [
    {
      "chain_id": 8453,
      "market_id": "0xd92d...7614",
      "user_address": "0xAlice...",
      "loan_token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "maturity": 1798761600,
      "credit": "10500000000",
      "pending_fee": "12000",
      "last_loss_factor": "0",
      "loss_factor": "0",
      "debt": "0",
      "cost_basis": "952380952380952380",
      "effective_rate_wad": "52000000000000000",
      "effective_apr": 0.0508,
      "collaterals": [],
      "created_at": 1761922790,
      "type": "lend"
    }
  ]
}

Lend only:

curl "https://api.morpho.org/v0/midnight/users/0xAlice.../positions?types=lend"

Borrow only:

curl "https://api.morpho.org/v0/midnight/users/0xAlice.../positions?types=borrow"

Get position detail

Raw position state in a specific market. Does not include cost_basis or effective_rate_wad (use the performance endpoint for those).

GET /v0/midnight/markets/{market-id}/users/{user-address}/position

curl "https://api.morpho.org/v0/midnight/markets/0xd92d...7614/users/0xBob.../position"

// Response (borrow position):
{
  "data": {
    "chain_id": 8453,
    "market_id": "0xd92d...7614",
    "user_address": "0xBob...",
    "loan_token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "maturity": 1798761600,
    "credit": "0",
    "pending_fee": "0",
    "last_loss_factor": "0",
    "loss_factor": "0",
    "debt": "9000000000", // debt to clear
    "collaterals": [
      {
        "token": "0x4200000000000000000000000000000000000006", // WETH on Base
        "amount": "2000000000000000000" // 2 WETH
      },
      {
        "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
        "amount": "10000000" // 10 USDC
      }
    ],
    "type": "borrow",
    "last_indexed_block": "47457420"
  }
}

Get position performance

Cost basis and effective rate for P&L computation. Uses average cost accounting.

GET /v0/midnight/markets/{market-id}/users/{user-address}/position/performance

curl "https://api.morpho.org/v0/midnight/markets/0xd92d...7614/users/0xAlice.../position/performance"

// Response:
{
  "data": {
    "chain_id": 8453,
    "market_id": "0xd92d...7614",
    "user_address": "0xAlice...",
    "type": "lend",
    "cost_basis": "952380952380952380",
    "effective_rate_wad": "52000000000000000",
    "effective_apr": 0.0508,
    "last_indexed_block": "47457420",
    "accounting_method": "average_cost"
  }
}

List all positions in a market

Find all borrowers, cross-reference with oracle prices to find unhealthy positions.

GET /v0/midnight/markets/{market-id}/positions

# All borrowers in a market
curl "https://api.morpho.org/v0/midnight/markets/0xd92d...7614/positions?types=borrow"

# Active positions only (market not yet matured)
curl "https://api.morpho.org/v0/midnight/markets/0xd92d...7614/positions\
  ?types=borrow\
  &active_only=true"

Transaction history

User transactions

All onchain events for a user. Filter by event_types to focus on specific actions. Valid values:

borrow, lend, exit_lend_primary, exit_lend_secondary, exit_borrow_primary, exit_borrow_secondary, partial_liquidation, full_liquidation, withdraw_collateral, supply_collateral, roll

  • lend - entered a lending position (bought units)
  • exit_lend_primary - redeemed credit (1:1 withdrawal)
  • exit_lend_secondary - sold credit units early
  • borrow - entered a borrowing position (sold units)
  • exit_borrow_primary - repaid debt
  • exit_borrow_secondary - bought units to close debt early
  • supply_collateral - deposited collateral
  • withdraw_collateral - withdrew collateral
  • partial_liquidation / full_liquidation - liquidations; events include the borrower, collateral, seized assets, repaid units, post-maturity mode, bad debt, and latest loss factor
  • roll - the borrower's Midnight debt and collateral were rolled into a Morpho Blue market under a rolling configuration the borrower authorized; events include the destination market, debt and collateral moved, and the incentive paid to the caller

GET /v0/midnight/users/{user-address}/transactions

Lending activity:

curl "https://api.morpho.org/v0/midnight/users/0xAlice.../transactions\
  ?event_types=lend,exit_lend_primary,exit_lend_secondary"

Borrowing activity:

curl "https://api.morpho.org/v0/midnight/users/0xBob.../transactions\
  ?event_types=borrow,exit_borrow_primary,exit_borrow_secondary,supply_collateral,withdraw_collateral"

Market transactions

GET /v0/midnight/markets/{market-id}/transactions

# All activity in a market since a specific time
curl "https://api.morpho.org/v0/midnight/markets/0xd92d...7614/transactions?created_at_gte=1719000000"

Offer management

List offer groups

Track a maker's consumption groups and which offers belong to them. statuses selects one or more lifecycle states (groups matching any of them are returned) and defaults to active. Groups can also be narrowed to verified Blue callbacks with callback_type=blue_buy, and to Midnight market families with market_family_ids.

GET /v0/midnight/users/{user-address}/offer-groups

# All active offer groups for this maker (default lifecycle state)
curl "https://api.morpho.org/v0/midnight/users/0xMaker.../offer-groups"

# Active offer groups filtered by market and group
curl "https://api.morpho.org/v0/midnight/users/0xMaker.../offer-groups\
  ?market_ids=0xd92d...7614\
  &groups=0xMyGroupId..."

# Expired offer groups with verified Blue-buy callbacks
curl "https://api.morpho.org/v0/midnight/users/0xMaker.../offer-groups\
  ?statuses=expired\
  &callback_type=blue_buy"

Mempool

Validate offers before publishing

Check whether the Router will index your offers. Payload is version byte + 4-byte big-endian gzip length + gzip(ABI-encoded (Offer, bytes ratifierData)[]). Optionally pass a timestamp to validate against a specific policy snapshot.

POST /v0/midnight/mempool/validate

Current policy:

curl -X POST "https://api.morpho.org/v0/midnight/mempool/validate" \
  -H "Content-Type: application/json" \
  -d '{
    "chain_id": 8453,
    "payload": "0x01..."
  }'

# Success (Router will index):
{ "data": { "issues": [] } }

# Issues found (Router will ignore):
{ "data": { "issues": [{ "rule": "blue_callback", "details": null }] } }

At a specific time:

# Validate against the policy snapshot active at a specific time
# Uses the latest 15:00 UTC boundary at or before the given timestamp
curl -X POST "https://api.morpho.org/v0/midnight/mempool/validate\
  ?timestamp=2026-06-28T12:00:00Z" \
  -H "Content-Type: application/json" \
  -d '{
    "chain_id": 8453,
    "payload": "0x01..."
  }'

Pagination & filtering

List endpoints support cursor-based pagination. The response includes a cursor field - pass it as a query parameter to get the next page.

# First page
curl "https://api.morpho.org/v0/midnight/markets?chain_ids=8453"

// Response includes:
{ "cursor": "***...", "data": [...] }

# Next page - pass the cursor
curl "https://api.morpho.org/v0/midnight/markets?chain_ids=8453&cursor=***..."

// cursor is null when there are no more pages

The markets list carries the richest filter set - other list endpoints follow the same conventions:

All these parameters are optional query parameters.

NameTypeDescription
chain_idsarrayFilter by chain ids. Supported chains: Ethereum (1), Base (8453), Arc (5042), and Robinhood Chain (4663). Required when any address filter is provided.
market_idsarrayFilter by Midnight market ids. These ids are globally unique.
market_family_idsarrayFilter by Midnight market family ids. A family contains markets whose immutable parameters differ only by maturity.
loan_assetsarrayFilter by loan token addresses. Combine with chain_ids; lowercase input is checksummed.
collateral_assetsarrayFilter by collateral token addresses. Combine with chain_ids; lowercase input is checksummed.
oracle_addressesarrayFilter by collateral oracle addresses. Combine with chain_ids; lowercase input is checksummed.
enter_gatesarrayFilter by enter gate addresses. Combine with chain_ids; lowercase input is checksummed.
liquidator_gatesarrayFilter by liquidator gate addresses. Combine with chain_ids; lowercase input is checksummed.
maturitiesarrayFilter by exact maturity timestamps, in unix seconds.
active_onlystringWhen true, enforces maturity strictly after the current timestamp.
maturity_gteanyOfFilter for maturities greater than or equal to this unix timestamp.
maturity_lteanyOfFilter for maturities less than or equal to this unix timestamp.
total_units_gtestringFilter for total units greater than or equal to this value.
total_units_ltestringFilter for total units less than or equal to this value.
lend_depth_gtestringFilter for cached lend-side order-book depth, in loan-token units, greater than or equal to this value.
lend_depth_ltestringFilter for cached lend-side order-book depth, in loan-token units, less than or equal to this value.
borrow_depth_gtestringFilter for cached borrow-side order-book depth, in loan-token units, greater than or equal to this value.
borrow_depth_ltestringFilter for cached borrow-side order-book depth, in loan-token units, less than or equal to this value.
listedstringFilter by listing status. When true, returns only markets surfaced by the app trust layer; when false, only unlisted markets. Omit to return both.
sort_bystringSort field for cursor pagination.
sort_directionstringSort direction for cursor pagination.
limitintegerMaximum number of items to return.
cursorstringOpaque cursor from a previous page response.