Sign up with our partner broker and get free XAU/USD signals. JOIN US
LIVE MT5 BUILD 5830 LAST REV 2026-05-23
SESSION -- UTC --:--
SESSIONS
SYDNEY22:00–07:00 UTC
TOKYO00:00–09:00 UTC
LONDON07:00–16:00 UTC
NEW YORK12:00–21:00 UTC

Sending MT5 alerts to Slack, Discord, and Teams via webhooks

MT5 ships with built-in alerts (popups, sounds, email, push) but no webhook support. With a few lines of MQL5 and the WebRequest function, you can pipe alerts to Slack, Discord, Teams, or any other webhook-accepting service. Here is the working pattern.

PUBLISHED 2026-05-24 READING TIME 11 MIN MT5 BUILD 5830 CATEGORY TOOLS
Critical setup step: Before any WebRequest call works, you must add the destination URL to the MT5 allowed URLs list. Open Tools → Options → Expert Advisors and add the host (e.g. https://hooks.slack.com) to the "Allow WebRequest for listed URL" field. Without this, every WebRequest call fails silently with error 4060.

1. The WebRequest function

MQL5 exposes WebRequest for outbound HTTP calls. Two function signatures exist; the one used for sending JSON to webhook services:

int WebRequest(
   const string  method,        // "POST" or "GET"
   const string  url,           // Full URL
   const string  headers,       // HTTP headers
   int           timeout,       // ms
   const char    &data[],       // Request body as byte array
   char          &result[],     // Response body
   string        &result_headers // Response headers
);

The function returns the HTTP status code (200 for success) or -1 for transport errors. Check GetLastError() for specific failure codes; the common ones are 4060 (URL not in allowed list) and 4014 (function not allowed).

2. Slack webhook

Slack incoming webhooks are the simplest case. Get a webhook URL from Slack: Apps → Incoming Webhooks → Add to workspace → choose a channel. The URL looks like https://hooks.slack.com/services/T0XXXXX/B0XXXXX/XXXXXXXXX.

The payload is JSON with a single text field for plain text:

void SendSlackAlert(string message)
{
   string url = "https://hooks.slack.com/services/T0XXXXX/B0XXXXX/XXXXXXXXX";
   string headers = "Content-Type: application/json\r\n";
   string payload = "{\"text\": \"" + message + "\"}";

   char data[], result[];
   string result_headers;
   StringToCharArray(payload, data, 0, StringLen(payload));

   int res = WebRequest("POST", url, headers, 5000, data, result, result_headers);
   if(res != 200)
      Print("Slack webhook failed: HTTP ", res, " error ", GetLastError());
}

Call SendSlackAlert("Trade opened: XAUUSD long at 2380.50") wherever you want a notification.

3. Discord webhook

Discord webhooks work similarly. In Discord: Server Settings → Integrations → Webhooks → New Webhook. The URL format is https://discord.com/api/webhooks/XXXXX/XXXXX.

Discord accepts a content field for plain text and an embeds array for richer formatting:

void SendDiscordAlert(string message)
{
   string url = "https://discord.com/api/webhooks/XXXXX/XXXXX";
   string headers = "Content-Type: application/json\r\n";
   string payload = "{\"content\": \"" + message + "\"}";

   char data[], result[];
   string result_headers;
   StringToCharArray(payload, data, 0, StringLen(payload));

   int res = WebRequest("POST", url, headers, 5000, data, result, result_headers);
   if(res != 204)  // Discord returns 204 No Content on success
      Print("Discord webhook failed: HTTP ", res, " error ", GetLastError());
}

Note Discord's success code is 204, not 200. The function signature is otherwise identical.

4. Microsoft Teams webhook

Teams webhooks expect a slightly different payload structure using the MessageCard schema or the newer Adaptive Card format. Get a webhook URL from Teams: channel → Connectors → Incoming Webhook → Configure.

void SendTeamsAlert(string title, string message)
{
   string url = "https://outlook.office.com/webhook/XXXXX/IncomingWebhook/XXXXX/XXXXX";
   string headers = "Content-Type: application/json\r\n";
   string payload = "{\"@type\":\"MessageCard\",\"@context\":\"http://schema.org/extensions\","
                  + "\"summary\":\"" + title + "\","
                  + "\"title\":\"" + title + "\","
                  + "\"text\":\"" + message + "\"}";

   char data[], result[];
   string result_headers;
   StringToCharArray(payload, data, 0, StringLen(payload));

   int res = WebRequest("POST", url, headers, 5000, data, result, result_headers);
   if(res != 200)
      Print("Teams webhook failed: HTTP ", res, " error ", GetLastError());
}

5. Building useful alerts

The interesting question is not how to send a webhook but what to send. Useful alert content for trading:

EventAlert content
Trade openedSymbol, direction, lot size, entry price, stop loss, take profit
Trade closedSymbol, exit price, profit/loss in deposit currency, hold time
Stop loss hitSymbol, lot size, loss amount, account equity remaining
Daily loss limit reachedAccount equity, drawdown percentage, EA disabled status
Connection lostTimestamp, last successful tick, alert priority
EA errorFunction name, error code, suggested action

The pattern: build a message string in OnTrade or wherever the event occurs, then call your SendXxxAlert function.

6. Hooking into trade events

The cleanest way to notify on trades is the OnTradeTransaction callback. MQL5 calls this function whenever any trade-related event occurs:

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
   if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
   {
      string msg = StringFormat("Deal: %s %.2f lots %s at %.5f",
         (trans.deal_type == DEAL_TYPE_BUY ? "BUY" : "SELL"),
         trans.volume,
         trans.symbol,
         trans.price);
      SendSlackAlert(msg);
   }
}

This fires on every executed deal. Filter by symbol or magic number if you want to limit notifications.

7. Rate limits

Webhook services impose rate limits to prevent abuse:

  • Slack: approximately 1 message per second per webhook. Bursts of a few messages are tolerated.
  • Discord: 5 messages per 2 seconds per webhook, beyond which you receive HTTP 429 with a Retry-After header.
  • Teams: generally 4 messages per second, but Microsoft has been known to tighten limits without notice.

For a normal EA sending a few alerts per day, you will not hit limits. If you ever loop and send many messages quickly (e.g. on EA startup looping through historical trades), batch them or add small delays.

8. Authentication and security

Webhook URLs are themselves secrets. Anyone with the URL can post to your channel. Treat them as you would a password:

  • Do not commit webhook URLs into source code you publish or share.
  • Use inputs in your EA so the URL is configured at attach time, not hardcoded.
  • If a webhook URL is leaked, revoke it at the service and generate a new one.
  • Do not include sensitive data (account passwords, broker credentials) in alert messages even though the webhook is private.

9. Formatting messages

Beyond plain text, each service supports richer formatting:

Slack

Slack supports markdown-like formatting in the text field: *bold*, _italic_, ~strike~, ` + "`code`" + `. For richer layouts use the blocks array with structured Block Kit JSON.

Discord

Discord supports markdown (**bold**, *italic*, __underline__, code blocks with triple backticks). Embeds let you add structured fields, colours, thumbnails, and footers. Embed example:

{
  "embeds": [{
    "title": "Trade Opened",
    "description": "XAUUSD long",
    "color": 5763719,
    "fields": [
      {"name": "Entry", "value": "2380.50", "inline": true},
      {"name": "SL", "value": "2376.50", "inline": true}
    ]
  }]
}

Teams

Teams MessageCard supports sections, facts (key/value pairs), images, and action buttons. The newer Adaptive Card format is more flexible but requires the AdaptiveCard schema.

10. Debugging webhook failures

When alerts do not arrive, check in this order:

  1. Is the URL added to MT5's allowed list? Tools → Options → Expert Advisors. Without this, WebRequest returns -1 immediately.
  2. Is "Allow WebRequest" checked in the EA properties? Right-click EA on chart → Properties → Common.
  3. Print the HTTP status and last error after each WebRequest call.
  4. Test the webhook URL outside MT5 (curl, Postman, or browser). If it works there, the issue is in MT5; if it fails there too, the webhook is misconfigured at the service end.
  5. Check that your JSON is valid. Quote escaping inside MQL5 strings is error-prone. Print the payload before sending and paste it into a JSON validator.

FAQ

Does WebRequest work in the Strategy Tester?

No. WebRequest is disabled in the Strategy Tester. Alerts are only sent in live or demo trading. For testing, mock the alert function to just Print the message.

Can I use webhooks to receive commands, not just send alerts?

Not directly. WebRequest is outbound only. To receive external commands (e.g. close all trades from a Slack command), you need a polling architecture: the EA periodically WebRequests a status endpoint, the external system posts commands to that endpoint, the EA acts on what it reads.

What is the latency of a webhook alert?

Typically 200ms to 1 second from WebRequest call to message appearing in the destination. Slow internet or service degradation can push this to several seconds. Not real-time, but fast enough for trade notifications.

Can I send images or files via webhooks?

Slack and Discord support image attachments via webhook, but you must upload the file to a publicly-accessible URL first and reference that URL in the payload. MT5 cannot directly upload binary files; you would need an intermediate server. For chart screenshots, taking and uploading is more involved than typical retail traders attempt.

Are there official MQL5 libraries for these services?

Not from MetaQuotes. Community libraries exist on MQL5 Code Base for Slack and Discord integration. They wrap the raw WebRequest pattern into nicer interfaces. Code quality varies; review before using.