Skip to main content
POST
/
v0
/
profiles
curl --request POST \
  --url https://api.formo.so/v0/profiles \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "conditions": [
    {
      "field": "users.net_worth_usd",
      "op": "gt",
      "value": 10000
    }
  ],
  "logic": "and"
}
'
{
"data": [
{
"address": "0x9CC3cB28cd94eB4423B15cdA73346e204f59a407",
"net_worth_usd": 125000.5,
"ens": "vitalik.eth",
"farcaster": null,
"lens": null,
"basenames": null,
"linea": null,
"discord": null,
"telegram": null,
"website": "https://example.com",
"github": "username",
"twitter": "username",
"linkedin": null,
"email": null,
"instagram": null,
"facebook": null,
"tiktok": null,
"youtube": null,
"reddit": null,
"avatar": "https://example.com/avatar.png",
"description": "Wallet description",
"display_name": "Display Name",
"updated_at": "2025-01-20T14:22:00Z",
"tx_count": 1234,
"first_onchain": "2024-01-15T10:30:00Z",
"last_onchain": "2025-01-20T14:22:00Z",
"lifecycle": "Returning"
}
],
"meta": {
"total": 150,
"limit": 100,
"offset": 0
}
}
Search and filter wallet profiles across your project with advanced filtering capabilities. Returns a paginated list of wallet profiles matching the specified criteria.

Authentication

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

Query Parameters

address

Filter by a specific wallet address (exact match).
curl -sS -X POST \
  -H "Authorization: Bearer <your_workspace_api_key>" \
  "https://api.formo.so/v0/profiles?address=0x1234..."

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
curl -sS -X POST \
  -H "Authorization: Bearer <your_workspace_api_key>" \
  "https://api.formo.so/v0/profiles?expand=apps,chains,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

limit

Maximum number of profiles to return per request.
  • Default: 100
  • Maximum: 1000

offset

Number of profiles to skip for pagination.
  • Default: 0

Request Body (Filters)

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

Filter Schema

{
  "conditions": [
    {
      "field": "users.net_worth_usd",
      "op": "gt",
      "value": 1000
    }
  ],
  "logic": "and"
}
FieldTypeDescription
conditionsarrayArray of filter conditions
logicstringHow to combine conditions: and (all must match) or or (any must match). Default: and

Filter Condition

Each condition in the conditions array has:
FieldTypeDescription
fieldstringThe field path to filter on (see Field Reference below)
opstringThe comparison operator
valuestring | number | boolean | arrayThe value to compare against
scopestring(Optional) Only for token filters: any (wallet + protocols) or protocol (specific protocol only)
appIdstring(Optional) Only for token filters with scope: "protocol". The DeFi protocol ID (e.g., aave-v3, compound-v3)

Operators

OperatorDescriptionExample
eqEquals{"field": "users.device", "op": "eq", "value": "Desktop"}
neqNot equals{"field": "users.os", "op": "neq", "value": "Windows"}
gtGreater than{"field": "users.net_worth_usd", "op": "gt", "value": 1000}
gteGreater than or equal{"field": "users.tx_count", "op": "gte", "value": 100}
ltLess than{"field": "users.net_worth_usd", "op": "lt", "value": 50000}
lteLess than or equal{"field": "chains.1.balance", "op": "lte", "value": 10000}
inIn array{"field": "users.lifecycle", "op": "in", "value": ["New", "Power user"]}
ninNot in array{"field": "users.location", "op": "nin", "value": ["US", "UK"]}

Field Reference

User Fields (users.*)

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

Profile Fields

FieldTypeDescription
users.net_worth_usdnumberTotal net worth in USD
users.tx_countnumberTotal transaction count
Example - Find users with net worth > $10,000:
{
  "conditions": [
    { "field": "users.net_worth_usd", "op": "gt", "value": 10000 }
  ],
  "logic": "and"
}

Engagement Fields

FieldTypeDescription
users.devicestringDevice type (e.g., Desktop, Mobile)
users.browserstringBrowser name (e.g., Chrome, Safari)
users.osstringOperating system (e.g., macOS, Windows)
users.locationstringCountry code (e.g., US, NG)
Example - Find mobile users from the US:
{
  "conditions": [
    { "field": "users.device", "op": "eq", "value": "Mobile" },
    { "field": "users.location", "op": "eq", "value": "US" }
  ],
  "logic": "and"
}

UTM & Referral Fields

FieldTypeDescription
users.first_utm_sourcestringFirst UTM source
users.last_utm_sourcestringLast UTM source
users.first_utm_mediumstringFirst UTM medium
users.last_utm_mediumstringLast UTM medium
users.first_utm_campaignstringFirst UTM campaign
users.last_utm_campaignstringLast UTM campaign
users.first_utm_contentstringFirst UTM content
users.last_utm_contentstringLast UTM content
users.first_utm_termstringFirst UTM term
users.last_utm_termstringLast UTM term
users.first_referrerstringFirst referrer domain
users.last_referrerstringLast referrer domain
users.first_referrer_urlstringFirst referrer full URL
users.last_referrer_urlstringLast referrer full URL
users.first_refstringFirst referral code
users.last_refstringLast referral code
Example - Find users from Google Ads campaign:
{
  "conditions": [
    { "field": "users.first_utm_source", "op": "eq", "value": "google" },
    { "field": "users.first_utm_medium", "op": "eq", "value": "cpc" }
  ],
  "logic": "and"
}

Lifecycle Filter

Filter by user lifecycle stage. Valid values: Churned, New, Power user, Resurrected, Returning.
FieldTypeDescription
users.lifecyclestringUser lifecycle stage
Example - Find new and power users:
{
  "conditions": [
    { "field": "users.lifecycle", "op": "in", "value": ["New", "Power user"] }
  ],
  "logic": "and"
}

Social Fields

Filter by presence of social identities. These check if the user has a non-empty value for the specified social field.
FieldDescription
users.ensENS name
users.farcasterFarcaster username
users.lensLens handle
users.basenamesBase names
users.lineaLinea identifier
users.discordDiscord username
users.telegramTelegram username
users.twitterTwitter/X handle
users.githubGitHub username
users.linkedinLinkedIn profile
users.emailEmail address
Example - Find users with ENS names:
{
  "conditions": [
    { "field": "users.ens", "op": "eq", "value": true }
  ],
  "logic": "and"
}
Example - Find users with both ENS and Farcaster:
{
  "conditions": [
    { "field": "users.ens", "op": "eq", "value": true },
    { "field": "users.farcaster", "op": "eq", "value": true }
  ],
  "logic": "and"
}

Chain Filters (chains.*)

Filter by per-chain net worth. Supports filtering across all chains or specific chains.

All Chains

Use chains.balance to filter across all chains (returns profiles where any chain matches). Example - Find users with >$1,000 on any chain:
{
  "conditions": [
    { "field": "chains.balance", "op": "gt", "value": 1000 }
  ],
  "logic": "and"
}

Specific Chain

Use chains.{chain_id}.balance 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:
{
  "conditions": [
    { "field": "chains.1.balance", "op": "gt", "value": 5000 }
  ],
  "logic": "and"
}
Example - Find users with >$1,000 on both Ethereum and Polygon:
{
  "conditions": [
    { "field": "chains.1.balance", "op": "gt", "value": 1000 },
    { "field": "chains.137.balance", "op": "gt", "value": 1000 }
  ],
  "logic": "and"
}

App Filters (apps.*)

Filter by DeFi app interactions and balances.

All Chains

Use apps.{app_id}.balance to filter by app balance across all chains. Example - Find users with >$1,000 in Uniswap:
{
  "conditions": [
    { "field": "apps.uniswap.balance", "op": "gt", "value": 1000 }
  ],
  "logic": "and"
}

Specific Chain

Use apps.{chain_id}.{app_id}.balance to filter by app balance on a specific chain. Example - Find users with >$500 in Aave on Ethereum:
{
  "conditions": [
    { "field": "apps.1.aave.balance", "op": "gt", "value": 500 }
  ],
  "logic": "and"
}

Token Filters (tokens.*)

Filter by token holdings. Supports optional scope and appId parameters.

Token Filter Parameters

ParameterTypeDescription
scopestringany (default) = wallet + all protocols, protocol = specific protocol only
appIdstringOnly for scope: "protocol". Specifies the DeFi protocol ID (e.g., aave-v3, compound-v3, uniswap-v3)

All Chains

Use tokens.{token_address}.balance to filter by token balance across all chains. Example - Find users holding >1000 USDC (any chain):
{
  "conditions": [
    {
      "field": "tokens.0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48.balance",
      "op": "gt",
      "value": 1000
    }
  ],
  "logic": "and"
}

Specific Chain

Use tokens.{chain_id}.{token_address}.balance to filter by token balance on a specific chain. Example - Find users with >500 USDC on Ethereum:
{
  "conditions": [
    {
      "field": "tokens.1.0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48.balance",
      "op": "gt",
      "value": 500
    }
  ],
  "logic": "and"
}

Protocol-Specific Token Filters

Use scope: "protocol" with appId to filter for tokens deposited in a specific DeFi protocol. Example - Find users with USDC deposited in any protocol:
{
  "conditions": [
    {
      "field": "tokens.0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48.balance",
      "op": "gt",
      "value": 0,
      "scope": "protocol"
    }
  ],
  "logic": "and"
}
Example - Find users with USDC deposited in Aave V3:
{
  "conditions": [
    {
      "field": "tokens.0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48.balance",
      "op": "gt",
      "value": 1000,
      "scope": "protocol",
      "appId": "aave-v3"
    }
  ],
  "logic": "and"
}
Example - Find users with ETH staked in Lido:
{
  "conditions": [
    {
      "field": "tokens.0x0000000000000000000000000000000000000000.balance",
      "op": "gt",
      "value": 1,
      "scope": "protocol",
      "appId": "lido"
    }
  ],
  "logic": "and"
}

Label Filters (labels.*)

Filter by wallet labels. Use the format labels.{tag_id}. Common label IDs:
  • 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:
{
  "conditions": [
    { "field": "labels.coinbase.verified_account", "op": "eq", "value": "true" }
  ],
  "logic": "and"
}
Example - Find US-verified Coinbase users:
{
  "conditions": [
    { "field": "labels.coinbase.verified_country", "op": "eq", "value": "US" }
  ],
  "logic": "and"
}
Example - Find users with high Passport score:
{
  "conditions": [
    { "field": "labels.passport.models_aggregate_score", "op": "gte", "value": "50" }
  ],
  "logic": "and"
}

Combined Filter Examples

High-Value Web3 Users

Find users with >$10,000 net worth, ENS name, and activity on Ethereum:
curl -sS -X POST \
  -H "Authorization: Bearer <your_workspace_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "conditions": [
      { "field": "users.net_worth_usd", "op": "gt", "value": 10000 },
      { "field": "users.ens", "op": "eq", "value": true },
      { "field": "chains.1.balance", "op": "gt", "value": 0 }
    ],
    "logic": "and"
  }' \
  "https://api.formo.so/v0/profiles?expand=chains,labels"

Active DeFi Users

Find users with activity in Uniswap or Aave:
curl -sS -X POST \
  -H "Authorization: Bearer <your_workspace_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "conditions": [
      { "field": "apps.uniswap.balance", "op": "gt", "value": 0 },
      { "field": "apps.aave.balance", "op": "gt", "value": 0 }
    ],
    "logic": "or"
  }' \
  "https://api.formo.so/v0/profiles?expand=apps"

Verified Power Users

Find Coinbase-verified power users from specific countries:
curl -sS -X POST \
  -H "Authorization: Bearer <your_workspace_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "conditions": [
      { "field": "labels.coinbase.verified_account", "op": "eq", "value": "true" },
      { "field": "labels.coinbase.verified_country", "op": "in", "value": ["US", "UK", "DE"] },
      { "field": "users.lifecycle", "op": "eq", "value": "Power user" }
    ],
    "logic": "and"
  }' \
  "https://api.formo.so/v0/profiles"

Multi-Chain Whales

Find users with significant holdings across multiple chains:
curl -sS -X POST \
  -H "Authorization: Bearer <your_workspace_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "conditions": [
      { "field": "chains.1.balance", "op": "gt", "value": 10000 },
      { "field": "chains.137.balance", "op": "gt", "value": 5000 },
      { "field": "chains.42161.balance", "op": "gt", "value": 5000 }
    ],
    "logic": "and"
  }' \
  "https://api.formo.so/v0/profiles?expand=chains&order_by=net_worth_usd&order_dir=desc"

Response

The response includes a data array of wallet profiles and a meta object with pagination information.
{
  "data": [
    {
      "address": "0x9CC3cB28cd94eB4423B15cdA73346e204f59a407",
      "net_worth_usd": 125000.5,
      "ens": "example.eth",
      "tx_count": 1234,
      "first_onchain": "2024-01-15T10:30:00Z",
      "last_onchain": "2025-01-20T14:22:00Z",
      "lifecycle": "Returning",
      // ... other profile fields
    }
  ],
  "meta": {
    "total": 150,
    "limit": 100,
    "offset": 0
  }
}

Response Fields

FieldTypeDescription
dataarrayArray of wallet profiles matching the search criteria
meta.totalintegerTotal number of profiles matching the criteria (before pagination)
meta.limitintegerMaximum number of profiles returned in this response
meta.offsetintegerNumber of profiles skipped (for pagination)

Profile Fields

Each profile in the data array includes:
FieldTypeDescription
addressstringWallet address
net_worth_usdnumberTotal net worth in USD
tx_countintegerTotal transaction count
first_onchainstringFirst on-chain activity timestamp (ISO 8601)
last_onchainstringLast on-chain activity timestamp (ISO 8601)
lifecyclestringUser lifecycle stage: Churned, New, Power user, Resurrected, Returning
ensstring | nullENS name
farcasterstring | nullFarcaster username
twitterstring | nullTwitter/X handle
discordstring | nullDiscord username
telegramstring | nullTelegram username
emailstring | nullEmail address
first_seenstring | nullFirst seen timestamp in your app
last_seenstring | nullLast seen timestamp in your app
num_sessionsinteger | nullTotal number of sessions
revenuenumber | nullTotal revenue
volumenumber | nullTotal volume
pointsnumber | nullTotal points
chainsarray | nullPer-chain data (when expanded)
appsarray | nullDeFi app data (when expanded)
tokensarray | nullToken holdings (when expanded)
labelsarray | nullWallet labels (when expanded)

Error Responses

StatusCodeDescription
400BAD_REQUESTInvalid query parameters or malformed JSON in request body
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENAPI key does not have profiles:read permission
500INTERNAL_SERVER_ERRORFailed to fetch wallet profile data

Authorizations

Authorization
string
header
required

Bearer token for authentication. Use an SDK Write Key for the Events API, or a Workspace API Key for the Query and Profile APIs. Format: 'Bearer '

Query Parameters

address
string

Filter by specific wallet address (exact match)

expand
string

Comma-separated list of additional data to include in each profile. Valid options: apps, chains, tokens, labels. Example: expand=apps,chains

order_by
enum<string>

Field to sort results by. Default: last_onchain

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

Sort direction. Default: desc

Available options:
asc,
desc
limit
integer
default:100

Maximum number of profiles to return. Default: 100, Maximum: 1000

Required range: 1 <= x <= 1000
offset
integer
default:0

Number of profiles to skip for pagination. Default: 0

Required range: x >= 0

Body

application/json

Filter configuration for searching wallet profiles

conditions
object[]

Array of filter conditions to apply

logic
enum<string>
default:and

How to combine multiple conditions: and (all must match) or or (any must match)

Available options:
and,
or

Response

Successfully retrieved wallet profiles

data
object[]
required

Array of wallet profiles matching the search criteria

meta
object
required