# Privy data

Use Stripe Sigma or Stripe Data Pipeline to analyze Privy users, wallets, and asset balances.

Analyze your [Privy](https://www.privy.io) app users, wallets, and asset balances with [Stripe Sigma](https://docs.stripe.com/data/sigma.md) or [Stripe Data Pipeline](https://docs.stripe.com/data/access-data-in-warehouse.md). Use these datasets for SQL-based reports or warehouse analysis of user adoption, wallet inventory, or historical asset holdings.

The datasets contain data for Privy accounts and apps associated with your Stripe account and refresh on a daily batch schedule. Privy data is typically around 24 hours delayed. Delays can be longer depending on the data source and delivery destination. The datasets don’t provide real-time wallet information.

## Get access 

Privy data is available in private preview. Access requires an eligible Stripe plan and approval for the Stripe account associated with your Privy account.

1. Contact your Privy or Stripe account team to request access and confirm which Stripe account will receive your data.
2. After your account team enables access, query the tables in Sigma or configure a Data Pipeline destination to use them in your warehouse.
3. Find your tables in [Available data](https://docs.stripe.com/data/privy-analytical-data.md#available-data). See the [data schema guide](https://docs.stripe.com/data/schema.md) for how to browse tables and columns.

The SQL examples on this page use Sigma syntax. Adapt them to your warehouse’s SQL dialect when you use Data Pipeline.

> #### Test mode contains production Privy data
> 
> Stripe live mode and test mode contain the same production Privy data. Test mode doesn’t provide a separate dataset for Privy development apps.

## Available data 

The three tables cover different reporting needs. Users and wallets are current snapshots; wallet assets contain historical daily balances.

| Table | Contents |
| --- | --- |
| [privy_external_users](https://docs.stripe.com/data/privy-analytical-data.md#users) | Current non-deleted users by app, lifecycle and activity timestamps, and indicators for linked authentication methods and wallet types. |
| [privy_external_wallets](https://docs.stripe.com/data/privy-analytical-data.md#wallets) | Current wallet profiles by app and chain family, including custody, wallet type, and import or export state. |
| [privy_external_wallet_assets](https://docs.stripe.com/data/privy-analytical-data.md#wallet-assets) | Historical daily closing token quantities and USD balances for supported assets, with current wallet attribution and position metadata. |

All three tables include `privy_account_id`, `account_name`, `app_id`, and `app_name` to identify the Privy account and app. Account and app names reflect their current values.

## Users 

Each row in `privy_external_users` represents one current non-deleted user in an app, identified by `app_id` and `user_id`. The table includes:

- Lifecycle and activity fields such as `created_at`, `updated_at`, `last_active_at`, `last_accepted_terms_at`, and `is_imported`.
- Indicators for linked authentication methods, such as `has_email`, `has_phone`, `has_passkey`, `has_custom_jwt_signer`, `is_guest`, and social login indicators.
- Linked wallet indicators: `has_embedded_wallet`, `has_external_wallet`, and `has_smart_wallet`. `has_wallet` also refers specifically to an embedded wallet; `has_any_wallet_linked_account` covers all three wallet types.

The indicators describe active linked accounts, not whether a user has recently signed in. The table excludes deleted users and direct contact values such as email addresses and phone numbers.

The following example summarizes current users and selected linked account capabilities by app. It also counts users with recorded activity in the last 30 calendar days, including today:

```sql
SELECT
    app_id,
    app_name,
    count(*) AS current_users,
    count_if(date(last_active_at) BETWEEN date_add('day', -29, current_date) AND current_date) AS users_active_last_30_days,
    count_if(has_email) AS users_with_email,
    count_if(has_passkey) AS users_with_passkey,
    count_if(has_embedded_wallet) AS users_with_embedded_wallet,
    count_if(has_external_wallet) AS users_with_external_wallet
FROM privy_external_users
GROUP BY 1, 2
ORDER BY current_users DESC
```

`current_users` counts the current non-deleted snapshot, not recently active users. Use `last_active_at` to define an activity window, taking the dataset’s delivery delay into account.

## Wallets 

Each row in `privy_external_wallets` represents one current wallet profile for an app, identified by `app_id`, `wallet_address`, and `chain_type`. The table includes:

- The public wallet address and chain family, such as `evm` or `solana`.
- Wallet classifications in `wallet_type`, `wallet_shape`, and `custody_category`, plus `is_bridge_owned` and `is_tee` indicators.
- Connection, import, and export fields: `first_connected_at`, `first_imported_at`, `first_exported_at`, `is_imported`, and `is_exported`.

The following example summarizes wallet profiles by app, chain family, wallet type, and custody category:

```sql
SELECT
    app_id,
    app_name,
    chain_type,
    wallet_type,
    custody_category,
    count(*) AS wallets,
    count_if(is_imported) AS imported_wallets,
    count_if(is_exported) AS exported_wallets
FROM privy_external_wallets
GROUP BY 1, 2, 3, 4, 5
ORDER BY wallets DESC
```

This table doesn’t include a user-to-wallet mapping. Joining users and wallets on `app_id` alone matches every user to every wallet in the app, rather than identifying which wallets belong to a user.

## Wallet assets 

Each row in `privy_external_wallet_assets` represents one daily closing balance, identified by `app_id`, `wallet_address`, `balance_date`, `chain`, and `token_address`. The table includes:

- The balance’s UTC date in `balance_date`, the blockchain network in `chain` and `chain_id`, and token identifiers in `token_address` and `token_name`.
- Token quantities and USD values in `token_balance` and `usd_balance`, plus `is_stablecoin` classification.
- Current wallet attributes: `current_wallet_type`, `current_wallet_shape`, `current_custody_category`, `is_currently_bridge_owned`, and `is_currently_tee`.
- Position and valuation metadata: `position_type`, `valuation_source`, `wrapper_nav_per_share_usd`, `curator_vault_address`, and `underlying_token_address`.

The following example summarizes daily USD balances for the last 30 completed calendar days. It groups balances by app, chain, token, and position type:

```sql
SELECT
    date(balance_date) AS balance_date,
    app_id,
    app_name,
    chain,
    token_address,
    token_name,
    position_type,
    count(DISTINCT wallet_address) AS wallets,
    sum(usd_balance) AS total_usd_balance
FROM privy_external_wallet_assets
WHERE balance_date >= date_add('day', -30, current_date)
    AND balance_date < current_date
GROUP BY 1, 2, 3, 4, 5, 6, 7
ORDER BY balance_date DESC, total_usd_balance DESC
```

When interpreting asset balances:

- The table includes only positive balances that pass Privy’s asset filters. Privy filters reported assets using token verification, market liquidity, trading volume, and valuation checks to reduce spam and anomalous balances. A missing row doesn’t necessarily mean a zero balance.
- Use `balance_date` to identify the date represented by each balance. The most recent dates might not yet be available.
- Historical balances use current wallet and app attribution. They don’t preserve historical ownership changes.
- Rows with `position_type = 'yield_wrapper_share'` represent wrapper shares held by a wallet. The `underlying_token_address` and `curator_vault_address` fields describe the position. They aren’t additional balances, so don’t add them to the position’s value.
- Coverage is limited to supported assets held by Privy-tracked wallets. A Bridge-owned wallet can appear when its address is in the Privy wallet registry, but this table isn’t a complete Bridge ledger.
