Skip to main content
GET
Search and filter wallet profiles across your project with advanced filtering capabilities. You can look up an exact wallet address, run a free-text search across addresses and social fields, and combine that with structured filters in the request body.

Authentication

This endpoint requires authentication using a Workspace API Key with profiles:read permission. Include the API key in your request headers:
The API key needs to have the read permission for profiles in the API settings. You can configure this in your workspace API settings.

Query Parameters

address

Filter by a specific wallet address (exact match). Accepts an EVM address, a Solana address, or an ENS name (e.g. vitalik.eth) which is resolved to an address before filtering. An unresolvable ENS name or an otherwise invalid value returns a 400 BAD_REQUEST.
Case-insensitive free-text search across wallet addresses and all supported social fields. This includes values from both global wallet profiles and project-scoped identify overrides.

expand

Comma-separated list of optional sections to include in each profile response. Supported values:
  • apps - DeFi app interactions and balances
  • chains - Per-chain activity metrics
  • tokens - Token holdings
  • labels - Wallet labels
Expanding fields like chains, tokens, or apps increases response size and latency. The collections are capped at 50 items each.

order_by

Field to sort results by. Supported values:
  • last_onchain (default) - Last on-chain activity timestamp
  • first_onchain - First on-chain activity timestamp
  • net_worth_usd - Total net worth
  • updated_at - Last profile update timestamp
  • tx_count - Total transaction count
  • first_seen - First seen timestamp in your app
  • last_seen - Last seen timestamp in your app
  • num_sessions - Number of sessions
  • revenue - Total revenue
  • volume - Total volume
  • points - Total points

order_dir

Sort direction:
  • desc (default) - Descending order
  • asc - Ascending order

page

1-indexed page number to return.
  • Default: 1

size

Page size - number of profiles per page.
  • Default: 100
  • Maximum: 1000

Request Body (Filters)

The search endpoint supports rich filtering capabilities through a JSON request body. The body contains a filter object with filters and logic.

Filter Schema

Filter Condition

Each filter in the filters array carries the canonical {field, op, value} core, plus named qualifier properties for resource filters: Unknown properties and qualifiers that don’t apply to the targeted field are rejected with a 400.

Operators

Behavioural labels such as defi.lender, defi.borrower, defi.staker and defi.perp_trader store a USD amount as their value, so the comparison operators work on them. For example, wallets that supply at least $10,000 to lending markets: {"field": "labels.value", "op": "gte", "value": "10000", "tag_id": "defi.lender"}. See Wallet labels for the full list and each label’s rule.
Legacy spellings are retired. The long-form spellings equals, notEquals, greater, greaterOrEqual, less, lessOrEqual, notIn, and includes (and symbol forms like = / != / like) are no longer accepted on this endpoint. A request carrying one is rejected with a 400 whose message names the offending token. Send only the canonical operators above. notEmpty / isEmpty are value-less existence checks (any value is ignored) and are supported on string user/profile attributes only, not on numeric metrics (net_worth_usd, volume, revenue, points), the lifecycle enum, or chain/app/token/label fields.
Dynamic field paths are retired. Identifier-in-path spellings such as chains.1.balance, apps.aave-v3.balance, tokens.0x….balance, and labels.coinbase.verified_account are no longer accepted and return a 400. Use the stable field (chains.balance, apps.balance, tokens.balance, labels.value) with the matching qualifier property (chain_id, app_id, token_address, tag_id) instead. Balance fields support only the comparison operators (eq, neq, gt, gte, lt, lte); labels.value supports comparisons plus case-insensitive contains.

Field Reference

User Fields (users.*)

Filter by user engagement and profile data. Use the format users.{attribute}.

Profile Fields

Example - Find users with net worth > $10,000:
Example - Find high-volume users:

Engagement Fields

Example - Find mobile users from the US:

UTM & Referral Fields

Example - Find users from Google Ads campaign:

Lifecycle Filter

Filter by user lifecycle stage. Valid values: New, Returning, Power user, At Risk, Churned, Resurrected. Example - Find new and power users:

Social Fields

Social fields support two modes:
  • Presence checks: use notEmpty to match profiles where the field is set (or isEmpty for the opposite). The value is ignored.
  • Value matching: use eq, neq, or contains (case-insensitive substring) with a non-empty string to match the actual social value.
Example - Find users with any email present:
Example - Find users with both ENS and Farcaster present:
Example - Find users whose Twitter contains bob:
Example - Find an exact email match:

Chain Filters (chains.balance)

Filter by per-chain net worth using the stable field chains.balance and an optional chain_id qualifier. This is distinct from users.net_worth_usd, which compares the profile’s total net worth.

All Chains

Omit chain_id to filter across all chains (returns profiles where any chain matches). Example - Find users with >$1,000 on any chain:

Specific Chain

Set the chain_id qualifier to filter on a specific chain. Common chain IDs:
  • 1 - Ethereum Mainnet
  • 137 - Polygon
  • 42161 - Arbitrum One
  • 10 - Optimism
  • 8453 - Base
  • 56 - BNB Chain
  • 43114 - Avalanche
Example - Find users with >$5,000 on Ethereum:
Example - Find users with >$1,000 on both Ethereum and Polygon:

App Filters (apps.balance)

Filter by DeFi app balances using the stable field apps.balance with a required app_id qualifier and an optional chain_id qualifier.

All Chains

Omit chain_id to filter by app balance across all chains. Example - Find users with >$1,000 in Uniswap:

Specific Chain

Set the chain_id qualifier to filter by app balance on a specific chain. Example - Find users with >$500 in Aave on Ethereum:

Token Filters (tokens.balance)

Filter by token holdings using the stable field tokens.balance with required token_address and scope qualifiers, plus an optional chain_id and, for protocol scope, a required app_id.

Token Filter Qualifiers

All Chains

Omit chain_id to filter by token balance across all chains. Example - Find users holding >1000 USDC (any chain):

Specific Chain

Set the chain_id qualifier to filter by token balance on a specific chain. Example - Find users with >500 USDC on Ethereum:

Protocol-Specific Token Filters

Use scope: "protocol" with app_id to filter for tokens deposited in a specific DeFi protocol. Example - Find users with USDC deposited in Aave V3:
Example - Find users with ETH staked in Lido:

Label Filters (labels.value)

Filter by wallet labels using the stable field labels.value with a required tag_id qualifier (and an optional chain_id). Supported operators are the comparisons (eq, neq, gt, gte, lt, lte) and case-insensitive contains; the value must be non-empty. Common label tags:
  • coinbase.verified_account - Coinbase verified account (boolean)
  • coinbase.verified_country - Coinbase verified country code
  • coinbase.verified_coinbase_one - Coinbase One membership (boolean)
  • sanctions.designated - Sanctioned address (boolean)
  • passport.models_aggregate_score - Passport aggregate score (0-100)
  • passport.unique_humanity_score - Passport uniqueness score
Example - Find Coinbase verified users:
Example - Find US-verified Coinbase users:
Example - Find users with high Passport score:

Combined Filter Examples

High-Value Web3 Users

Find users with >$10,000 net worth, ENS name, and activity on Ethereum:

Active DeFi Users

Find users with activity in Uniswap or Aave:

Verified Power Users

Find Coinbase-verified power users from specific countries:

Multi-Chain Whales

Find users with significant holdings across multiple chains:

Response

The response is a paginated envelope of wallet profiles.

Response Fields

Profile Fields

Each profile in the data array includes:

Error Responses

Authorizations

Authorization
string
header
required

Workspace API key (e.g. formo_xxx). Create one in the Formo dashboard under Team Settings > API.

Query Parameters

address
string

Filter by wallet address. Accepts an EVM (0x...) or Solana address, or an ENS name (e.g. vitalik.eth) which is resolved to an address.

expand
string

Comma-separated: apps, chains, tokens, labels

timestamp
string<date-time>

Optional point in time for wallet-enrichment data. Requires the address query parameter; unbounded historical collection scans are rejected. Returns the wallet's stored base snapshot closest to this instant instead of its latest snapshot; an exact-distance tie chooses the later snapshot. Expanded chains, apps, and tokens come from the selected snapshot's profiling batch. Project engagement fields, project-defined identity overrides, and labels remain current. Must be ISO-8601 with a timezone.

order_by
enum<string>

Sort field

Available options:
net_worth_usd,
tx_count,
first_onchain,
last_onchain,
updated_at,
first_seen,
last_seen,
num_sessions,
revenue,
volume,
points
order_dir
enum<string>

Sort direction

Available options:
asc,
desc
page
integer
default:1

1-indexed page number (default 1).

Required range: x >= 1
size
integer
default:100

Page size (default 100, max 1000).

Required range: 1 <= x <= 1000

Body

application/json

Optional filter conditions

A profile-search filter group. filters contains canonical {field, op, value} leaves and logic combines them at this level.

filters
object[]
required
logic
enum<string>
default:and
Available options:
and,
or

Response

Paginated wallet profile search results.

Pagination cursor returned alongside data on every paginated list endpoint. Use these to walk pages: has_more is true while page * size < total. Combine with the matching Page and Size query parameters to request the next page.

page
integer
required

1-indexed page number echoed from the request.

size
integer
required

Page size echoed from the request.

total
integer
required

Total row count across all pages.

has_more
boolean
required

True when more pages remain (page * size < total).

data
object[]
required