What is Base Verify?
Base Verify allows users to prove ownership of verified accounts on X, Coinbase, Instagram, and TikTok without sharing credentials. Your app receives a deterministic token for Sybil resistance. Even if a wallet has few transactions, Base Verify reveals whether the user is high-value through their verified social accounts on X, Instagram, and TikTok or a Coinbase One subscription. This lets you identify quality users regardless of onchain activity. Example use cases:- Token-gated airdrops or daily rewards
- Exclusive content access (e.g., creator coins)
- Identity-based rewards and loyalty programs
Core concepts
Provider
An identity platform that Base Verify integrates with. Currently supports X, Coinbase, Instagram, and TikTok.Verification
Cryptographic proof that a wallet owns an account with a specific provider.Trait
A specific attribute of the provider account that can be verified. Examples:verified: true— X account has blue checkmarkcoinbase_one_active: true— active Coinbase One subscriptionfollowers: gt:1000— X account has over 1,000 followersfollowers_count: gte:5000— Instagram account with 5,000+ followersvideo_count: gte:50— TikTok account with 50+ videos
Action
A developer-defined string that identifies what the user is doing with their verification. Actions let you issue different tokens for different use cases within the same app. Examples:claim_daily_reward— claiming a daily rewardjoin_allowlist— joining an exclusive allowlistunlock_premium_content— accessing gated contentparticipate_in_raffle— entering a raffle
How actions work
Actions are specified in the Sign-In with Ethereum (SIWE) message resources:SIWE resources with action
Verification response with action
Why actions matter
Different actions produce different tokens. This enables multiple independent claims from the same verified account:- User verifies X account with action
claim_airdrop→ Token:abc123 - Same X account with action
join_allowlist→ Token:def456(different) - Same X account with action
claim_airdropagain → Token:abc123(same as first)
- Multiple campaigns — run separate airdrops without interference
- Feature gating — different tokens for different premium features
- Time-based events — new action per event (e.g.,
raffle_jan_2025,raffle_feb_2025)
Choosing action names
Use descriptive, lowercase names with underscores:| Good | Bad |
|---|---|
claim_genesis_airdrop | airdrop (too generic) |
unlock_pro_features | action1 (meaningless) |
enter_weekly_raffle | base_verify_token (reserved/confusing) |
Token — Sybil resistance
A deterministic identifier tied to the provider account, not the wallet. This is the key anti-Sybil mechanism.How it works
- Wallet A verifies an X account → Base Verify returns
Token: abc123→ you have never seen it, so grant the airdrop. - The same X account tries again with Wallet B → Base Verify returns
Token: abc123→ you have seen it, so block the duplicate claim.
Token properties
- Deterministic — the same provider account always produces the same token
- Unique per provider — a user’s X token is different from their Instagram token
- Unique per app — your app receives different tokens than other apps (privacy)
- Action-specific — tokens vary based on the action in your SIWE message
- Persistent — tokens don’t expire or rotate (unless the user deletes their verification)
- Trait-independent — tokens stay the same even if traits change (e.g., follower count increases)
How to store tokens
Verification token storage record
Prevent double claims
Prevent duplicate claims by token
Architecture and flow
Base Verify architecture and verification flow
Your app’s responsibilities
- Generate SIWE messages with trait requirements
- Handle user wallet connection
- Redirect to the Base Verify Mini App when verification is not found
- Store the returned verification token to prevent reuse
- Keep your secret key secure on the backend
Base Verify’s responsibilities
- Validate SIWE signatures
- Store provider verifications (X, Coinbase, Instagram, TikTok)
- Check if verification meets trait requirements
- Facilitate OAuth flow with providers
- Return deterministic tokens for Sybil resistance
Response codes
| Code | Meaning | Action |
|---|---|---|
| 200 OK | Wallet has verified the provider account AND meets all trait requirements. Returns a unique token. | Grant access, store the token. |
| 404 Not Found | Wallet has never verified this provider. | Redirect user to the Base Verify Mini App. |
400 Bad Request (verification_traits_not_satisfied) | Wallet has verified the provider, but doesn’t meet the trait requirements. | Show user they don’t meet requirements. Do not redirect. |
Getting started
Prerequisites
- API key — fill out the interest form to get access
- Wallet integration — users must be able to connect and sign messages. See Authenticate users or the web React quickstart
- Backend server — to securely call the Base Verify API and keep your secret key private. For a similar frontend-to-backend signing pattern, see Sign and verify typed data
Register your app
Provide the Base Verify team:- Your Mini App domain
- Your redirect URI — where users return after verification (e.g.,
https://yourapp.com)
Implementation
Configure your app
Create a configuration file for your Base Verify integration:Add your secret key to
lib/config.ts
.env.local:.env.local
Generate the SIWE signature (frontend)
Build a SIWE message that includes the provider, trait requirements, and action:
lib/signature-generator.ts
Check verification (frontend → backend)
The frontend generates the signature and sends it to your backend, which calls the Base Verify API.Frontend:Backend (your API endpoint):
Frontend verification check
pages/api/check-verification.ts
Redirect to Base Verify (frontend)
If you receive a 404 response, redirect the user to the Base Verify Mini App to complete OAuth:After verification, the user returns to your
Open the Base Verify Mini App
redirect_uri with ?success=true. Run the check again (step 3) and it now returns 200 with a token. If you’re building for the Base app, see the Mini apps overview for broader app structure and lifecycle guidance.Error handling
| Response | What to do |
|---|---|
| 404 | User hasn’t verified. Redirect to the Base Verify Mini App. |
400 (verification_traits_not_satisfied) | User has account but doesn’t meet requirements. Show a message — don’t redirect and don’t retry. |
| 200 | Store the token and grant access. |
Do not retry 404 responses — the user simply hasn’t verified yet. Do not retry 400 responses with
verification_traits_not_satisfied — retrying won’t help unless the user’s account metrics change (e.g., they gain more followers).API reference
Authentication
All API requests require your secret key in theAuthorization header:
Authorization header
POST /v1/base_verify_token
Check if a wallet has a specific verification and retrieve the verification token.Request
POST /v1/base_verify_token request body
Example request
POST /v1/base_verify_token cURL example
Responses
200 OK — verified:200 OK response
| Field | Type | Description |
|---|---|---|
token | string | Deterministic verification token for Sybil resistance. Same provider account + same action = same token. |
action | string | The custom action specified in the SIWE message. Different actions produce different tokens. |
wallet | string | User’s wallet address. |
404 not found response
400 traits not satisfied response
401 unauthorized response
Mini App redirect
To redirect users to Base Verify for verification:Base Verify redirect URL format
| Parameter | Required | Description | Example |
|---|---|---|---|
redirect_uri | Yes | Where to send the user after verification | https://yourapp.com |
providers | Yes | Provider to verify | x, coinbase, instagram, tiktok |
Trait catalog
Traits are specific attributes of a provider account that you can verify. They are specified in SIWE message resources using this format:Trait resource format
Operations
| Operation | Symbol | Applies to | Description | Example |
|---|---|---|---|---|
| Equals | eq | All types | Exact match | verified:eq:true |
| Greater than | gt | Integers | Strictly greater | followers:gt:1000 |
| Greater/equal | gte | Integers | Greater or equal | followers:gte:1000 |
| Less than | lt | Integers | Strictly less | followers:lt:5000 |
| Less/equal | lte | Integers | Less or equal | followers:lte:5000 |
| In (list) | in | Strings | Value in comma-separated list | verified_type:in:blue,government |
Type system
Boolean traits:- Values:
"true"or"false"(as strings) - Only supports
eqoperation - Example:
verified:eq:true
- Values: numbers as strings
- Supports:
eq,gt,gte,lt,lte - Example:
followers:gte:1000
- Values: text strings
- Supports:
eq,in - Example:
verified_type:eq:blueorverified_type:in:blue,government
Combining traits
When you specify multiple traits for the same provider, all must be satisfied (AND logic):Multiple traits for one provider
You can only check one provider per request. To check multiple providers, make separate API calls.
Common patterns
Tiered access:Tiered access trait rules
Coinbase
Provider:coinbase (Coinbase)
| Trait | Type | Operations | Description | Example values |
|---|---|---|---|---|
coinbase_one_active | Boolean | eq | Active Coinbase One subscription | "true", "false" |
coinbase_one_billed | Boolean | eq | User has been billed for Coinbase One | "true", "false" |
Coinbase trait examples
X
Provider:x (X)
| Trait | Type | Operations | Description | Example values |
|---|---|---|---|---|
verified | Boolean | eq | Has any type of verification | "true", "false" |
verified_type | String | eq | Type of verification | "blue", "government", "business", "none" |
followers | Integer | eq, gt, gte, lt, lte | Number of followers | "1000", "50000" |
X trait examples
instagram (Instagram)
| Trait | Type | Operations | Description | Example values |
|---|---|---|---|---|
username | String | eq | Instagram username | "john_doe" |
followers_count | Integer | eq, gt, gte, lt, lte | Number of followers | "1000", "50000" |
instagram_id | String | eq | Unique Instagram user ID | "1234567890" |
Instagram trait examples
TikTok
Provider:tiktok (TikTok)
| Trait | Type | Operations | Description | Example values |
|---|---|---|---|---|
open_id | String | eq | TikTok Open ID (unique per app) | "abc123..." |
union_id | String | eq | TikTok Union ID (unique across apps) | "def456..." |
display_name | String | eq | TikTok display name | "John Doe" |
follower_count | Integer | eq, gt, gte, lt, lte | Number of followers | "1000", "50000" |
following_count | Integer | eq, gt, gte, lt, lte | Number of accounts following | "500", "2000" |
likes_count | Integer | eq, gt, gte, lt, lte | Total likes received | "10000", "100000" |
video_count | Integer | eq, gt, gte, lt, lte | Number of videos posted | "50", "200" |
TikTok trait examples
Security and privacy
SIWE signature requirement
Every API call requires a valid SIWE signature from the wallet owner. This prevents:- Arbitrary lookup of verification status
- Third parties checking if a wallet is verified
- Enumeration attacks
SIWE payload example
Validate trait requirements
Example attack without validation:- Your app requires users to have 100 followers
- User modifies the frontend to request only 10 followers
- User signs the modified message
- Without validation, your backend forwards the request to Base Verify
- User gains access with fewer than 100 followers
Validate traits on the backend
Protect your secret key
Never:- Include the secret key in frontend code
- Use
NEXT_PUBLIC_*or similar environment variables that expose to the browser - Commit secret keys to version control
- Share secret keys in chat, email, or documentation
- Store the secret key in backend environment variables only
- Use
.envfiles that are gitignored - Rotate keys immediately if accidentally exposed
- Call the Base Verify API only from your backend
OAuth security model
Base Verify validates provider accounts through OAuth:- User initiates OAuth in the Base Verify Mini App
- Provider (X, Instagram, etc.) authenticates the user
- Provider returns an OAuth token to Base Verify
- Base Verify fetches account data using the OAuth token
- Base Verify stores the verification linked to the user’s wallet
- OAuth token is encrypted and stored securely
Data storage
What Base Verify stores:- Wallet addresses associated with verified provider accounts
- Provider account metadata (username, follower counts, verification status)
- OAuth tokens (encrypted, never shared with apps)
- Verification timestamps
- Users’ private keys
- Provider account passwords
- User activity or browsing history
- Any data beyond what’s needed for verification
/v1/base_verify_token, you receive only token, action, and wallet. No PII is returned.
User control
Users can delete their verifications at any time:- Removes all stored provider data
- Invalidates future token generation
- Your app’s stored tokens become meaningless (user can’t re-verify with the same account)
Caching
Cache verification results to reduce API calls:- Cache for the user’s session (not permanently)
- Clear cache when the user disconnects their wallet
- Don’t check verification on every page load