Skip to main content

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
If you still need wallet connection or message signing in your app, start with Authenticate users, Sign and verify typed data, or the web React quickstart.

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 checkmark
  • coinbase_one_active: true — active Coinbase One subscription
  • followers: gt:1000 — X account has over 1,000 followers
  • followers_count: gte:5000 — Instagram account with 5,000+ followers
  • video_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 reward
  • join_allowlist — joining an exclusive allowlist
  • unlock_premium_content — accessing gated content
  • participate_in_raffle — entering a raffle

How actions work

Actions are specified in the Sign-In with Ethereum (SIWE) message resources:
SIWE resources with action
The action is returned in the API response:
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_airdrop again → Token: abc123 (same as first)
Use cases:
  • 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:
Once you launch with an action name, don’t change it. Changing the action generates different tokens for the same users, breaking your Sybil resistance.

Token — Sybil resistance

A deterministic identifier tied to the provider account, not the wallet. This is the key anti-Sybil mechanism.

How it works

  1. Wallet A verifies an X account → Base Verify returns Token: abc123 → you have never seen it, so grant the airdrop.
  2. The same X account tries again with Wallet B → Base Verify returns Token: abc123 → you have seen it, so block the duplicate claim.
Without Base Verify, users could claim multiple times with different wallets. With Base Verify, one verified account = one token = one 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 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


Getting started

Prerequisites

  1. API key — fill out the interest form to get access
  2. Wallet integration — users must be able to connect and sign messages. See Authenticate users or the web React quickstart
  3. 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:
  1. Your App domain
  2. Your redirect URI — where users return after verification (e.g., https://yourapp.com)
Your secret key must never be exposed in frontend code. All Base Verify API calls must go through your backend.

Implementation

1

Configure your app

Create a configuration file for your Base Verify integration:
lib/config.ts
Add your secret key to .env.local:
.env.local
2

Generate the SIWE signature (frontend)

Build a SIWE message that includes the provider, trait requirements, and action:
lib/signature-generator.ts
3

Check verification (frontend → backend)

The frontend generates the signature and sends it to your backend, which calls the Base Verify API.Frontend:
Frontend verification check
Backend (your API endpoint):
pages/api/check-verification.ts
Your backend must validate that the trait requirements in the SIWE message match what your backend expects. This prevents users from modifying trait requirements on the frontend to bypass your access controls. See security best practices for details.
4

Redirect to Base Verify (frontend)

If you receive a 404 response, redirect the user to the Base Verify App to complete OAuth:
Open the Base Verify App
After verification, the user returns to your 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 Apps overview for broader app structure and lifecycle guidance.

Error handling

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 the Authorization 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
404 Not Found — verification not found:
404 not found response
Redirect the user to the Base Verify App to complete verification. 400 Bad Request — traits not satisfied:
400 traits not satisfied response
The user has the provider account but doesn’t meet trait requirements. Do not redirect. 401 Unauthorized — invalid key:
401 unauthorized response
Check that your secret key is correct and included in the Authorization header.

App redirect

To redirect users to Base Verify for verification:
Base Verify redirect URL format

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

Type system

Boolean traits:
  • Values: "true" or "false" (as strings)
  • Only supports eq operation
  • Example: verified:eq:true
Integer traits:
  • Values: numbers as strings
  • Supports: eq, gt, gte, lt, lte
  • Example: followers:gte:1000
String traits:
  • Values: text strings
  • Supports: eq, in
  • Example: verified_type:eq:blue or verified_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)
Coinbase trait examples

X

Provider: x (X)
X trait examples

Instagram

Provider: instagram (Instagram)
Instagram trait examples

TikTok

Provider: tiktok (TikTok)
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
The user signs a structured message proving they control the wallet and agree to check specific traits:
SIWE payload example

Validate trait requirements

When your backend receives a SIWE message from the frontend, you must validate that the trait requirements in the message match what your backend expects. This prevents users from modifying trait requirements on the frontend to bypass your access controls.
Example attack without validation:
  1. Your app requires users to have 100 followers
  2. User modifies the frontend to request only 10 followers
  3. User signs the modified message
  4. Without validation, your backend forwards the request to Base Verify
  5. User gains access with fewer than 100 followers
Implementation:
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
Always:
  • Store the secret key in backend environment variables only
  • Use .env files 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:
  1. User initiates OAuth in the Base Verify App
  2. Provider (X, Instagram, etc.) authenticates the user
  3. Provider returns an OAuth token to Base Verify
  4. Base Verify fetches account data using the OAuth token
  5. Base Verify stores the verification linked to the user’s wallet
  6. OAuth token is encrypted and stored securely
Your app never handles OAuth tokens or redirects — this is all handled within the Base Verify App.

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
What Base Verify does not store:
  • Users’ private keys
  • Provider account passwords
  • User activity or browsing history
  • Any data beyond what’s needed for verification
What your app receives: When you call /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

Support

Want to integrate Base Verify? Fill out the interest form and the team will reach out with API access.