License SystemIntegration Guide

Integration Guide

This guide is for developers who have purchased a licensed product on Web3.Market and need to integrate the license verification call into their deployed dApp, or for sellers building verification into their product before listing it.

Quick Start

Get your license key

After purchasing a licensed product, go to your Dashboard and navigate to My Licenses. Copy your license key (format: LIC-XXXX-XXXX-XXXX-XXXX). See the Setup Guide for detailed instructions.

Activate your deployment domain

Register the domain where your dApp will run. You can do this from the dashboard or via the API:

curl -X POST https://verify.web3.market/activate \
  -H "Content-Type: application/json" \
  -d '{
    "license_key": "LIC-A3F9-K2M7-P8X1-Q4R6",
    "domain": "mydapp.com"
  }'

Add verification to your dApp

Add a license verification call to your dApp that runs on startup or page load. The following sections provide implementation examples for different environments.

Verification Endpoint

The verification endpoint accepts GET requests:

GET https://verify.web3.market/verify?license_key={KEY}&domain={DOMAIN}

Parameters:

ParameterTypeRequiredDescription
license_keystringYesThe license key in LIC-XXXX-XXXX-XXXX-XXXX format
domainstringYesThe domain to verify against

Success response (200):

{
  "valid": true,
  "license": {
    "expires_at": null
  }
}

Failure response (200):

{
  "valid": false,
  "error": "invalid_domain"
}

The endpoint always returns HTTP 200. Use the valid field to determine whether the license check passed.

Implementation Examples

This example runs in the browser and checks the license on page load. It uses window.location.hostname to automatically detect the current domain.

const LICENSE_KEY = 'LIC-A3F9-K2M7-P8X1-Q4R6';
 
async function verifyLicense() {
  const domain = window.location.hostname;
 
  try {
    const response = await fetch(
      `https://verify.web3.market/verify?license_key=${LICENSE_KEY}&domain=${domain}`
    );
    const data = await response.json();
 
    if (!data.valid) {
      console.error('License verification failed:', data.reason);
      // Handle invalid license — show notice, disable features, etc.
      showLicenseNotice(data.reason);
      return false;
    }
 
    // License is valid — proceed normally
    return true;
  } catch (error) {
    console.error('License verification request failed:', error);
    // Network error — handle gracefully (see best practices below)
    return true; // Fail open to avoid blocking users during outages
  }
}
 
// Run on page load
verifyLicense();
⚠️

Client-side verification is easier to implement but can be bypassed by a technically sophisticated user. For stronger protection, use server-side verification. See the Security Considerations section below.

Handling Verification Responses

Your integration should handle three scenarios:

1. License is valid

The API returns { "valid": true }. Your dApp should proceed normally. No user-facing action is needed.

2. License is invalid

The API returns { "valid": false, "reason": "..." }. The possible reasons and recommended actions:

ReasonMeaningRecommended Action
invalid_keyThe license key does not existShow error message directing user to check their key
suspendedLicense temporarily disabledShow notice to contact seller or Web3.Market support
revokedLicense permanently invalidatedShow notice to contact support
expiredLicense has passed its expiration dateShow notice to renew the license
invalid_domainCurrent domain is not activatedShow notice to activate domain at web3.market

3. Network error

The verification request fails due to a network issue, timeout, or API downtime. See best practices below for how to handle this gracefully.

Best Practices

Cache verification results

Do not call the verification endpoint on every page load or every request. Cache the result for a reasonable period (1 hour is recommended). This reduces latency for your users, lowers the load on the License API, and makes your dApp resilient to brief network interruptions.

// Example cache implementation
const CACHE_KEY = 'w3m_license_status';
const CACHE_TTL = 60 * 60 * 1000; // 1 hour
 
function getCachedResult() {
  const cached = localStorage.getItem(CACHE_KEY);
  if (!cached) return null;
 
  const { valid, timestamp } = JSON.parse(cached);
  if (Date.now() - timestamp > CACHE_TTL) return null;
 
  return valid;
}
 
function setCachedResult(valid) {
  localStorage.setItem(CACHE_KEY, JSON.stringify({
    valid,
    timestamp: Date.now()
  }));
}

Handle failures gracefully

If the verification request fails (network error, timeout, API downtime), your dApp should fail open rather than blocking the user. A user who has a valid license should not be locked out because of a temporary network issue. Use cached results when available, and only show a warning after repeated failures.

“Fail open” means treating a network error as a valid license and allowing the dApp to operate normally. This is the recommended approach because legitimate users should not be penalized by infrastructure issues. The tradeoff is acceptable because license checks will resume once connectivity is restored.

Do not block the UI on verification

Run the verification check asynchronously. Load your dApp’s interface immediately and perform the license check in the background. If the check fails, overlay a notice or disable certain features — but never show a blank screen while waiting for a verification response.

// Good: non-blocking verification
async function init() {
  renderApp(); // Show the UI immediately
  const isValid = await verifyLicense(); // Check in background
 
  if (!isValid) {
    showLicenseOverlay(); // Show notice over the UI
  }
}

Verify on startup, then periodically

The best pattern is to verify once when the dApp loads, cache the result, and re-verify periodically (every hour) or when the user performs a sensitive action. This balances protection with performance.

Security Considerations

Prefer server-side verification

Client-side verification (running in the browser) can be inspected and bypassed by modifying the JavaScript code. For stronger protection, perform verification on the server side where the code is not accessible to the end user.

With server-side verification:

  • The license key is stored in an environment variable, not in the client bundle
  • The verification logic runs in your backend, where it cannot be tampered with
  • The API response is evaluated by your server, which controls access to the application

Do not expose your license key in the client bundle

If you must use client-side verification, be aware that the license key will be visible in the page source or JavaScript bundle. While this does not allow someone to use your license (they would still need to activate it on their own domain), it does expose the key itself. For maximum security, keep the license key in server-side environment variables.

# Store your license key as an environment variable
export LICENSE_KEY="LIC-A3F9-K2M7-P8X1-Q4R6"
export DEPLOYMENT_DOMAIN="mydapp.com"

Use HTTPS

Always call the License API over HTTPS (which is the default verify.web3.market URL). This ensures the license key and verification response are encrypted in transit and cannot be intercepted or tampered with by a man-in-the-middle.

Combine with other protections

License verification is one layer of protection. For high-value products, consider combining it with:

  • Code obfuscation — Make it harder to locate and remove the verification logic
  • Server-side rendering — Keep sensitive logic on the server
  • Feature gating — Require a valid license only for premium features rather than the entire application
  • Integrity checks — Detect modifications to the verification code

No client-side protection is unbreakable. Domain-locked licensing raises the barrier to unauthorized use significantly, but determined actors with technical skills can potentially bypass it. Server-side verification provides the strongest protection.