Skip to content

Integration Guide

This guide shows how to integrate ValidonX license validation and activation into your application using PHP and JavaScript.

PHP Integration

License Validation

php
<?php

class ValidonX
{
    private string $apiKey;
    private string $baseUrl;

    public function __construct(string $apiKey, string $baseUrl = 'https://api.validonx.com/api')
    {
        $this->apiKey = $apiKey;
        $this->baseUrl = $baseUrl;
    }

    public function validateLicense(string $licenseKey): array
    {
        $ch = curl_init("{$this->baseUrl}/v1/integration/licenses/{$licenseKey}/validate");
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-API-Key: {$this->apiKey}",
                'Content-Type: application/json',
            ],
        ]);

        $response = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $data = json_decode($response, true);

        if ($status !== 200) {
            throw new \Exception($data['error']['message'] ?? 'License validation failed');
        }

        return $data['data'];
    }

    // $instanceId (required): a stable, unique per-install seat identity.
    // $deviceFingerprint (optional, recommended): a hash of hardware identifiers
    // recorded with the activation. instance_id is client-chosen, so a
    // hardware-derived fingerprint gives each seat an auditable device identity.
    public function createActivation(string $licenseKey, string $instanceId, ?string $deviceFingerprint = null, array $metadata = []): array
    {
        $payload = [
            'license_key' => $licenseKey,
            'instance_id' => $instanceId,
            'metadata' => $metadata,
        ];
        if ($deviceFingerprint !== null) {
            $payload['device_fingerprint'] = $deviceFingerprint;
        }

        $ch = curl_init("{$this->baseUrl}/v1/integration/activations");
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-API-Key: {$this->apiKey}",
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS => json_encode($payload),
        ]);

        $response = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $data = json_decode($response, true);

        if ($status !== 201 && $status !== 200) {
            throw new \Exception($data['error']['message'] ?? 'Activation failed');
        }

        return $data['data'];
    }

    public function checkEntitlements(array $codes): array
    {
        $ch = curl_init("{$this->baseUrl}/v1/integration/entitlements/check");
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-API-Key: {$this->apiKey}",
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS => json_encode(['entitlement_codes' => $codes]),
        ]);

        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true)['data'] ?? [];
    }
}

// Usage
$vx = new ValidonX('vx_your-api-key');

// Validate license
$result = $vx->validateLicense('XXXX-XXXX-XXXX-XXXX');
if ($result['valid']) {
    echo "License is valid!\n";
    echo "Plan: " . ($result['license']['entitlements']['plan'] ?? 'none') . "\n";
}

// Activate on this device
$activation = $vx->createActivation(
    'XXXX-XXXX-XXXX-XXXX',
    // required: a stable, unguessable instance id — generate once per install
    // (e.g. a random UUID) and persist it; don't reuse a shared/guessable value.
    '3f9c2e1a-7b4d-4c8a-9e2f-6d1b0a5e8c74',
    hash('sha256', php_uname()),      // optional but recommended: device fingerprint
    ['app_version' => '2.0.0']
);
echo "Activation ID: " . $activation['activation']['id'] . "\n";

JavaScript / Node.js Integration

javascript
class ValidonX {
  constructor(apiKey, baseUrl = 'https://api.validonx.com/api') {
    this.apiKey = apiKey;
    this.baseUrl = baseUrl;
  }

  async validateLicense(licenseKey) {
    const res = await fetch(
      `${this.baseUrl}/v1/integration/licenses/${licenseKey}/validate`,
      {
        method: 'POST',
        headers: {
          'X-API-Key': this.apiKey,
          'Content-Type': 'application/json',
        },
      }
    );

    const json = await res.json();
    if (!res.ok) throw new Error(json.error?.message || 'Validation failed');
    return json.data;
  }

  // instanceId (required): stable, unique per-install seat identity.
  // deviceFingerprint (optional, recommended): hash of hardware identifiers
  // recorded with the activation. instance_id is client-chosen, so a
  // hardware-derived fingerprint gives each seat an auditable device identity.
  async createActivation(licenseKey, instanceId, deviceFingerprint = null, metadata = {}) {
    const body = { license_key: licenseKey, instance_id: instanceId, metadata };
    if (deviceFingerprint) body.device_fingerprint = deviceFingerprint;

    const res = await fetch(`${this.baseUrl}/v1/integration/activations`, {
      method: 'POST',
      headers: {
        'X-API-Key': this.apiKey,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(body),
    });

    const json = await res.json();
    if (!res.ok) throw new Error(json.error?.message || 'Activation failed');
    return json.data;
  }

  async checkEntitlements(codes) {
    const res = await fetch(
      `${this.baseUrl}/v1/integration/entitlements/check`,
      {
        method: 'POST',
        headers: {
          'X-API-Key': this.apiKey,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ entitlement_codes: codes }),
      }
    );

    const json = await res.json();
    return json.data;
  }
}

// Usage
const vx = new ValidonX('vx_your-api-key');

const result = await vx.validateLicense('XXXX-XXXX-XXXX-XXXX');
console.log('Valid:', result.valid);
console.log('Plan:', result.license?.entitlements?.plan);

const activation = await vx.createActivation(
  'XXXX-XXXX-XXXX-XXXX',
  // required: stable, unguessable instance id generated once per install
  // (e.g. crypto.randomUUID()) and persisted — not a shared/guessable value.
  '3f9c2e1a-7b4d-4c8a-9e2f-6d1b0a5e8c74',
  'sha256-of-hardware-ids',   // optional but recommended: device fingerprint
  { app_version: '2.0.0', os: 'Linux' }
);
console.log('Activation ID:', activation.activation.id);

Error Handling

All errors follow the standard envelope format. Always check for error responses:

javascript
try {
  const result = await vx.validateLicense(key);
} catch (error) {
  // error.message contains the human-readable error
  // Common codes: LICENSE.NOT_FOUND, LICENSE.REVOKED, RATE_LIMIT.EXCEEDED
}

Rate Limiting

Check response headers to monitor your rate limit status:

javascript
const res = await fetch(url, options);
const remaining = res.headers.get('X-RateLimit-Remaining');
const limit = res.headers.get('X-RateLimit-Limit');
console.log(`${remaining}/${limit} requests remaining`);

If you receive a 429 response, wait for the Retry-After seconds before retrying.