44

I'm trying to send a message using Slack's chat.postMessage API call. I have no problems encoding my test messages within HTTP GET, but I'm trying to achieve the same result with JSON in a HTTP POST request.

I've been testing with both curl and Postman, but Slack doesn't seem to be acknowledging my request body at all.

{
  "ok": false,
  "error": "not_authed"
}

In curl, my request is encoded like this:

curl -H "Content-type: application/json" -X POST -d '{"token":"my-token-here","channel":"#channel-name-or-id","text":"Text here.","username":"otherusername"}'

In Postman, this is the raw body:

{
    "token":"my-token-here",
    "channel":"#channel-name-or-id",
    "text":"Text here.",
    "username":"otherusername"
}

I haven't done anything like this before, so I'm not sure if I'm missing something out. Thanks!

Valentine
  • 567
  • 1
  • 4
  • 8

11 Answers11

68

I'm a bit late, but I hope this can help other people who stumble into this issue like me. I've just been in touch with Slack, and this is what they told me:

The Slack Web API doesn't accept JSON data at all — so along with changing the Content-Type those variables should be posted using standard HTTP form attributes.

We plan to support JSON data in the future for consistency in the future.

So, your cURL line should look like:

curl -X POST -d 'token=my-token-here&channel=#channel-name-or-id&text=Text here.&username=otherusername'`

I hope this helps! :)

Community
  • 1
  • 1
finferflu
  • 1,368
  • 2
  • 11
  • 28
  • 51
    I love how they actually never really spell this out in the documentation but then give every example in JSON as if a web developer is going to look at it and think, of course I'm going to form encode my JSON object and plug it on a query string. That just makes perfect sense. – Robert Kaucher Mar 29 '16 at 23:37
  • 3
    This is so annoying. Some api calls even support sending curl -d 'payload={"json":"wtf"}'. The docs are way too ambiguous about this. – xer0x May 27 '16 at 05:43
  • 3
    This is just crazy all those Json examples and the api doesn't actualy take a Json object at all. They even have a message builder where you can build complex messages in Json but then in reality you have to carve the Json up into a querystring to make it really work. – barbary Nov 04 '16 at 16:35
  • So it doesn't take JSON, but it responds with JSON.... that makes no sense! – pronoob Jan 26 '17 at 02:54
  • The documentation over at github is is also half json, half markdown – StingyJack Feb 05 '17 at 21:24
  • 1
    this is so stupid and i'll never get back the 3 hours of my life i wasted on this – botbot Sep 04 '17 at 11:27
12

Okay, after re-reading the documentation I found it:

JSON-encoded bodies

For these write methods, you may alternatively send your HTTP POST data as Content-type: application/json.

There are some ground rules:

  • You must explicitly set the Content-type HTTP header to application/json. We won't interpret your POST body as such without it.
  • You must transmit your token as a bearer token in the Authorization HTTP header.
  • You cannot send your token as part of the query string or as an attribute in your posted JSON.
  • Do not mix arguments between query string, URL-encoded POST body, and JSON attributes. Choose one approach per request.
  • Providing an explicitly null value for an attribute will result in whichever default behavior is assigned to it.

And the curl example. Notice the Authorization header.

curl -X POST \
     -H 'Authorization: Bearer xoxb-1234-56789abcdefghijklmnop' \
     -H 'Content-type: application/json; charset=utf-8' \
    --data '{"channel":"C061EG9SL","text":""..."}' \
https://slack.com/api/chat.postMessage
LSerni
  • 55,617
  • 10
  • 65
  • 107
6

This may not qualify for the complete answer, but if the purpose is to send a message attachment, you can send a urlencoded JSON structure as the value of the attachments parameter, like so (split into multiple lines for clarity):

https://slack.com/api/chat.postMessage?
token=YOUR-TOKE-N000&
channel=%23alerts&
text=Hi&
attachments=%5B%7B%22color%22%3A%22good%22%2C%22fallback%22%3A%22plain+text%22%2C%22text%22%3A%22colored+text%22%7D%5D

The value of attachments is URL-encoded [{"color":"good","fallback":"plain text","text":"colored text"}]. You should be able to use all attachment attributes described here.

mustaccio
  • 18,234
  • 16
  • 48
  • 57
6

As of March 2018, Slack now supports POST with JSON body

Endpoint: https://slack.com/api/chat.postMessage

Headers: Authorization: Bearer xoxp-your-hardly-find-token-here

Body: {"channel":"CH9NN37","text":"something from me!"}

Notice the Bearer in the Authorization header.

MuntingInsekto
  • 1,543
  • 4
  • 19
  • 36
  • 1
    I've been using this API since **november 2017** - I wrote this answer to this very question on January 9: https://stackoverflow.com/a/48178295/1428679 - and as far as I can see, your example is exactly the same. Am I missing something, or was there some documentation kerfuffle? – LSerni May 04 '18 at 19:50
5

Slack has been updated, this now works. Try this example:

curl -X POST -H 'Content-type: application/json' --data '{"text":"This is a line of text.\nAnd this is another one."}' https://hooks.slack.com/services/AAAAAA/BBBBBB/CCCCCC

See https://api.slack.com/incoming-webhooks for documentation.

William Entriken
  • 37,208
  • 23
  • 149
  • 195
  • 2
    This doesn't (yet) appear to work for the generic web API; only for (incoming) webhooks (which, I think, don't even need authentication via a token, as in the question's example). –  Jan 29 '17 at 05:24
  • This limited example works as is. We use it in production. – William Entriken Feb 04 '17 at 07:55
3

Try putting each property in its own -d parameter, like so:

curl https://slack.com/api/chat.postMessage -X POST -d "channel=#tehchannel" -d "text=teh text" -d "username=teh user" -d "token=teh-token-you-got-from-teh-page-that-machinehead115-linked-to" -d "icon_emoji=:simple_smile:"
Linus Proxy
  • 525
  • 1
  • 5
  • 21
2

On postman you can frame your request like this:

url(POST) : https://slack.com/api/chat.postMessage

Then under Headers section put these two headers:

  1. key(Content-Type) value(application/json)

  2. key(Authorization) value(YOUR-TOKEN-NAME)

Then in Body section in raw form put your data:

    {"channel": "CHANNEL-NAME", "data": "You better post this to channel"}
1

not_authed means No authentication token provided.

Which token are you passing along in the request? You need to pass your OAuth token, which you can get from here.

machinehead115
  • 1,647
  • 10
  • 20
  • I've managed to pass my token along in a GET request, and in a POST form-body. (Those return `channel_not_found` instead.) I suspect Slack just isn't accepting JSON in a POST body. – Valentine Aug 11 '15 at 15:33
0

I did this in powershell and it works like a charm.

$url="https://slack.com/api/chat.postMessage"
    $messageContent= # your message here
    $token = # your token here
    $channel = # channel name
    $opt_username= # optional user name

    $body = @{token=$token;channel=$channel;username=$opt_username;text=$messageContent;pretty=1}

    try
    {
        Invoke-WebRequest -Uri $url -Method POST -Body $body
    }
    catch
    {
        Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__ 
        Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription        
    }
0

If you are using java and spring such dependency, Voila!! here you go

     * Make a POST call to the chat.PostMessage.
     */
    public void chatPostMessage(Message message)
    {
        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
        map.add("token", slackPostMessageToken); //Required
        map.add("text", message.getText());//Required
        map.add("channel", message.getChannelId());//Required

        map.add("unfurl_links","true");
        map.add("as_user","false");//Default false
        map.add("icon_emoji",":chart_with_upwards_trend:");
        map.add("attachments","[\n" +
                "        {\n" +
                "            \"fallback\": \"Required plain-text summary of the attachment.\",\n" +
                "            \"color\": \"#36a64f\",\n" +
                "            \"pretext\": \"Optional text that appears above the attachment block\",\n" +
                "            \"author_name\": \"Bobby Tables\",\n" +
                "            \"author_link\": \"http://flickr.com/bobby/\",\n" +
                "            \"author_icon\": \"http://flickr.com/icons/bobby.jpg\",\n" +
                "            \"title\": \"Slack API Documentation\",\n" +
                "            \"title_link\": \"https://api.slack.com/\",\n" +
                "            \"text\": \"Optional text that appears within the attachment\",\n" +
                "            \"fields\": [\n" +
                "                {\n" +
                "                    \"title\": \"Priority\",\n" +
                "                    \"value\": \"High\",\n" +
                "                    \"short\": false\n" +
                "                }\n" +
                "            ],\n" +
                "            \"image_url\": \"http://my-website.com/path/to/image.jpg\",\n" +
                "            \"thumb_url\": \"http://example.com/path/to/thumb.png\",\n" +
                "            \"footer\": \"Datoo ©\",\n" +
                "            \"ts\": "+System.currentTimeMillis()+"" +
                "        }\n" +
                "    ]");
        map.add("username","III");


        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);

        try {
            ResponseEntity<String> response = restTemplate.postForEntity(slackPostMessageUrl, request, String.class);
            System.out.println(response);
        }
        catch (RestClientException e) {
            logger.error("Error :-( : ", e);
        }
    }
piet.t
  • 11,718
  • 21
  • 43
  • 52
rbyndoor
  • 699
  • 4
  • 14
0

Below curl command worked for me.

curl -X POST -H 'Authorization: Bearer xoxb-41234078565-14457098702432-ZLJj9UFOZKnOJtjNW4dv3ukG'  -H 'Content-type: application/json; charset=utf-8'  --data '{"channel":"#general","text":"I hope the tour went well, Mr. Wonka."}' https://slack.com/api/chat.postMessage

devops-admin
  • 1,447
  • 1
  • 15
  • 26