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:
| Parameter | Type | Required | Description |
|---|---|---|---|
license_key | string | Yes | The license key in LIC-XXXX-XXXX-XXXX-XXXX format |
domain | string | Yes | The 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:
| Reason | Meaning | Recommended Action |
|---|---|---|
invalid_key | The license key does not exist | Show error message directing user to check their key |
suspended | License temporarily disabled | Show notice to contact seller or Web3.Market support |
revoked | License permanently invalidated | Show notice to contact support |
expired | License has passed its expiration date | Show notice to renew the license |
invalid_domain | Current domain is not activated | Show 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.