Bulk Queries API

Validate, lookup, and search multiple licenses in a single API call. Query by activation key, customer email, or hardware ID.

Overview

The Bulk Queries API allows you to perform batch operations on licenses, reducing API calls and improving performance for enterprise applications.

Bulk Validate

Validate multiple licenses with hardware binding

POST /api/license/validate-bulk
Bulk Info

Get details for multiple activation keys

POST /api/license/bulk-info
Bulk by Hardware

Get licenses for multiple devices

POST /api/license/bulk-by-hardware

Use Cases

  • Enterprise dashboards displaying license status for multiple customers
  • CRM integrations syncing license data for customer accounts
  • Device management checking licenses across a fleet of machines
  • Batch validation at application startup for multi-license systems
  • Customer support tools looking up all licenses for a customer
Performance: Query up to 100 items in a single API call, reducing network overhead and improving response times.

Authentication

Include your API token in the Authorization header:

Authorization: ExisOneApi your-api-token

Required Permissions

Endpoint Required Permission
/api/license/validate-bulk verify
/api/license/bulk-info Any valid token
/api/license/bulk-by-email Any valid token
/api/license/bulk-by-hardware Any valid token

Endpoints

Bulk Validate Licenses

POST /api/license/validate-bulk

Validates multiple licenses against hardware IDs. Use this when you need to check if licenses are currently valid and active.

Request Body

{
  "licenses": [
    {
      "activationKey": "XXXX-XXXX-XXXX-XXXX",
      "hardwareId": "ABC123DEF456..."
    },
    {
      "activationKey": "YYYY-YYYY-YYYY-YYYY",
      "hardwareId": "DEF789GHI012..."
    },
    {
      "hardwareId": "GHI345JKL678...",
      "productName": "MyProduct"
    }
  ]
}

Response

{
  "results": [
    {
      "activationKey": "XXXX-XXXX-XXXX-XXXX",
      "hardwareId": "ABC123DEF456...",
      "isValid": true,
      "status": "licensed",
      "error": null,
      "expirationDate": "2026-01-01T23:59:59Z",
      "features": ["Feature1", "Feature2"]
    }
  ],
  "totalProcessed": 3,
  "successCount": 2,
  "failureCount": 1
}

Bulk Info by Activation Keys

POST /api/license/bulk-info

Gets detailed information for multiple licenses by their activation keys. Use this when you know the keys and need full license details.

Request Body

{
  "activationKeys": [
    "XXXX-XXXX-XXXX-XXXX",
    "YYYY-YYYY-YYYY-YYYY",
    "ZZZZ-ZZZZ-ZZZZ-ZZZZ"
  ]
}

Response

{
  "licenses": [
    {
      "activationKey": "XXXX-XXXX-XXXX-XXXX",
      "found": true,
      "email": "customer@example.com",
      "productName": "MyProduct",
      "productId": 123,
      "hardwareId": "ABC123...",
      "isActive": true,
      "activationDate": "2025-01-15T10:30:00Z",
      "expirationDate": "2026-01-15T23:59:59Z",
      "createdAt": "2025-01-10T08:00:00Z",
      "note": "Enterprise customer",
      "features": ["Feature1", "Feature2", "Pro"],
      "isCorporate": false,
      "maxSeats": null,
      "currentSeats": null,
      "corporateName": null,
      "isOffline": false
    },
    {
      "activationKey": "INVALID-KEY",
      "found": false
    }
  ],
  "totalRequested": 3,
  "foundCount": 2,
  "notFoundCount": 1
}

Bulk by Customer Email

POST /api/license/bulk-by-email

Gets all licenses for multiple customer email addresses. Use this for customer support tools or CRM integrations.

Request Body

{
  "emails": [
    "customer1@example.com",
    "customer2@example.com",
    "enterprise@company.com"
  ]
}

Response

{
  "customers": [
    {
      "email": "customer1@example.com",
      "licenses": [
        {
          "activationKey": "XXXX-XXXX-XXXX-XXXX",
          "found": true,
          "productName": "MyProduct",
          "isActive": true,
          "expirationDate": "2026-01-15T23:59:59Z",
          "features": ["Feature1", "Feature2"]
          // ... full license details
        },
        {
          "activationKey": "AAAA-AAAA-AAAA-AAAA",
          "found": true,
          "productName": "OtherProduct",
          "isActive": false,
          "expirationDate": "2024-06-01T23:59:59Z",
          "features": ["Basic"]
        }
      ],
      "licenseCount": 2
    },
    {
      "email": "newcustomer@example.com",
      "licenses": [],
      "licenseCount": 0
    }
  ],
  "totalCustomers": 3,
  "totalLicenses": 5
}

Bulk by Hardware ID

POST /api/license/bulk-by-hardware

Gets all licenses associated with multiple hardware IDs. Use this for device fleet management or multi-machine deployments.

Request Body

{
  "hardwareIds": [
    "ABC123DEF456GHI789...",
    "JKL012MNO345PQR678...",
    "STU901VWX234YZA567..."
  ]
}

Response

{
  "devices": [
    {
      "hardwareId": "ABC123DEF456GHI789...",
      "licenses": [
        {
          "activationKey": "XXXX-XXXX-XXXX-XXXX",
          "found": true,
          "email": "customer@example.com",
          "productName": "MyProduct",
          "isActive": true,
          "expirationDate": "2026-01-15T23:59:59Z",
          "features": ["Feature1", "Feature2"],
          "isCorporate": false
        }
      ],
      "licenseCount": 1
    },
    {
      "hardwareId": "JKL012MNO345PQR678...",
      "licenses": [
        {
          "activationKey": "CORP-XXXX-XXXX-XXXX",
          "found": true,
          "email": "enterprise@company.com",
          "productName": "MyProduct",
          "isActive": true,
          "isCorporate": true,
          "maxSeats": 50,
          "currentSeats": 23,
          "corporateName": "Acme Corporation"
        }
      ],
      "licenseCount": 1
    },
    {
      "hardwareId": "UNKNOWN-HARDWARE-ID",
      "licenses": [],
      "licenseCount": 0
    }
  ],
  "totalDevices": 3,
  "totalLicenses": 2
}

Response Fields

License Info Object

Field Type Description
activationKeystringThe license activation key
foundbooleanWhether the license was found in the system
emailstring?Customer email associated with the license
productNamestring?Name of the licensed product
productIdint?Internal product ID
hardwareIdstring?Hardware ID the license is bound to
isActivebooleanWhether the license is currently activated
activationDatedatetime?When the license was activated
expirationDatedatetime?When the license expires
createdAtdatetime?When the license was created
notestring?Admin notes on the license
featuresstring[]Array of enabled feature names
isCorporatebooleanWhether this is a multi-seat corporate license
maxSeatsint?Maximum allowed seats (corporate only)
currentSeatsint?Currently used seats (corporate only)
corporateNamestring?Company name (corporate only)
isOfflinebooleanWhether this is an offline license

Validation Status Codes

These status codes are returned by the /validate-bulk endpoint:

Status Valid Description
licensed Yes License is active and valid for this hardware
trial Yes Trial period is active
expired No License or trial has expired
invalid No License is invalid (hardware mismatch, inactive, etc.)
invalid_key No Activation key does not exist
invalid_product No Activation key is for a different product
trial_unavailable No Trial is not available for this product
invalid_request No Missing required fields in the request
error No An unexpected error occurred

Code Examples

using System.Net.Http;
using System.Net.Http.Json;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "ExisOneApi your-api-token");

// Bulk Validate
var validateRequest = new {
    licenses = new[] {
        new { activationKey = "XXXX-XXXX-XXXX-XXXX", hardwareId = "ABC123..." },
        new { activationKey = "YYYY-YYYY-YYYY-YYYY", hardwareId = "DEF456..." }
    }
};
var validateResponse = await client.PostAsJsonAsync(
    "https://api.exisone.com/api/license/validate-bulk", validateRequest);

// Bulk Info by Keys
var infoRequest = new {
    activationKeys = new[] { "XXXX-XXXX-XXXX-XXXX", "YYYY-YYYY-YYYY-YYYY" }
};
var infoResponse = await client.PostAsJsonAsync(
    "https://api.exisone.com/api/license/bulk-info", infoRequest);

// Bulk by Email
var emailRequest = new {
    emails = new[] { "customer1@example.com", "customer2@example.com" }
};
var emailResponse = await client.PostAsJsonAsync(
    "https://api.exisone.com/api/license/bulk-by-email", emailRequest);

// Bulk by Hardware
var hardwareRequest = new {
    hardwareIds = new[] { "ABC123...", "DEF456..." }
};
var hardwareResponse = await client.PostAsJsonAsync(
    "https://api.exisone.com/api/license/bulk-by-hardware", hardwareRequest);
import requests

headers = {
    "Authorization": "ExisOneApi your-api-token",
    "Content-Type": "application/json"
}
base_url = "https://api.exisone.com/api/license"

# Bulk Validate
validate_response = requests.post(f"{base_url}/validate-bulk", json={
    "licenses": [
        {"activationKey": "XXXX-XXXX-XXXX-XXXX", "hardwareId": "ABC123..."},
        {"activationKey": "YYYY-YYYY-YYYY-YYYY", "hardwareId": "DEF456..."}
    ]
}, headers=headers)

# Bulk Info by Keys
info_response = requests.post(f"{base_url}/bulk-info", json={
    "activationKeys": ["XXXX-XXXX-XXXX-XXXX", "YYYY-YYYY-YYYY-YYYY"]
}, headers=headers)

# Bulk by Email
email_response = requests.post(f"{base_url}/bulk-by-email", json={
    "emails": ["customer1@example.com", "customer2@example.com"]
}, headers=headers)

# Bulk by Hardware
hardware_response = requests.post(f"{base_url}/bulk-by-hardware", json={
    "hardwareIds": ["ABC123...", "DEF456..."]
}, headers=headers)

# Process results
for customer in email_response.json()["customers"]:
    print(f"{customer['email']}: {customer['licenseCount']} licenses")
    for lic in customer["licenses"]:
        print(f"  - {lic['productName']}: {'Active' if lic['isActive'] else 'Inactive'}")
const headers = {
    'Authorization': 'ExisOneApi your-api-token',
    'Content-Type': 'application/json'
};
const baseUrl = 'https://api.exisone.com/api/license';

// Bulk Validate
const validateResponse = await fetch(`${baseUrl}/validate-bulk`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
        licenses: [
            { activationKey: 'XXXX-XXXX-XXXX-XXXX', hardwareId: 'ABC123...' },
            { activationKey: 'YYYY-YYYY-YYYY-YYYY', hardwareId: 'DEF456...' }
        ]
    })
});

// Bulk Info by Keys
const infoResponse = await fetch(`${baseUrl}/bulk-info`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
        activationKeys: ['XXXX-XXXX-XXXX-XXXX', 'YYYY-YYYY-YYYY-YYYY']
    })
});

// Bulk by Email
const emailResponse = await fetch(`${baseUrl}/bulk-by-email`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
        emails: ['customer1@example.com', 'customer2@example.com']
    })
});

// Bulk by Hardware
const hardwareResponse = await fetch(`${baseUrl}/bulk-by-hardware`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
        hardwareIds: ['ABC123...', 'DEF456...']
    })
});

// Process results
const emailData = await emailResponse.json();
for (const customer of emailData.customers) {
    console.log(`${customer.email}: ${customer.licenseCount} licenses`);
}
# Bulk Validate
curl -X POST https://api.exisone.com/api/license/validate-bulk \
  -H "Authorization: ExisOneApi your-api-token" \
  -H "Content-Type: application/json" \
  -d '{"licenses": [{"activationKey": "XXXX-XXXX-XXXX-XXXX", "hardwareId": "ABC123..."}]}'

# Bulk Info by Keys
curl -X POST https://api.exisone.com/api/license/bulk-info \
  -H "Authorization: ExisOneApi your-api-token" \
  -H "Content-Type: application/json" \
  -d '{"activationKeys": ["XXXX-XXXX-XXXX-XXXX", "YYYY-YYYY-YYYY-YYYY"]}'

# Bulk by Email
curl -X POST https://api.exisone.com/api/license/bulk-by-email \
  -H "Authorization: ExisOneApi your-api-token" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["customer1@example.com", "customer2@example.com"]}'

# Bulk by Hardware
curl -X POST https://api.exisone.com/api/license/bulk-by-hardware \
  -H "Authorization: ExisOneApi your-api-token" \
  -H "Content-Type: application/json" \
  -d '{"hardwareIds": ["ABC123...", "DEF456..."]}'

Rate Limits

Batch Size Limit: Each request can query up to 100 items. Requests with more than 100 items will be automatically truncated.

Limits by Endpoint

Endpoint Max Items Notes
/validate-bulk 100 licenses Each license validated and logged
/bulk-info 100 keys Read-only, no logging
/bulk-by-email 100 emails May return many licenses per email
/bulk-by-hardware 100 hardware IDs Includes corporate seat lookups

Best Practices

1. Choose the Right Endpoint

  • Validate when you need to check if licenses are currently valid for specific hardware
  • Info when you know the keys and need full details without validation
  • By Email when looking up all licenses for customers (support, CRM)
  • By Hardware when managing devices or checking fleet status

2. Handle Partial Results

All bulk endpoints return results for each item, even if some items fail or aren't found. Always check individual results.

// Check each result individually
foreach (var license in response.Licenses)
{
    if (license.Found)
    {
        ProcessLicense(license);
    }
    else
    {
        LogNotFound(license.ActivationKey);
    }
}

3. Cache Appropriately

  • Validate results: Cache for 5-15 minutes (security-sensitive)
  • Info/Email/Hardware results: Cache for 15-60 minutes (read-only data)

4. Batch Strategically

Group related items together. For example, query all licenses for a single customer or product in one request rather than mixing unrelated data.

5. Use for Administrative Tools

These endpoints are designed for server-side administrative use. Don't expose them directly to end users.

Security Note: Bulk query endpoints return sensitive license information. Use them server-side only and protect your API tokens.