CheckMyLicense LogoCheckMyLicense

Documentation

Learn how to use CheckMyLicense with step-by-step guides, API reference, and SDK examples.

User Guide

Get started, understand operations, and configure your workspace.

API Reference

Authenticate, create and manage licenses, and verify activations.

SDKs

Explore the MQL5 SDK with installation, quick start, and examples.

User Guide

Overview

After logging in, the left‑side navigation divides the site into four main areas:

  • Operations – programs and licenses.
  • E‑Commerce – products, referees, customers, orders and payments.
  • Settings – user profile, organization, billing and balance.

Search boxes and "Add" buttons appear at the top of most pages, making it easy to find items and create new ones.

Important: The menu structure and available features may differ from user to user based on their assigned role (Administrator or Member) and their active subscription package. Administrators have full access to all features, while Members may have restricted access to certain administrative functions.

Operations

Dashboard

The dashboard summarises your organisation's usage. It displays counts of programs, total and active licences, and API hits, along with charts for licence creation and usage. Use it for a quick health check.

Programs

Purpose: Register software programs and their versions so that products and licences can reference them.

  1. Go to Programs and click Add Program.
  2. Enter a Program Name and Program Code (unique short identifier). Optionally upload a logo and write a description.
  3. Click Create. The program appears in the table with actions to view (eye), edit (pencil) or delete (trash). The delete icon removes the program permanently.
  4. To add a version, click the eye icon, then Add Version. Provide a version number, description and upload the program file. Versions appear beneath the program with actions to edit or delete.

Release Management: A complete release cycle is available through program versions. When you publish a new version, users with active licenses can receive automated email notifications about the update, ensuring they stay informed about the latest releases of your software.

Licences

Purpose: Generate activation keys that allow customers to use your program.

  1. Navigate to Licences and click Add Licence.
  2. Select the Program, type the Customer Email, set a Limit (devices allowed, 0 = unlimited) and an Expiry Date (or leave blank for unlimited).
  3. Click Generate. A unique licence key appears; copy it or send via email. The licence list shows email, program and status (Active, Expired, etc.), with actions to view or edit a licence.

License Management

After creation, only the license status can be edited. Each license maintains its own list of activations, which can be managed based on the Activations Deletable flag. When enabled, users can delete individual activations if needed.

End users can manage their activations directly at www.checkmylicense.online/myactivations. An SDK will be available soon, allowing you to integrate activation management into your own website without redirecting users to the CheckMyLicense platform.

API Integration

CheckMyLicense provides a ready-to-use API for license operations that you can integrate directly with your programs:

  • License Creation – programmatically generate licenses
  • License Update – modify license status and parameters
  • License Check – verify license validity and create activations

For detailed API documentation, parameters, and code examples, please refer to the API section of this help guide.

E‑Commerce

This section enables you to sell programs, reward affiliates, manage customers and handle orders and payments.

Coming Soon: A comprehensive E-Commerce API will be available soon, allowing you to integrate CheckMyLicense with your website as a full-fledged backend solution. This will enable seamless product sales, order management, and payment processing directly through your own website/s.

Products

Products allow you to commercialize your programs in different packages, offering flexibility in how you monetize your software. Each product can have its own configuration including different activation limits, validity periods, and pricing structures. This opens a wide range of possibilities for your commercial imagination—from offering trial versions with limited activations to premium packages with extended validity and unlimited devices.

Create a Product

  1. Navigate to Products and select Add Product.
  2. Specify a Title and Product Code, select the Program it belongs to and set the Currency and Price.
  3. Mark Discountable if referral codes should apply discounts.
  4. Define Limit (number of licences per purchase, 0 = unlimited) and Validity (days before licence expiry, 0 = no expiry).
  5. Write a description for storefront display.
  6. Click Create. The product appears with actions to view, edit or delete.

Referees and Referral Codes

Referees are affiliates who refer customers using referral codes.

Add Referee

  1. Navigate to Referees and click Add Referee.
  2. Provide the contact's email, first name and last name.
  3. Enter phone number, country, state and address.
  4. Click Save.
  5. The referee appears in the list with actions to view or edit.

Note: There is no delete option; a referee can only be cancelled (deactivated).

Roadmap: Referee compensation is not currently handled by CheckMyLicense, but it is on our roadmap. We welcome your ideas and feedback on how you would like this feature to work. Please don't hesitate to share your suggestions.

Create Referral Code

Open a referee's detail page and click Add Referral. Enter a unique code and select whether the discount is Percentage Based or Fixed Amount. Provide the discount value, optionally select a Program to limit its scope, and set an Expiry Date (or leave blank for "Never expires").

If Allow Multiple Usage is checked, the code can be redeemed unlimited times; otherwise the usage limit is exactly one. You cannot set custom usage counts beyond one or unlimited.

Customers

To create an order, you must have a customer on file.

  1. Go to Customers and click Add Customer.
  2. Enter the Email, First Name, Last Name, Phone, Country, State and Address. Click Create.
  3. The customer list shows names and emails with actions to view, edit or delete.

Note: Customers can be deleted as long as they don't have any orders associated with them. Once a customer has orders, they can only be deactivated if necessary.

Orders

Order Statuses

  • Draft – created but not confirmed. Can be edited or cancelled. Payment cannot be recorded at this stage.
  • Pending Payment – order confirmed and awaiting payment. At this status, you may record payments. Once the paid amount equals the order total the status becomes Paid; partial payments change the status to Partial Paid.
  • Paid / Partial Paid – payment recorded. A backend job (runs hourly) automatically generates the associated licences. Paid orders can be cancelled within 24 hours; the status then changes to Refunded and another backend job deactivates the licences.
  • Cancelled – order cancelled before payment; no licences generated.

Create an Order

  1. Navigate to Orders and click Create Order. Select a Customer. Optionally choose a Referral Code; the discount value is calculated automatically.
  2. Click Add Product, select the desired product and set the quantity. You may add multiple products. The order total and discount update in real time.
  3. Click Create Order. A confirmation modal shows the order code and total. Confirming sets the status to Draft. Open the order details to review.
  4. On the order details page, use the icons to Edit (pencil), Confirm (blue check) or Cancel (red icon). Confirming moves the order to Pending Payment; cancelling at this stage removes the order. There is no deletion; cancellation simply marks the order as cancelled.

Payments

Payments must correspond to orders that are Pending Payment (not Draft or already Paid). CheckMyLicense provides a payment screen to handle transactions directly through the platform.

Record a Payment

  1. Go to Payments and click Add Payment.
  2. Fill in the following details:
    • Order Code – e.g., ORD251017133003DR1
    • Amount – amount paid
    • Provider – name of the payment provider (e.g., cash, stripe, paypal)
    • Status – choose from Captured (successful), Failed, etc.
    • Payment Method and Provider Transaction ID – optional reference values
  3. Click Record Payment. If the order status is Pending Payment, the payment is accepted and appears in the payments list. If the order is still Draft or already Paid, the system rejects the payment.

Payments update the Paid Amount field in the order. When total paid equals the order total, the order status changes to Paid. Licences are then generated automatically by the backend job.

Roadmap: A webhook will be available to update payment information directly from your website or platform. Integrations with Xpay, PayPal, and Stripe are planned for future releases, enabling seamless payment processing.

Settings

User Profile

Use User Profile to manage your account:

  • Upload or update your Profile Picture.
  • Edit your Name, Email and Phone Number.
  • Change your password via the Change Password dialog after entering your current password.

For Members: Users who are members of an organization (not administrators) have the option to leave the organization. However, leaving will result in loss of access to the organization's resources unless you are re-invited by an administrator.

Organization

This section contains organisation‑wide settings.

Administrator Role

Each organization has one administrator who has exclusive access to critical functions including:

  • Managing billing and subscription plans
  • Inviting and managing team members
  • Accessing API integration keys
  • Modifying organization-wide settings

Members are added to the organization via email invitation. The administrator can delegate their role to another team member through the Change Admin function, but doing so will transfer all administrative privileges to the new administrator and revoke them from the current one.

Organization Settings

  1. Organization Information: Edit fields such as organisation name, type (Personal or Company), phone, email, country, website, Tax ID and billing address.
  2. API Key: Your organization ID serves as the API key for license verification operations. Copy it to use in your API requests. Keep it secure and do not share it publicly.
  3. Members: Click Manage Members to view and manage your team. Each member entry shows name, email, role (ADMIN or MEMBER), status (Active or Suspended), invited and joined dates. Actions allow:
    • Invite Member – enter an email address to send an invitation link.
    • Change Admin – assign the admin role to another member.
    • Suspend – temporarily remove access from a member. Suspended members can be reactivated later.

There are no limits on the number of members you can invite at present.

Billing

The billing page displays your current consumption and estimated overage costs. You see your next billing date and the usage limits for programs, active licences and API hits. Exceeding these limits incurs overage charges depending on your subscription plan. A list of invoices appears once your organisation has billable transactions.

Subscription Plans

CheckMyLicense offers several subscription packages, each designed to meet different business needs. Plans include varying limits for programs, active licenses, and API hits, with options for overage support when you exceed included limits.

Available Plans

  • Starter Kit (Free) – Perfect for getting started with basic features and community support.
  • Pay as you Go – Flexible usage-based pricing with email support.
  • Growth – Includes E‑Commerce support, email support, and overage capability for growing businesses.
  • Pro – Enterprise-grade features with multi‑user support, priority support, and white‑labelled emails.

You can view your current subscription via Billing → Manage Subscription, which shows your active plan, billing period and included features. Use Cancel Subscription to stop billing, or upgrade to higher-tier packages as your business grows.

Balance and Add Credit

The Balance page shows your available credit (for overage fees) and a ledger of credit transactions.

Add Credit

  1. Click Add Credit. Enter the amount and select a payment method:
    • Xpay (USDT TRC20) – redirects to the Xpay portal where you can complete the cryptocurrency payment.
    • PayPal – redirects to PayPal's SDK for processing.
    • Other Payment Method – opens a support form where you may arrange offline payment (e.g., bank transfer, cheque deposit). The operations team manually adds the credit after verifying the payment.
  2. Check the box agreeing that credits will pay current and future dues.
  3. Follow the external instructions to finish the payment. On returning, your balance will update.

Typical Workflow

Use the following steps to sell a program to a customer:

  1. Create a Program and add a version under Operations → Programs.
  2. Create a Product linked to that program under E‑Commerce → Products.
  3. (Optional) Add a Referee and Referral Code if you wish to offer discounts.
  4. Add a Customer under E‑Commerce → Customers.
  5. Create an Order for the customer in Orders. Select the product, apply any referral code and confirm the order. The order enters Draft status.
  6. Confirm the Order via the blue check icon on the order page. The status becomes Pending Payment.
  7. Record Payment in Payments. Provide the order code, amount and provider details. Once payments cover the total, the order status becomes Paid and licences are generated automatically by the backend job (runs hourly).
  8. Monitor Licences and Overage Usage in Operations → Licences and Settings → Billing.

Orders can be cancelled before payment or within 24 hours after payment (status changes to Refunded). There is no delete function; cancelling is the only way to void an order or referral.

Frequently Asked Questions

Order and Payment Workflow

Payments are only accepted when an order is in Pending Payment status. Attempting to add a payment while the order is still Draft or already Paid results in "Failed to insert payment."

Cancellations

There is no delete function for orders, programmes, products or referrals. You can cancel orders (Draft or Pending Payment) or refund paid orders within 24 hours. Licences are created or deactivated automatically by backend jobs.

Referral Code Usage

If Allow Multiple Usage is unchecked, a referral code may be used once. There is no way to specify a custom usage count. When checked, the code can be used unlimited times.

Add Credit Methods

Xpay and PayPal redirect you to their respective payment portals, while Other Payment Method contacts support for manual payment arrangements (e.g., bank transfer or cheque deposit).

Multi‑User Limits

There are no limits on the number of members you can invite to your organisation.

API Documentation

Authentication

Authenticate with email/password to receive a session object. Use the returned accessToken as a Bearer token in Authorization header for protected endpoints.

Sign In with Email/Password

POST/signin/email-password

Request body: email and password.

ParameterTypeInRequiredDescription
emailstringbodyyesUser email
passwordstringbodyyesUser password
Example Request
POST https://vwqretlvkrravzguxydw.functions.eu-west-2.nhost.run/v1/signin/email-password HTTP/1.1
Content-Type: application/json

{
  "email": "john.doe@example.com",
  "password": "MyP@ssw0rd!"
}
Example Response
{
  "session": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NjA2MjEwMjMs...",
    "accessTokenExpiresIn": 900,
    "refreshToken": "b62f696a-b61b-4f2e-9e74-f4f18c6062d3",
    "refreshTokenId": "9fe23c69-da50-4212-b467-0a219eb9b4b1",
    "user": {
      "id": "693de173-d234-509a-a1dc-4d40da908866",
      "email": "john.doe@example.com",
      "displayName": "John Doe"
    }
  }
}

Use the access token in subsequent requests:

Authorization: Bearer <accessToken>

License Create

Create License

POST/license/create

Create a new license. Implemented in functions/license/create. The endpoint requires organization context (auth provides organization_id).

ParameterTypeInRequiredDescription
emailstringbody or queryyesLicense owner email
program_namestringbody or queryyesProgram name
limitintegerbody or querynoActivation limit
expirybigintbody or querynoExpiry timestamp (seconds or ms accepted)
activations_deletablebooleanbody or querynoWhether activations can be deleted
cURL Example
curl -X POST "https://vwqretlvkrravzguxydw.functions.eu-west-2.nhost.run/v1/license/create" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "program_name": "My Product",
    "limit": 3,
    "expiry": 1761315325262
  }'

Possible Responses

200License created

Success

{
  "success": {
    "message": "License created",
    "data": {
      "insert_licenses": {
        "affected_rows": 1,
        "returning": [{
          "id": 309,
          "email": "example@tradet.net",
          "license": "9845cca98bbe4664bbbc9fb10862a453",
          "program_id": 42,
          "limit": 10,
          "expiry": null,
          "status": 0,
          "activations_deletable": true,
          "organization_id": "723493dd-4a3c-cd4d-8b7b-c288704d96e9",
          "created_at": "2025-10-17T09:08:59.838129+00:00",
          "updated_at": "2025-10-17T09:08:59.838129+00:00"
        }]
      },
      "subscription_info": {
        "subscription_id": 70,
        "package_id": 36,
        "overage_created": false,
        "is_vip": false,
        "current_license_count": 5,
        "license_limit": 10,
        "reason": "Within package limits"
      }
    }
  }
}
400Invalid request / validation failed

Missing or invalid parameters

{
  "error": {
    "message": "Invalid license request",
    "errors": ["email is required", "program_name not found"]
  }
}
400Missing organization

Caller is not associated with an organization

{
  "error": {
    "message": "User must belong to an organization to create licenses"
  }
}
400Program validation failed

Program not owned by organization or not found

{
  "error": {
    "message": "Program not found or not owned by this organization"
  }
}
400Subscription limit / quota prevented creation

Subscription does not allow creating more licenses

{
  "error": {
    "message": "Subscription limits prevent creating new licenses",
    "reason": "license limit reached for current package"
  }
}
500Insert error

General failure while processing the request

{
  "error": {
    "message": "Error creating license",
    "data": { "message": "<error object>", "stack": "..." }
  }
}

License Update

Update License

PUT/license/update

Update license fields such as status. Implemented in functions/license/update. The handler expects license_id and any fields to set.

ParameterTypeInRequiredDescription
license_idintegerquery or bodyyesLicense ID to update
statusintegerquery or bodyno0=active, 1=inactive (will set deactivated_at)
cURL Example
curl -X PUT "https://vwqretlvkrravzguxydw.functions.eu-west-2.nhost.run/v1/license/update" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "license_id": 124, "status": 1 }'
Example Response
{
  "success": {
    "message": "License updated: status and deactivated_at updated",
    "data": {
      "update_licenses": {
        "affected_rows": 1,
        "returning": [{
          "id": 309,
          "status": 1,
          "deactivated_at": "2025-10-17T09:23:23.35+00:00",
          "updated_at": "2025-10-17T09:23:23.38114+00:00"
        }]
      }
    }
  }
}

License Check

Verify License

POST/license/verify

Verify a license and create an activation record using HMAC-SHA256 signature authentication. Implemented in functions/license/verify.

ParameterTypeInRequiredDescription
api_idstring (UUID)bodyyesOrganization ID (from Settings → Organization)
tsstringbodyyesCurrent Unix timestamp in seconds (UTC)
payloadstring (base64)bodyyesBase64-encoded JSON payload with license UUID and activation details
sigstring (base64)bodyyesHMAC-SHA256 signature of canonical string (base64 encoded)
vstringbodynoAPI version (default: "1")
cURL Example
curl -X POST "https://vwqretlvkrravzguxydw.functions.eu-west-2.nhost.run/v1/license/verify" \
  -H "Content-Type: application/json" \
  -d '{
    "api_id": "723493dd-4a3c-4dcd-b78b-c288704d96e9",
    "ts": "1729875123",
    "payload": "eyJsaWNlbnNlX3V1aWQiOiI5ODQ1Y2NhOS04YmJlLTQ2NjQtYmJiYy05ZmIxMC04NjJhNDUzIiwiZW1haWwiOiJqb2huQGV4YW1wbGUuY29tIiwidGFyZ2V0X2lkIjoiMTIzNDU2Nzg5IiwidGFyZ2V0X2hvc3QiOiJNVDUtUENcLVNlcnZlciIsInR5cGUiOiJMaXZlIn0=",
    "sig": "EQpYrJDEJ2xH5gQ0Pn9mKzRtUvJf4eW2cD7vM3nKj0o=",
    "v": "1"
  }'

Payload Structure (JSON, before base64 encoding)

License verification payload
{
  "license": "9845cca98bbe4664bbbc9fb10862a453",
  "email": "john@example.com",
  "target_id": "123456789",
  "target_host": "MT5-PC\\Server",
  "type": "Live"
}

Field Descriptions:

  • license: The full 32-char hex license key
  • email: License owner's email address (must match the license)
  • target_id: Account number or unique machine identifier
  • target_host: Server name or hostname
  • type: Account type (e.g., "Live", "Demo")

Possible Responses

StatusMessageDescription
200activation existsLicense verified successfully. This target already has an active license.
200activation createdFirst time this target is checking this license. New activation was created.
400missing required fieldsOne or more required fields (api_id, ts, payload, sig) are missing or empty.
401stale timestampTimestamp is too old or too far in the future (must be within ±60 seconds of server time).
401invalid api_idOrganization ID (api_id) not found in the system.
401invalid signatureHMAC-SHA256 signature verification failed. Verify your api_secret and signature computation.
400invalid payloadPayload cannot be decoded from base64 or is not valid JSON.
404unmatched licenseNo license matching the provided UUID exists for this organization.
400license inactiveLicense status is 1 (inactive/deactivated). Cannot use inactive licenses.
400invalid emailProvided email does not match the license owner email.
400expired certificateLicense expiry timestamp has passed. License has expired.
400max limit reachedMaximum number of activations for this license has been exceeded.
500internal errorInternal server error while processing the verification request.

Activation Tracking

Each successful verification creates a license hit record immediately upon organization verification. If the license is found, the hit is updated with the license_id and the license'slast_used_at timestamp is updated. Activations are created on a best-effort basis; if activation insertion fails, the verification still succeeds.

Encoding & Encryption

The license verify endpoint uses HMAC-SHA256 signature authentication. The request body is JSON, but the payload field must be base64-encoded and the request is authenticated with an HMAC-SHA256 signature.

Request Signature Flow

To verify a license, follow these steps:

  1. Prepare JSON payload with license, email, and target info
  2. Base64 encode the JSON payload
  3. Get current Unix timestamp (seconds, UTC)
  4. Build canonical string: api_id.ts.payload_base64
  5. Compute HMAC-SHA256 of canonical string using your api_secret
  6. Base64 encode the HMAC result
  7. Send JSON request with api_id, ts, payload, sig, and v fields

Building the Payload

The JSON payload contains the license and activation information:

Example payload (before base64 encoding)
{
  "license": "9845cca98bbe4664bbbc9fb10862a453",
  "email": "john@example.com",
  "target_id": "123456789",
  "target_host": "MT5-Desktop\\EURUSD",
  "type": "Live"
}

Payload Fields:

  • license: 32-character hex license key
  • email: Email address of the license owner
  • target_id: Account login number or unique machine ID
  • target_host: Server hostname or terminal identifier
  • type: Account type (e.g., "Demo", "Live")
Example payload (base64 encoded)
eyJsaWNlbnNlX3V1aWQiOiI5ODQ1Y2NhOS04YmJlLTQ2NjQtYmJiYy05ZmIxMC04NjJhNDUzIiwiZW1haWwiOiJqb2huQGV4YW1wbGUuY29tIiwidGFyZ2V0X2lkIjoiMTIzNDU2Nzg5IiwidGFyZ2V0X2hvc3QiOiJNVDUtRGVza3RvcFxcRVVSVVNEIiwidHlwZSI6IkxpdmUifQ==

Computing HMAC-SHA256 Signature

Use your api_secret (from Settings → Organization) and the canonical string to compute an HMAC-SHA256 digest, then base64-encode it.

Steps:

  1. Take the canonical string: api_id.ts.payload_base64
  2. Compute HMAC-SHA256 using your api_secret as the key and the canonical string as the data
  3. Base64 encode the resulting HMAC digest
  4. Use this base64-encoded value as the sig parameter

Most modern programming languages have built-in libraries for HMAC-SHA256 computation. Look for crypto, hashlib, or similar security libraries in your language of choice.

Timestamp Window: The server accepts timestamps within ±60 seconds of the current time. Ensure your system clock is synchronized.

Complete Request Example

Full JSON request body
{
  "api_id": "723493dd-4a3c-4dcd-b78b-c288704d96e9",
  "ts": "1729875123",
  "payload": "eyJsaWNlbnNlX3V1aWQiOiI5ODQ1Y2NhOS04YmJlLTQ2NjQtYmJiYy05ZmIxMC04NjJhNDUzIiwiZW1haWwiOiJqb2huQGV4YW1wbGUuY29tIiwidGFyZ2V0X2lkIjoiMTIzNDU2Nzg5IiwidGFyZ2V0X2hvc3QiOiJNVDUtRGVza3RvcFxcRVVSVVNEIiwidHlwZSI6IkxpdmUifQ==",
  "sig": "EQpYrJDEJ2xH5gQ0Pn9mKzRtUvJf4eW2cD7vM3nKj0o=",
  "v": "1"
}

Breaking it down:

  • api_id = Organization ID
  • ts = Current Unix timestamp (seconds)
  • payload = Base64(JSON payload)
  • sig = Base64(HMAC-SHA256(api_id.ts.payload, api_secret))
  • v = API version

Response Handling

The response is always JSON. Check the HTTP status code:

  • 200 OK — License verified. Response contains success: true, message, and data with validity/limit/used.
  • 400-500 — Error. Response contains error object with code and message.
Success response (200 OK)
{
  "success": true,
  "message": "activation exists",
  "data": {
    "validity": 1761315325262,
    "limit": 3,
    "used": 1
  }
}
Error response (e.g., 401 Unauthorized)
{
  "error": {
    "code": 401,
    "message": "invalid signature"
  }
}

Signature Verification Failed?

  • Verify your api_secret is correct
  • Ensure timestamp is recent (within 60 seconds of server time)
  • Confirm canonical string format: api_id.ts.payload (with periods, no spaces)
  • Use base64 encoding for payload, then use the base64 string (not the decoded bytes) in canonical
  • Check that HMAC input and output are both base64-encoded
SDK Documentation

SDK Overview

CheckMyLicense provides Software Development Kits (SDKs) to simplify the integration of license verification into your applications. These SDKs handle all the complexity of encryption, API communication, and response parsing, allowing you to implement robust license protection with just a few lines of code.

Key Features

  • Easy Integration – Add license verification with minimal code changes
  • Secure Encryption – HMAC-SHA256 encryption for data signatures
  • Detailed Error Handling – Clear error messages for troubleshooting

Available SDKs

To download the available SDKs, please visit your organization page: Available SDK section.

  • Metatrader SDK – Add license verification with minimal code changes in Metatrader 4 or 5 EA and indicators.

More SDKs Coming Soon: We're actively developing SDKs for additional platforms including Python, JavaScript/Node.js, C#/.NET, and Java. If you need an SDK for a specific platform, please contact our support team.

MQL SDK Installation

Important: Always enable Cloud Protect and rebuild regularly

When compiling your Indicator or Expert Advisor (EA), always enable Cloud Protect. Using cloud protection adds an extra layer of security for your published EA and helps prevent unauthorized redistribution. Never share an EA without cloud protection enabled.

  • Enable Cloud Protect every time you compile your indicator or EA.
  • Never distribute an unprotected EA — always use cloud protection for published builds.
  • Periodically rebuild your programs using newer MetaTrader builds and SDK versions to benefit from security fixes and compiler improvements.

Prerequisites

  • MetaTrader platform installed
  • MetaEditor installed
  • Active CheckMyLicense organization account
  • Your organization's API Key and Secret (found in Settings → Organization)

Installation Steps

  1. Download the SDK
  2. Extract Files

    The SDK package contains two files:

    • CheckMyLicense.mqh – The reusable SDK library
    • SHA26.mqh – The reusable component for SHA-256 hashing
    • CheckMyLicense.mq5 – Example implementation script
  3. Copy to MetaTrader Directory

    Copy CheckMyLicense.mqh and SHA26.mqh to your MetaTrader 5 Include folder:

    C:\Users\YourUsername\AppData\Roaming\MetaQuotes\Terminal\[TerminalID]\MQL5\Include\
  4. Allow WebRequest URL

    In MetaTrader 5, go to Tools → Options → Expert Advisors and add the CheckMyLicense API URL to the list of allowed URLs:

    https://vwqretlvkrravzguxydw.functions.eu-west-2.nhost.run/v1

Important: Without adding the URL to allowed WebRequest addresses, the SDK will not be able to communicate with CheckMyLicense servers, and license verification will fail.

MQL5 Quick Start

Basic Implementation

Add license verification to your Expert Advisor, Indicator, or Script:

1. Define Input Parameters

input string InpEmail = "";    // User&apos;s email
input string InpLicence = ""; // License key

2. Verify License OnInit for Expert Advisors

int OnInit()
{
    if(!CheckMyLicense(InpEmail, InpLicence))
    {
        Print("License verification failed!");
        return INIT_FAILED;
    }
    
    Print("License verified successfully!");
    return INIT_SUCCEEDED;
}

3. Verify License OnStart for Scripts

void OnStart()
{
    if(!CheckMyLicense(InpEmail, InpLicence))
    {
        Print("License verification failed!");
        return;
    }
    
    // Your script logic here
    Print("Running licensed script...");
}

MQL5 Examples

Complete Expert Advisor Example

Here's a complete example of an Expert Advisor with license verification:

//+------------------------------------------------------------------+
//|                                            LicensedEA.mq5 |
//|                                  Copyright 2025, Your Company |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Your Company"
#property link      "https://www.yourwebsite.com"
#property version   "1.00"

string name = "Your Program Name"
#include "CheckMyLicense.mqh"

// Input parameters
input string InpEmail = "";              // Email
input string InpLicence = "";            // License Key
input double InpLotSize = 0.01;          // Lot Size
input int    InpMagicNumber = 12345;     // Magic Number

//+------------------------------------------------------------------+
//| Expert initialization function                                     |
//+------------------------------------------------------------------+
int OnInit()
{
    // Verify license first
    if(!CheckMyLicense(InpEmail, InpLicence))
    {
        Alert("License verification failed! EA will not run.");
        return INIT_FAILED;
    }
    
    Print("License verified! EA starting...");
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick()
{
    // Your trading logic here
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    Print("EA stopped. Reason: ", reason);
}

Indicator Example

Important Limitation: MetaTrader does not allow Indicators to call WebRequest() functions for security reasons. If you need to license a custom indicator, you must create a wrapper Expert Advisor that verifies the license and then calls the indicator logic. Alternatively, you can distribute your indicator as part of a licensed EA template.

If you must use an Indicator with license verification, create an EA wrapper that loads the indicator as an embedded resource. This approach requires only license verification on the EA, not the indicator itself:

//+------------------------------------------------------------------+
//|                         CustomIndicatorWrapper.mq5 |
//|  EA that attaches a custom licensed indicator to the chart      |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Your Company"
#property link      "https://www.yourwebsite.com"
#property version   "1.0"

string name = "Licensed Indicator Wrapper"
#include "CheckMyLicense.mqh"

// Embed your custom indicator as a resource
#resource "CustomIndicator.ex5"

// Resource reference for iCustom
#define CUSTOM_INDICATOR "::CustomIndicator.ex5"

// Mirror indicator inputs to match your custom indicator parameters
input int    InpPeriod            = 14;       // MA Period
input int    InpShift             = 0;        // Shift
input bool   InpShowSignal        = true;     // Show Signal Line

// License input
input string InpEmail = "";
input string InpLicence = "";

// Internal
int g_ind_handle = INVALID_HANDLE;
int ext_reason = 0;

//+------------------------------------------------------------------+
//| Helper: Remove indicator from chart if present                   |
//+------------------------------------------------------------------+
void RemoveIndicator()
{
    if(g_ind_handle != INVALID_HANDLE)
    {
        // Find and remove any indicator with matching name
        int total = (int)ChartIndicatorsTotal(0, 0);
        for(int i = total - 1; i >= 0; --i)
        {
            string name = ChartIndicatorName(0, 0, i);
            if(StringFind(name, "CustomIndicator") >= 0)
                ChartIndicatorDelete(0, 0, name);
        }
        IndicatorRelease(g_ind_handle);
        g_ind_handle = INVALID_HANDLE;
    }
}

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // Verify license first
    if(ext_reason != 3) // Skip on EA reload (reason 3)
    {
        if(!CheckMyLicense(InpEmail, InpLicence))
        {
            Alert("License verification failed! EA will not run.");
            return INIT_PARAMETERS_INCORRECT;
        }
    }

    // Ensure any previous instance is removed
    RemoveIndicator();

    // Create indicator handle with your custom parameters
    g_ind_handle = iCustom(
        _Symbol,
        _Period,
        CUSTOM_INDICATOR,
        InpPeriod,
        InpShift,
        InpShowSignal
    );

    if(g_ind_handle == INVALID_HANDLE)
    {
        PrintFormat("Failed to create indicator handle. Error=%d", GetLastError());
        return INIT_FAILED;
    }

    // Add indicator to chart
    if(!ChartIndicatorAdd(0, 0, g_ind_handle))
    {
        PrintFormat("ChartIndicatorAdd failed. Error=%d", GetLastError());
        IndicatorRelease(g_ind_handle);
        g_ind_handle = INVALID_HANDLE;
        return INIT_FAILED;
    }

    Print("License verified! Custom indicator attached to chart.");
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    RemoveIndicator();
    if(reason == 3)
    {
        ext_reason = 3; // Track EA reload
    }
}

//+------------------------------------------------------------------+
//| Expert tick function (no trading logic needed)                   |
//+------------------------------------------------------------------+
void OnTick()
{
    // Wrapper runs silently; indicator handles all logic
}

Understanding Error Codes

The SDK uses specific error codes to help diagnose issues during license verification:

Error CodeDescriptionSolution
EX1001Email not providedEnter your email address in the input parameters (InpEmail)
EX1002License key not providedEnter your license key in the input parameters (InpLicence)
EX1003Program name not configuredSet #define ProgramName to match your program name in CheckMyLicense
EX1004License validation failed at startupVerify your license key format and API credentials
EX2001Payload encoding failedVerify your #define APISecret is correctly set from Organization settings
EX2002HMAC-SHA256 signature computation failedVerify #define APIID and #define APISecret are correct
EX3001WebRequest URL not allowed in MT5Add https://vwqretlvkrravzguxydw.functions.eu-west-2.nhost.run/v1 to Tools → Options → Expert Advisors → Allow WebRequest for URLs
EX3003Connection error or timeoutCheck your internet connection; if persists, verify the server URL is accessible
EX4001-EX4005Cryptographic operation failed (Base64 encoding/decoding)Verify the license key is valid; check that SHA256.mqh is included in your project
400 Bad RequestInvalid payload or malformed requestVerify email format is correct and license key contains valid 32 hex characters
401 UnauthorizedLicense invalid, expired, or not owned by emailVerify the email matches the license owner; check license hasn't expired in your dashboard
404 Not FoundLicense or program not foundVerify the license key exists and the program name matches your CheckMyLicense dashboard
500 Server ErrorCheckMyLicense server errorTry again later; if error persists, contact support

Testing Your Implementation

  1. Compile – Compile your MQL5 file in MetaEditor (F7)
  2. Attach to Chart – Drag your EA/Indicator to a chart
  3. Enter Credentials – Input your email and license key in the parameters dialog
  4. Check Logs – Open the Experts tab to see verification results
  5. Verify Activation – Check your CheckMyLicense dashboard for the new activation

Best Practice: Always verify the license during initialization (OnInit). This prevents unauthorized use and ensures proper activation tracking from the start. Also consider implementing periodic re-validation during runtime for long-running applications.

License Management Documentation | CheckMyLicense API, MQL4/MQL5 SDK & MetaTrader Guides