Skip to main content
This page describes how partner applications can integrate with Proof to verify users. Partners can redirect users to Proof for verification and query the Proof API to check verification status.

Integration Overview

Deep Linking

Partners can redirect users to Proof with pre-populated data to streamline the verification flow. When the user completes verification, they are redirected back to your application.
ParameterRequiredDescription
walletYesThe Solana wallet address to link
signatureYesPre-signed ownership proof (base58 encoded)
timestampYesUnix timestamp in milliseconds when signature was created
redirect_uriYesURL to redirect the user after verification
emailNoEmail address to prefill in the authentication step
projectIdNoYour project identifier for tracking
Redirect URIs must use https: or chrome-extension: schemes. Custom URL schemes (e.g. myapp://) are not supported and the redirect will not fire. Native mobile apps should use universal links (iOS) or app links (Android), which use https: URLs that deep link into your app.
Build the deep link URL with query parameters:
https://dflow.net/proof?wallet={address}&signature={signature}&timestamp={timestamp}&redirect_uri={encodedRedirectUri}&email={encodedEmail}

Generating the Signature

The user must sign a message proving wallet ownership. The message format is:
Proof KYC verification: {timestamp}
Where {timestamp} is the Unix timestamp in milliseconds (13 digits).
import { Connection, PublicKey } from "@solana/web3.js";
import bs58 from "bs58";

async function createProofDeepLink(
  wallet: { publicKey: PublicKey; signMessage: (message: Uint8Array) => Promise<Uint8Array> },
  redirectUri: string
): Promise<string> {
  // Generate timestamp in milliseconds
  const timestamp = Date.now();
  
  // Create the message to sign
  const message = `Proof KYC verification: ${timestamp}`;
  const messageBytes = new TextEncoder().encode(message);
  
  // Request signature from wallet
  const signatureBytes = await wallet.signMessage(messageBytes);
  const signature = bs58.encode(signatureBytes);
  
  // Build the deep link URL
  const params = new URLSearchParams({
    wallet: wallet.publicKey.toBase58(),
    signature,
    timestamp: timestamp.toString(),
    redirect_uri: redirectUri,
  });
  
  return `https://dflow.net/proof?${params.toString()}`;
}

// Usage
const deepLink = await createProofDeepLink(wallet, "https://yourapp.com/callback");
window.location.href = deepLink;

Handling the Return

When the user completes verification (or cancels), they are redirected to your redirect_uri. Query the verification API to confirm their status. When verification succeeds, Proof also sends an “Identity Verification Complete” email to the user.
async function handleProofCallback(walletAddress: string): Promise<boolean> {
  const response = await fetch(
    `https://proof.dflow.net/verify/${walletAddress}`
  );
  const { verified } = await response.json();
  return verified;
}

Verification API

The verification API lets you check if a wallet address is linked to a verified identity. This is a public endpoint that does not require authentication.

Endpoint

GET https://proof.dflow.net/verify/{address}

Parameters

ParameterLocationTypeDescription
addresspathstringSolana wallet address (32-44 characters)

Response

{
  "verified": true
}
FieldTypeDescription
verifiedbooleanWhether the wallet is linked to a verified identity

Example: Checking Verification Status

async function isWalletVerified(address: string): Promise<boolean> {
  const response = await fetch(
    `https://proof.dflow.net/verify/${address}`
  );
  
  if (!response.ok) {
    throw new Error(`Failed to check verification: ${response.status}`);
  }
  
  const { verified } = await response.json();
  return verified;
}

// Usage
const walletAddress = "DFlow1111111111111111111111111111111111111";
const verified = await isWalletVerified(walletAddress);

if (verified) {
  console.log("Wallet is verified");
} else {
  console.log("Wallet is not verified");
}

Example: Gating Features

async function handleRestrictedAction(walletAddress: string) {
  const verified = await isWalletVerified(walletAddress);
  
  if (!verified) {
    // Redirect to Proof for verification
    const redirectUri = encodeURIComponent(window.location.href);
    window.location.href = `https://dflow.net/proof?redirect_uri=${redirectUri}`;
    return;
  }
  
  // User is verified, proceed with action
  await performRestrictedAction();
}

Integration Flow

Here’s a complete integration flow combining deep linking and the verification API:

Best Practices

Cache Verification Status

Verification status is stable once a user is verified. Consider caching the result to reduce API calls:
const verificationCache = new Map<string, boolean>();

async function isWalletVerified(address: string): Promise<boolean> {
  // Check cache first
  if (verificationCache.has(address)) {
    return verificationCache.get(address)!;
  }
  
  const response = await fetch(
    `https://proof.dflow.net/verify/${address}`
  );
  const { verified } = await response.json();
  
  // Cache verified status (don't cache unverified as it may change)
  if (verified) {
    verificationCache.set(address, true);
  }
  
  return verified;
}

Getting Prediction Market Order Quotes for Unverified Users

To show order quotes to unverified users, omit userPublicKey from /order requests.

Handle Edge Cases

  • Signature expiration: Generate fresh signatures close to redirect time
  • User cancellation: Handle cases where users return without completing verification
  • Network errors: Implement retry logic for API calls

Security Considerations

  • Always verify wallet ownership server-side when performing sensitive actions
  • Do not trust client-side verification status alone for security-critical operations
  • Use HTTPS for all API calls and redirects

API Reference

For complete API documentation, see the Proof API Reference:

Need Help?

https://mintcdn.com/dflow/a8Yx7HBusmKl4Z7w/images/meteor-icons_discord.svg?fit=max&auto=format&n=a8Yx7HBusmKl4Z7w&q=85&s=0ea834bc8a9fa3fe161ba181329effda

Join Our Discord

Connect with other developers, get help, and stay updated on the latest DFlow developments.
https://mintcdn.com/dflow/a8Yx7HBusmKl4Z7w/images/meteor-icons_telegram.svg?fit=max&auto=format&n=a8Yx7HBusmKl4Z7w&q=85&s=e928c5dd68311ff0d419936a35c86eed

Dev Notifications

Join the DFlow Dev Notifications Telegram group to stay in the loop on new features and other announcements.