API Documentation
Reference for integrating the GoldScalper Pro Expert Advisors for MT4/MT5 and the Android companion app with the licensing backend. All endpoints are JSON over HTTPS. CORS is open on /api/public/*.
POST /api/public/license/validate
Validate a license key against an MT5 account. Auto-binds new MT5 accounts up to device_limit.
Request body
| license_key | string · required | Format GSP-XXXX-XXXX-XXXX |
| account_number | string · required | MT5 login number |
| device_id | string · optional | Stable per-machine id |
| broker | string · optional | Broker company name |
| server | string · optional | Broker server name |
Responses
200 OK
{ "ok": true, "plan": "monthly", "expires_at": "2026-07-27T…", "device_limit": 2 }
200 OK (refusal)
{ "ok": false, "error": "license_expired" } // also: license_revoked, license_suspended
{ "ok": false, "error": "license_not_found" }
{ "ok": false, "error": "device_limit_reached" }
{ "ok": false, "error": "bind_failed" }
400 Bad Request
{ "ok": false, "error": "invalid_json" } // body wasn't valid JSON
{ "ok": false, "error": "invalid_input" } // failed schema validation (e.g. bad license_key format)Example
curl -X POST https://goldscalperpro.com/api/public/license/validate \
-H "Content-Type: application/json" \
-d '{
"license_key": "GSP-XXXX-XXXX-XXXX",
"account_number": "12345678",
"device_id": "optional-device-uuid",
"broker": "Optional Broker Ltd",
"server": "Broker-Live"
}'ok: true. Rechecking every 6 hours is recommended.POST /api/public/trades/report
Batch-report closed trades for dashboard analytics. Idempotent on (account_number, ticket). The account must already be bound via License validate.
Trade object fields
| ticket | int · optional | MT5 ticket | required for dedup |
| symbol | string · optional | e.g. XAUUSD |
| side | "buy" | "sell" · optional | |
| volume | number · optional | Lot size |
| open_price / close_price | number · optional | |
| sl / tp | number · optional | Stop loss / take profit |
| comment | string · optional | Max 100 chars |
| profit | number · optional | |
| opened_at / closed_at | ISO datetime · optional |
Example
curl -X POST https://goldscalperpro.com/api/public/trades/report \
-H "Content-Type: application/json" \
-d '{
"license_key": "GSP-XXXX-XXXX-XXXX",
"account_number": "12345678",
"trades": [
{
"ticket": 123456,
"symbol": "XAUUSD",
"side": "buy",
"volume": 0.10,
"open_price": 2345.10,
"close_price": 2348.55,
"sl": 2340.00,
"tp": 2360.00,
"comment": "gsp-v4.30",
"profit": 34.50,
"opened_at": "2026-06-27T09:00:00Z",
"closed_at": "2026-06-27T09:42:00Z"
}
]
}'Responses
200 OK
{ "ok": true, "inserted": 3, "skipped": 1 } // skipped = trades already reported for this (account_number, ticket)
200 OK (refusal)
{ "ok": false, "error": "invalid_license" } // license not found or not active
{ "ok": false, "error": "license_expired" }
{ "ok": false, "error": "account_not_bound" } // call license/validate for this account first
{ "ok": false, "error": "insert_failed" }
400 Bad Request
{ "ok": false, "error": "invalid_json" }
{ "ok": false, "error": "invalid_input" } // e.g. empty trades array, or more than 100 tradesskipped rather than duplicated. Trades sent without a ticket number cannot be deduplicated and will always be inserted.GET /api/public/ea/commands
Poll for pending remote commands issued from the dashboard or Android app (pause, resume, close_all, settings updates). The account must already be bound.
Query params
| license_key | string · required | Format GSP-XXXX-XXXX-XXXX |
| account_number | string · required | MT5 login number |
Example
curl "https://goldscalperpro.com/api/public/ea/commands?license_key=GSP-XXXX-XXXX-XXXX&account_number=12345678"Responses
200 OK
{ "ok": true, "commands": [
{ "id": "…", "command": "pause", "payload": {}, "created_at": "2026-06-27T09:00:00Z" }
] }
200 OK (refusal)
{ "ok": false, "error": "invalid_license" } // not found, not active
{ "ok": false, "error": "license_expired" }
{ "ok": false, "error": "invalid_input" } // bad license_key format or missing paramsPOST /api/public/ea/push
Push live EA/account state for real-time monitoring in the dashboard and Android app. The account must already be bound.
Request body
| license_key | string · required | Format GSP-XXXX-XXXX-XXXX |
| account_number | string · required | MT5 login number |
| status | "ACTIVE"|"DISABLED"|"HALTED"|"OFFLINE" · optional | |
| halt_reason | string · optional | Max 200 chars |
| symbol / trend / signal | string · optional | Max 20 chars each |
| spread_points | number · optional | |
| session_open | boolean · optional | |
| equity / balance / daily_pnl | number · optional | |
| open_trades / max_open_trades | int · optional |
Example
curl -X POST https://goldscalperpro.com/api/public/ea/push \
-H "Content-Type: application/json" \
-d '{
"license_key": "GSP-XXXX-XXXX-XXXX",
"account_number": "12345678",
"status": "ACTIVE",
"symbol": "XAUUSD",
"trend": "bullish",
"signal": "buy",
"spread_points": 18,
"session_open": true,
"equity": 10432.20,
"balance": 10200.00,
"daily_pnl": 232.20,
"open_trades": 1,
"max_open_trades": 3
}'Responses
200 OK
{ "ok": true }
200 OK (refusal)
{ "ok": false, "error": "invalid_license" }
{ "ok": false, "error": "license_expired" }
{ "ok": false, "error": "account_not_bound" } // call license/validate for this account first
{ "ok": false, "error": "push_failed" }
400 Bad Request
{ "ok": false, "error": "invalid_json" }
{ "ok": false, "error": "invalid_input" }(license_id, account_number) | fields you omit are left unchanged from the previous push.MQL5 / MetaTrader 5 snippet
Drop this into your EA's OnInit(). Add the API host to Tools → Options → Expert Advisors → Allow WebRequest.
// MQL5 | OnInit() snippet
string LicenseKey = "GSP-XXXX-XXXX-XXXX";
string Url = "https://goldscalperpro.com/api/public/license/validate";
int OnInit() {
string body = StringFormat(
"{\"license_key\":\"%s\",\"account_number\":\"%I64u\",\"broker\":\"%s\",\"server\":\"%s\"}",
LicenseKey, AccountInfoInteger(ACCOUNT_LOGIN),
AccountInfoString(ACCOUNT_COMPANY), AccountInfoString(ACCOUNT_SERVER)
);
char post[]; StringToCharArray(body, post, 0, StringLen(body));
char result[]; string headers, resHeaders;
headers = "Content-Type: application/json\r\n";
int code = WebRequest("POST", Url, headers, 10000, post, result, resHeaders);
if (code != 200) { Alert("License check failed: ", code); return INIT_FAILED; }
string resp = CharArrayToString(result);
if (StringFind(resp, "\"ok\":true") < 0) { Alert("License invalid: ", resp); return INIT_FAILED; }
return INIT_SUCCEEDED;
}