List active Midnight offer groups for a user
Cursor-paginated list of a user's active offer groups with nested active offers.
Active offers have started, have not passed their offer expiry or market maturity, and still have remaining group capacity. Asset-capped offers are considered fully consumed when consumed >= max_assets; unit-capped offers are fully consumed when consumed >= max_units. Fully consumed offers are excluded, and a group is omitted entirely when no active offers remain in it. Each group returns the max expiry across all unexpired and unmatured offers in the whole group, including future-start offers, one deterministic representative offer limit (max_units, max_assets), the latest group-level consumed value, and all active offers in that group matching the non-market request filters. Each offer includes both market_id and the immutable market config used to derive it, because uncreated markets cannot be decoded from market_id alone.
Filters. market_ids filters the group page to groups containing at least one active offer in any requested market, but nested offers are not narrowed by market_ids; all active sibling offers in each returned group remain visible. chain_ids, loan_assets, and groups filter both the group page and nested offers. listed=true returns only groups where every active offer is on a listed market; listed=false returns groups with at least one active offer on an unlisted market. loan_assets matches loan token addresses across all chains unless chain_ids is also provided. The group-level expiry is computed for the whole offer group and is not narrowed by market_ids or loan_assets. created_at_gte and created_at_lte filter by the first active matching offer created in each group. market_ids, loan_assets, and groups are capped at 20 values.
Pagination. Response follows the list envelope: { cursor, data }. Pagination is over groups; nested offers are not split across pages. Sort groups with sort_by=id|created_at and sort_direction=asc|desc.
For enterprise access, use https://private.api.morpho.org as the base URL and send your API key in the x-api-key header. Request an API key.
Path Parameters
User address whose active offer groups should be listed.
Query Parameters
Filter by chain ids. Supported chains: Base (8453).
items <= 100Filter groups to those containing active offers in these Midnight markets. Nested offers are not narrowed by this filter.
items <= 20Filter nested active offers by loan token addresses. Combined with market_ids and groups using AND semantics.
items <= 20Filter by offer group ids. Combined with market_ids and loan_assets using AND semantics.
items <= 20Filter for group created_at greater than or equal to this unix timestamp.
Filter for group created_at less than or equal to this unix timestamp.
Filter by market listing status. When true, returns only groups where every active offer is on a listed market; when false, groups with at least one active offer on an unlisted market. Omit to return both.
"true" | "false"Sort field for group cursor pagination.
"id""id" | "created_at"Sort direction for group cursor pagination.
"asc""asc" | "desc"Maximum number of groups to return.
1001 <= value <= 100Opaque cursor from a previous page response.
1 <= length <= 4096Response Body
application/json
application/json
const baseUrl = "https://api.morpho.org";const userAddress = "0x958eB498a4172EA513c79b09E7f064070C5b1917";const url = new URL(`${baseUrl}/v0/midnight/users/${userAddress}/offer-groups`);url.searchParams.set("chain_ids", "8453");const response = await fetch(url, { headers: { accept: "application/json", },});if (!response.ok) throw new Error(await response.text());const body = await response.json();{
"cursor": "eyJzb3J0QnkiOiJpZCIsInNvcnREaXJlY3Rpb24iOiJhc2MiLCJjaGFpbklkIjo4NDUzLCJncm91cCI6IjB4MGJhYjUxZmFiNjQxNTdiYzEwMTFjZTY1YjliZjliMmIxMWYyMDJiOGE3YWI3NmI0MDhjZjQwYjhhZGYwNjlkMyJ9",
"data": [
{
"id": "0x0bab51fab64157bc1011ce65b9bf9b2b11f202b8a7ab76b408cf40b8adf069d3",
"chain_id": 8453,
"created_at": 1783584485,
"expiry": 1784300399,
"max_units": "0",
"max_assets": "80000000000000",
"consumed": "0",
"offers": [
{
"market_id": "0xcc9418ea594c6e658650aedd205ce4544b266b69493f56fd2adc65c14bd06738",
"market": {
"loan_token": "0x4200000000000000000000000000000000000006",
"maturity": 1784300400,
"rcf_threshold": "0",
"enter_gate": "0x0000000000000000000000000000000000000000",
"liquidator_gate": "0x0000000000000000000000000000000000000000",
"collaterals": [
{
"token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"lltv": "860000000000000000",
"liquidation_cursor": "300000000000000000",
"oracle": "0xD09048c8B568Dbf5f189302beA26c9edABFC4858"
}
]
},
"created_at": 1783584485,
"buy": true,
"maker": "0x958eB498a4172EA513c79b09E7f064070C5b1917",
"max_units": "0",
"max_assets": "80000000000000",
"continuous_fee_cap": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
"start": 1783584483,
"expiry": 1784300399,
"tick": 4408,
"callback": "0x0000000000000000000000000000000000000000",
"callback_data": "0x",
"receiver_if_maker_is_seller": "0x0000000000000000000000000000000000000000",
"ratifier": "0xd6e70365C8E8DDa9a4ca662C07bbE663b017755E",
"reduce_only": false
}
]
}
]
}{
"error": {
"code": "INVALID_CURSOR",
"message": "Invalid user group cursor",
"details": null,
"request_id": "f0e1d2c3-b4a5-4968-8728-1c0d1e2f3a4b"
}
}