Activity taxonomy

The normalized cross-protocol activity feed — one label set for deposits, borrows, swaps, and more, with per-event USD valuation and keyset pagination.

Where the positions endpoints tell you what a wallet holds now, the activity feed tells you what it did — each on-chain action normalized to one label set that means the same thing across every protocol.

The label set

activity_type is a closed enum. A deposit into a Blend pool and a liquidity add on Soroswap map to the same vocabulary, so you branch on one field:

activity_typeMeaning
depositSupplied assets into a protocol.
withdrawRemoved supplied assets.
borrowTook on debt.
repayRepaid debt.
liquidationPosition was liquidated.
claim_rewardsClaimed emissions / rewards.
flash_loanFlash loan taken.
bad_debtDebt written off as unrecoverable.
swapToken swap.
add_liquidityAdded to an AMM pool.
remove_liquidityRemoved from an AMM pool.
mintMinted shares / tokens.
burnBurned shares / tokens.
contract_status_changeA tracked contract changed lifecycle state (e.g. a pool froze).

contract_status_change is not a user action — for those rows the address field is the contract whose status changed, not a wallet.

Read the feed

GET /v1/users/{address}/activities returns the wallet’s activity, newest first:

curl "https://query.orionhq.run/v1/users/GABC7XYZ.../activities?limit=50" \
  -H "x-orion-api-key: $ORION_KEY"
{
  "data": {
    "address": "GABC7XYZ...",
    "activities": [
      {
        "id": "80421993",
        "address": "GABC7XYZ...",
        "protocol": "blend",
        "activity_type": "borrow",
        "contract": "CCLBPEYS...",
        "asset_id": "CDLZFC3S...",
        "asset_symbol": "USDC",
        "asset_decimals": 7,
        "amount": "50.0000000",
        "share_amount": "49.8100000",
        "usd_value": "50.00",
        "counterparty": null,
        "tx_hash": "3f9a...c1",
        "ledger": 3356020,
        "timestamp": "2026-07-23T08:41:12Z",
        "metadata": null
      }
    ],
    "next_cursor": "eyJsZWRnZXIiOjMzNTYwMjB9"
  },
  "meta": { "...": "response metadata" }
}

Each row carries the normalized activity_type, the protocol and contract it touched, the asset (asset_id, asset_symbol, asset_decimals), on-chain provenance (tx_hash, ledger, timestamp), and a per-event usd_value when a price was available — null otherwise, with the row still counted and returned.

id is a string even though it’s numeric: the underlying sequence can exceed JSON’s safe integer range, so treat it as an opaque string.

Pagination

The feed uses keyset (cursor) pagination. When more rows exist, next_cursor is non-null. Pass it back verbatim as the cursor query parameter for the next page — do not parse or construct it:

curl "https://query.orionhq.run/v1/users/GABC7XYZ.../activities?cursor=eyJsZWRnZXIiOjMzNTYwMjB9" \
  -H "x-orion-api-key: $ORION_KEY"

limit defaults to 50 and is capped at 100. A null next_cursor means you’ve reached the end.

Filters

Narrow the feed with query parameters (combine freely):

ParameterFilters by
protocolProtocol id, e.g. blend.
activity_typeOne type, or a comma-separated list (e.g. deposit,withdraw).
contractThe contract an activity touched.
tx_hashA specific transaction.
from_ledger / to_ledgerAn inclusive ledger range.
as_of_ledgerRows at or before a ledger. Cannot be combined with to_ledger.
curl "https://query.orionhq.run/v1/users/GABC7XYZ.../activities?protocol=blend&activity_type=borrow,repay" \
  -H "x-orion-api-key: $ORION_KEY"

Aggregated series

GET /v1/users/{address}/activities/series buckets the feed into event counts and USD volume, grouped by activity_type within each bucket — useful for charting activity over time without paging the raw feed.

Choose one axis: time buckets (interval of 1h/4h/1d with from/to) or ledger buckets (ledger_bucket with from_ledger/to_ledger).

curl "https://query.orionhq.run/v1/users/GABC7XYZ.../activities/series?interval=1d&from=2026-07-16T00:00:00Z&to=2026-07-23T00:00:00Z" \
  -H "x-orion-api-key: $ORION_KEY"
{
  "data": {
    "address": "GABC7XYZ...",
    "points": [
      {
        "timestamp": "2026-07-22T00:00:00Z",
        "ledger": 3356020,
        "activity_type": "borrow",
        "events": 3,
        "usd_volume": "150.00"
      }
    ]
  },
  "meta": { "...": "response metadata" }
}

usd_volume sums only priced events, so a bucket of entirely unpriced events is null — but events still counts every row. Gap-fill is not offered here: counts and sums have no meaningful value to carry across an empty bucket.