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

# Integration Guide

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

<Info>
  Using an AI coding agent? The [`dflow-proof-kyc` skill](https://github.com/DFlowProtocol/dflow-skills/blob/main/skills/dflow-proof-kyc/SKILL.md) teaches Claude Code to build a Proof integration end-to-end. See [Agent Skills](/ai/agent-skills).
</Info>

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;
}
```

### Showing Order Quotes to 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
