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.
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.
- Go to Programs and click Add Program.
- Enter a Program Name and Program Code (unique short identifier). Optionally upload a logo and write a description.
- 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.
- 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.
- Navigate to Licences and click Add Licence.
- Select the Program, type the Customer Email, set a Limit (devices allowed, 0 = unlimited) and an Expiry Date (or leave blank for unlimited).
- 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
- Navigate to Products and select Add Product.
- Specify a Title and Product Code, select the Program it belongs to and set the Currency and Price.
- Mark Discountable if referral codes should apply discounts.
- Define Limit (number of licences per purchase, 0 = unlimited) and Validity (days before licence expiry, 0 = no expiry).
- Write a description for storefront display.
- 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
- Navigate to Referees and click Add Referee.
- Provide the contact's email, first name and last name.
- Enter phone number, country, state and address.
- Click Save.
- 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.
- Go to Customers and click Add Customer.
- Enter the Email, First Name, Last Name, Phone, Country, State and Address. Click Create.
- 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
- Navigate to Orders and click Create Order. Select a Customer. Optionally choose a Referral Code; the discount value is calculated automatically.
- 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.
- Click Create Order. A confirmation modal shows the order code and total. Confirming sets the status to Draft. Open the order details to review.
- 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
- Go to Payments and click Add Payment.
- 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
- Order Code – e.g.,
- 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
- Organization Information: Edit fields such as organisation name, type (Personal or Company), phone, email, country, website, Tax ID and billing address.
- 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.
- 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
- 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.
- Check the box agreeing that credits will pay current and future dues.
- 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:
- Create a Program and add a version under Operations → Programs.
- Create a Product linked to that program under E‑Commerce → Products.
- (Optional) Add a Referee and Referral Code if you wish to offer discounts.
- Add a Customer under E‑Commerce → Customers.
- Create an Order for the customer in Orders. Select the product, apply any referral code and confirm the order. The order enters Draft status.
- Confirm the Order via the blue check icon on the order page. The status becomes Pending Payment.
- 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).
- 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.
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
/signin/email-passwordRequest body: email and password.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
email | string | body | yes | User email |
password | string | body | yes | User password |
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!"
}{
"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
/license/createCreate a new license. Implemented in functions/license/create. The endpoint requires organization context (auth provides organization_id).
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
email | string | body or query | yes | License owner email |
program_name | string | body or query | yes | Program name |
limit | integer | body or query | no | Activation limit |
expiry | bigint | body or query | no | Expiry timestamp (seconds or ms accepted) |
activations_deletable | boolean | body or query | no | Whether activations can be deleted |
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
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"
}
}
}
}Missing or invalid parameters
{
"error": {
"message": "Invalid license request",
"errors": ["email is required", "program_name not found"]
}
}Caller is not associated with an organization
{
"error": {
"message": "User must belong to an organization to create licenses"
}
}Program not owned by organization or not found
{
"error": {
"message": "Program not found or not owned by this organization"
}
}Subscription does not allow creating more licenses
{
"error": {
"message": "Subscription limits prevent creating new licenses",
"reason": "license limit reached for current package"
}
}General failure while processing the request
{
"error": {
"message": "Error creating license",
"data": { "message": "<error object>", "stack": "..." }
}
}License Update
Update License
/license/updateUpdate license fields such as status. Implemented in functions/license/update. The handler expects license_id and any fields to set.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
license_id | integer | query or body | yes | License ID to update |
status | integer | query or body | no | 0=active, 1=inactive (will set deactivated_at) |
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 }'{
"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
/license/verifyVerify a license and create an activation record using HMAC-SHA256 signature authentication. Implemented in functions/license/verify.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
api_id | string (UUID) | body | yes | Organization ID (from Settings → Organization) |
ts | string | body | yes | Current Unix timestamp in seconds (UTC) |
payload | string (base64) | body | yes | Base64-encoded JSON payload with license UUID and activation details |
sig | string (base64) | body | yes | HMAC-SHA256 signature of canonical string (base64 encoded) |
v | string | body | no | API version (default: "1") |
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": "9845cca98bbe4664bbbc9fb10862a453",
"email": "john@example.com",
"target_id": "123456789",
"target_host": "MT5-PC\\Server",
"type": "Live"
}Field Descriptions:
license: The full 32-char hex license keyemail: License owner's email address (must match the license)target_id: Account number or unique machine identifiertarget_host: Server name or hostnametype: Account type (e.g., "Live", "Demo")
Possible Responses
| Status | Message | Description |
|---|---|---|
200 | activation exists | License verified successfully. This target already has an active license. |
200 | activation created | First time this target is checking this license. New activation was created. |
400 | missing required fields | One or more required fields (api_id, ts, payload, sig) are missing or empty. |
401 | stale timestamp | Timestamp is too old or too far in the future (must be within ±60 seconds of server time). |
401 | invalid api_id | Organization ID (api_id) not found in the system. |
401 | invalid signature | HMAC-SHA256 signature verification failed. Verify your api_secret and signature computation. |
400 | invalid payload | Payload cannot be decoded from base64 or is not valid JSON. |
404 | unmatched license | No license matching the provided UUID exists for this organization. |
400 | license inactive | License status is 1 (inactive/deactivated). Cannot use inactive licenses. |
400 | invalid email | Provided email does not match the license owner email. |
400 | expired certificate | License expiry timestamp has passed. License has expired. |
400 | max limit reached | Maximum number of activations for this license has been exceeded. |
500 | internal error | Internal 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:
- Prepare JSON payload with license, email, and target info
- Base64 encode the JSON payload
- Get current Unix timestamp (seconds, UTC)
- Build canonical string:
api_id.ts.payload_base64 - Compute HMAC-SHA256 of canonical string using your
api_secret - Base64 encode the HMAC result
- Send JSON request with api_id, ts, payload, sig, and v fields
Building the Payload
The JSON payload contains the license and activation information:
{
"license": "9845cca98bbe4664bbbc9fb10862a453",
"email": "john@example.com",
"target_id": "123456789",
"target_host": "MT5-Desktop\\EURUSD",
"type": "Live"
}Payload Fields:
license: 32-character hex license keyemail: Email address of the license ownertarget_id: Account login number or unique machine IDtarget_host: Server hostname or terminal identifiertype: Account type (e.g., "Demo", "Live")
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:
- Take the canonical string:
api_id.ts.payload_base64 - Compute HMAC-SHA256 using your
api_secretas the key and the canonical string as the data - Base64 encode the resulting HMAC digest
- Use this base64-encoded value as the
sigparameter
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
{
"api_id": "723493dd-4a3c-4dcd-b78b-c288704d96e9",
"ts": "1729875123",
"payload": "eyJsaWNlbnNlX3V1aWQiOiI5ODQ1Y2NhOS04YmJlLTQ2NjQtYmJiYy05ZmIxMC04NjJhNDUzIiwiZW1haWwiOiJqb2huQGV4YW1wbGUuY29tIiwidGFyZ2V0X2lkIjoiMTIzNDU2Nzg5IiwidGFyZ2V0X2hvc3QiOiJNVDUtRGVza3RvcFxcRVVSVVNEIiwidHlwZSI6IkxpdmUifQ==",
"sig": "EQpYrJDEJ2xH5gQ0Pn9mKzRtUvJf4eW2cD7vM3nKj0o=",
"v": "1"
}Breaking it down:
api_id= Organization IDts= 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, anddatawith validity/limit/used. - 400-500 — Error. Response contains
errorobject withcodeandmessage.
{
"success": true,
"message": "activation exists",
"data": {
"validity": 1761315325262,
"limit": 3,
"used": 1
}
}{
"error": {
"code": 401,
"message": "invalid signature"
}
}Signature Verification Failed?
- Verify your
api_secretis 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 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
- Download the SDK
- Extract Files
The SDK package contains two files:
CheckMyLicense.mqh– The reusable SDK librarySHA26.mqh– The reusable component for SHA-256 hashingCheckMyLicense.mq5– Example implementation script
- Copy to MetaTrader Directory
Copy
CheckMyLicense.mqhandSHA26.mqhto your MetaTrader 5 Include folder:C:\Users\YourUsername\AppData\Roaming\MetaQuotes\Terminal\[TerminalID]\MQL5\Include\ - 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's email
input string InpLicence = ""; // License key2. 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 Code | Description | Solution |
|---|---|---|
EX1001 | Email not provided | Enter your email address in the input parameters (InpEmail) |
EX1002 | License key not provided | Enter your license key in the input parameters (InpLicence) |
EX1003 | Program name not configured | Set #define ProgramName to match your program name in CheckMyLicense |
EX1004 | License validation failed at startup | Verify your license key format and API credentials |
EX2001 | Payload encoding failed | Verify your #define APISecret is correctly set from Organization settings |
EX2002 | HMAC-SHA256 signature computation failed | Verify #define APIID and #define APISecret are correct |
EX3001 | WebRequest URL not allowed in MT5 | Add https://vwqretlvkrravzguxydw.functions.eu-west-2.nhost.run/v1 to Tools → Options → Expert Advisors → Allow WebRequest for URLs |
EX3003 | Connection error or timeout | Check your internet connection; if persists, verify the server URL is accessible |
EX4001-EX4005 | Cryptographic operation failed (Base64 encoding/decoding) | Verify the license key is valid; check that SHA256.mqh is included in your project |
400 Bad Request | Invalid payload or malformed request | Verify email format is correct and license key contains valid 32 hex characters |
401 Unauthorized | License invalid, expired, or not owned by email | Verify the email matches the license owner; check license hasn't expired in your dashboard |
404 Not Found | License or program not found | Verify the license key exists and the program name matches your CheckMyLicense dashboard |
500 Server Error | CheckMyLicense server error | Try again later; if error persists, contact support |
Testing Your Implementation
- Compile – Compile your MQL5 file in MetaEditor (F7)
- Attach to Chart – Drag your EA/Indicator to a chart
- Enter Credentials – Input your email and license key in the parameters dialog
- Check Logs – Open the Experts tab to see verification results
- 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.