> ## Documentation Index
> Fetch the complete documentation index at: https://pond.dflow.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Proof KYC Partner Integration

> How to integrate Proof into your application with deep linking and the verification API

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

```mermaid theme={null}
flowchart LR
    subgraph partner [Partner App]
        A[User Action] --> B[Check Verification]
        B --> C{Verified?}
        C -->|No| D[Redirect to Proof]
        C -->|Yes| E[Allow Action]
    end
    
    subgraph proof [Proof]
        D --> F[User Verifies]
        F --> G[Redirect Back]
    end
    
    G --> B
```

## 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.

### Deep Link Parameters

| Parameter      | Required | Description                                               |
| -------------- | -------- | --------------------------------------------------------- |
| `wallet`       | Yes      | The Solana wallet address to link                         |
| `signature`    | Yes      | Pre-signed ownership proof (base58 encoded)               |
| `timestamp`    | Yes      | Unix timestamp in milliseconds when signature was created |
| `redirect_uri` | Yes      | URL to redirect the user after verification               |
| `email`        | No       | Email address to prefill in the authentication step       |
| `projectId`    | No       | Your project identifier for tracking                      |

<Info>
  **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](https://developer.apple.com/ios/universal-links/) (iOS) or [app links](https://developer.android.com/training/app-links) (Android), which use `https:` URLs that deep link into your app.
</Info>

### Constructing a Deep Link

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).

### Example: Creating a Deep Link

```typescript theme={null}
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.

```typescript theme={null}
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

| Parameter | Location | Type   | Description                              |
| --------- | -------- | ------ | ---------------------------------------- |
| `address` | path     | string | Solana wallet address (32-44 characters) |

### Response

```json theme={null}
{
  "verified": true
}
```

| Field      | Type    | Description                                         |
| ---------- | ------- | --------------------------------------------------- |
| `verified` | boolean | Whether the wallet is linked to a verified identity |

### Example: Checking Verification Status

```typescript theme={null}
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

```typescript theme={null}
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:

```mermaid theme={null}
sequenceDiagram
    participant User
    participant PartnerApp as Partner App
    participant Wallet
    participant Proof
    
    User->>PartnerApp: Initiate restricted action
    PartnerApp->>Proof: GET /verify/{address}
    Proof->>PartnerApp: { verified: false }
    
    PartnerApp->>User: Request wallet signature
    User->>Wallet: Sign verification message
    Wallet->>User: Signature
    User->>PartnerApp: Provide signature
    
    PartnerApp->>Proof: Redirect with deep link
    Note over Proof: User completes verification
    Proof->>PartnerApp: Redirect to redirect_uri
    
    PartnerApp->>Proof: GET /verify/{address}
    Proof->>PartnerApp: { verified: true }
    PartnerApp->>User: Allow restricted action
```

## Best Practices

### Cache Verification Status

Verification status is stable once a user is verified. Consider caching the result to reduce API calls:

```typescript theme={null}
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`](/resources/trading-api/order/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](/resources/proof-api/verify-address):

* [Verify Address](/resources/proof-api/verify-address) — Check if a wallet is verified
