Featured image of post How to Post Messages to Slack using C++ (Win32 API + WinHTTP) [Webhook Supported]

How to Post Messages to Slack using C++ (Win32 API + WinHTTP) [Webhook Supported]

How to Post Messages to Slack using C++ (Win32 API + WinHTTP) [Webhook Supported]

I want to post messages to Slack from C++. It’s common in Node.js or Python, but doing it with “C++ × Win32 API × WinHTTP” is quite rare, isn’t it?

In this article, I will explain how to send messages from C++ to Slack using a Webhook URL, step-by-step and in an easy-to-understand manner.


✅ Overall Flow

To post to Slack, follow these steps:

  1. Obtain a Slack Webhook URL (API key)
  2. Send a POST request using WinHTTP
  3. Assemble the message body in JSON format
  4. Check the result and you’re done!

🔑 Step 1: How to Obtain a Slack Webhook URL

Slack allows you to easily post messages from external services using a feature called Incoming Webhooks.

Steps to Obtain

  1. Access https://api.slack.com/apps
  2. Click Create New App
  3. Choose From scratch, then select the app name and the workspace to post to
  4. Select “Incoming Webhooks” from the left menu and enable it
  5. Click “Add New Webhook to Workspace” and select a channel
  6. Copy the generated URL (e.g., https://hooks.slack.com/services/xxx/yyy/zzz)

This URL functions like an API key.


💻 Step 2: Send a Message to Slack with C++ Code

Technologies Used

  • Win32 API
  • WinHTTP (Standard Library)
  • JSON formatted messages

Sample Code (Posting to Slack)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <windows.h>
#include <winhttp.h>
#include <iostream>

#pragma comment(lib, "winhttp.lib")

bool PostToSlack(const std::wstring& webhookUrl, const std::string& messageJson) {
    // Parse URL
    URL_COMPONENTS urlComp{};
    wchar_t hostName[256];
    wchar_t urlPath[1024];

    urlComp.dwStructSize = sizeof(urlComp);
    urlComp.lpszHostName = hostName;
    urlComp.dwHostNameLength = _countof(hostName);
    urlComp.lpszUrlPath = urlPath;
    urlComp.dwUrlPathLength = _countof(urlPath);

    if (!WinHttpCrackUrl(webhookUrl.c_str(), 0, 0, &urlComp)) {
        std::wcerr << L"Failed to parse URL\n";
        return false;
    }

    // Connect and start HTTP session
    HINTERNET hSession = WinHttpOpen(L"SlackPoster/1.0",
                                     WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                                     WINHTTP_NO_PROXY_NAME,
                                     WINHTTP_NO_PROXY_BYPASS, 0);
    HINTERNET hConnect = WinHttpConnect(hSession, hostName, urlComp.nPort, 0);
    HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", urlPath,
                                            NULL, WINHTTP_NO_REFERER,
                                            WINHTTP_DEFAULT_ACCEPT_TYPES,
                                            WINHTTP_FLAG_SECURE);

    std::wstring headers = L"Content-Type: application/json\r\n";
    BOOL result = WinHttpSendRequest(hRequest,
                                     headers.c_str(),
                                     -1,
                                     (LPVOID)messageJson.c_str(),
                                     messageJson.length(),
                                     messageJson.length(),
                                     0);

    if (!result) {
        std::cerr << "Send request failed\n";
        return false;
    }

    WinHttpReceiveResponse(hRequest, NULL);

    DWORD statusCode = 0;
    DWORD size = sizeof(statusCode);
    WinHttpQueryHeaders(hRequest,
                        WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
                        WINHTTP_HEADER_NAME_BY_INDEX,
                        &statusCode, &size, WINHTTP_NO_HEADER_INDEX);

    // Release resources
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);

    return (statusCode == 200);
}

int main() {
    std::wstring webhookUrl = L"https://hooks.slack.com/services/xxx/yyy/zzz"; // Replace with your Webhook URL

    std::string message = R"({
        "text": "Hello from C++ :rocket:",
        "username": "C++ Bot",
        "icon_emoji": ":robot_face:"
    })";

    if (PostToSlack(webhookUrl, message)) {
        std::cout << "Posted successfully!\n";
    } else {
        std::cerr << "Failed to post.\n";
    }

    return 0;
}

🧪 Customizing JSON Messages

With Slack Webhooks, you can include parameters like the following:

1
2
3
4
5
6
{
  "text": "Notification content",
  "username": "Bot name",
  "icon_emoji": ":rocket:",
  "channel": "#desired_channel_name"
}

📌 Supplementary Notes

  • Content-Type must be specified as "application/json"
  • Pass the Webhook URL as a wstring without any changes (URL encoding is unnecessary)
  • Since it’s HTTPS communication, don’t forget WINHTTP_FLAG_SECURE

🎉 Bonus: Example of Post Confirmation in Slack

It will be displayed in Slack like this:

1
2
[C++ Bot]
Hello from C++ :rocket:

✍️ Summary

ItemDetails
Posting MethodWebhook (Incoming Webhooks)
Communication LibraryWinHTTP
Data FormatJSON
Usable Parameterstext, username, icon_emoji, channel, etc.

Even if you thought “Integrating C++ with Slack? No way…”, you can start embedding a notification bot today!


🚀 Teaser for Next Time?

If you’re interested, next time:

  • File attachments
  • UI with buttons
  • Flexible API operations with Slack App + OAuth2

I can introduce you to more advanced Slack integrations like these!

comments powered by Disqus