[SOLVED] Direct Message with REST API issue

Hello,
l am new to mattermost and l find it lovely.

l want to use REST API to send direct message to a user.

When there is a direct message already opened, or had been opened with that user,
REST API works.
curl -i -X POST -d ‘payload={“channel”: “@[USERID]”, “text”: “:white_check_mark: [MESSAGE]”}’ http://[INCOMING WEBHOOK URL]

However, when there is no history of direct messaging with that user,
REST API failes with this return.

HTTP/1.1 307 Temporary Redirect
Content-Security-Policy: frame-ancestors ‘none’
Location: /error?title=Mattermost+needs+your+help%3A&message=Couldn%27t+find+the+channel&details=err%3Dstore.sql_channel.get_by_name.missing.app_error&link=%2F&linkmessage=Go+back+to+Mattermost
X-Frame-Options: DENY
X-Ratelimit-Limit: 100
X-Ratelimit-Remaining: 99
X-Ratelimit-Reset: 1
X-Request-Id: ymrzak8jefnsfexe7yqzpqzh7a
X-Version-Id: 3.0.0.1468997210
Date: Mon, 25 Jul 2016 08:22:31 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

ls it impossible to initiate a new direct message with REST API?
lf there is a way to do this, please let me know!

Thank you in advance.

Hi warmcool,

Direct message channels are treated the same as regular channels so they have to be explicitly created before you can send a message on them. That being said, I think it would make sense for webhooks to automatically create the direct channel if possible, so I’ve created an improvement ticket to add this feature.

In the meantime, you’ll need to use the full web API to do this. We have Mattermost drivers that will make this easier if you’re using Javascript or Go. Both of those provide a createDirectChannel method taking the unique ID (not the username) of the user you want to create a DM channel for. If you aren’t using either of those, the API is directly available at /api/v3/TEAM_ID/channels/create_direct and it takes a JSON object of the form {"user_id":"USER_ID"}.

Hi @warmcool, can you help me understand the context in which you’d like to send a direct message via a webhook? I’d encourage you to create a feature request on our feature idea forum with some explanation on how this might be used.

Hi. I’m working with the python mattermost driver module and writing a python bot. I’m also having problems with direct messages. Specific questions:

  1. The above doesn’t really lay out how to use the JSON API to create a direct message channel proactively, i.e. from the bot to a user. From the text above, it sounds like it’s possible, but it’s not really explained.

  2. how do I detect if a post coming in via the websockets stream is a direct message post?

Below is the pretty-printed JSON from such a message. I notice there’s a channel_type=‘D’, I’m guessing that means direct message.

2a) related request, it’d be handy if the API docs website had some way to search for a given JSON variable name and see a definition of it. The existing search function appears to match it to any occurrence of the string in the command page.

2b) Could we have a plain vanilla version of the API docs without the spiffy javascript formatting tricks? The current layout, while elegant and nifty, makes it hard to use external search engines on the API docs.

(’{\n’
’ “broadcast”: {\n’
’ “channel_id”: “umach1cai3bpjyy193qcpnc7cc”,\n’
’ “omit_users”: null,\n’
’ “team_id”: “”,\n’
’ “user_id”: “”\n’
’ },\n’
’ “data”: {\n’
’ “channel_display_name”: “”,\n’
’ “channel_name”: ‘
’“cm966xfpfpgnjrfhgsygok5dew__hs3cybr747di9nxjdxgsj1bdrc”,\n’
’ “channel_type”: “D”,\n’
’ “mentions”: “[\“cm966xfpfpgnjrfhgsygok5dew\”]”,\n’
’ “post”: ‘
’"{\“id\”:\“5udj3thkgfr3bd6k7r8puuzt6e\”,\“create_at\”:1514066441361,\“update_at\”:1514066441361,\“edit_at\”:0,\“delete_at\”:0,\“is_pinned\”:false,\“user_id\”:\“hs3cybr747di9nxjdxgsj1bdrc\”,\“channel_id\”:\“umach1cai3bpjyy193qcpnc7cc\”,\“root_id\”:\"\",\“parent_id\”:\"\",\“original_id\”:\"\",\“message\”:\“channels\”,\“type\”:\"\",\“props\”:{},\“hashtags\”:\"\",\“pending_post_id\”:\"\"}",\n’
’ “sender_name”: “puff”,\n’
’ “team_id”: “”\n’
’ },\n’
’ “event”: “posted”,\n’
’ “seq”: 19\n’
’}’)
Embedded json from post:
(’{\n’
’ “channel_id”: “umach1cai3bpjyy193qcpnc7cc”,\n’
’ “create_at”: 1514066441361,\n’
’ “delete_at”: 0,\n’
’ “edit_at”: 0,\n’
’ “hashtags”: “”,\n’
’ “id”: “5udj3thkgfr3bd6k7r8puuzt6e”,\n’
’ “is_pinned”: false,\n’
’ “message”: “channels”,\n’
’ “original_id”: “”,\n’
’ “parent_id”: “”,\n’
’ “pending_post_id”: “”,\n’
’ “props”: {},\n’
’ “root_id”: “”,\n’
’ “type”: “”,\n’
’ “update_at”: 1514066441361,\n’
’ “user_id”: “hs3cybr747di9nxjdxgsj1bdrc”\n’
’}’)

I took a closer look at the channels section of the API docs:

https://api.mattermost.com/#tag/channels%2Fpaths%2F~1channels%2Fpost

There’s this parameter:
type
string Required
’O’ for a public channel, ‘P’ for a private channel

That’s ‘P’ for Private, not ‘D’ for Direct Message. Are these different types?

I guess I could:

  1. post to /channels to create a new, private channel

  2. post to /channels/newly_created_channel_id/members to add the recipient to the private channel

  3. post to /posts to send the message to the newly created private channel

That seems cumbersome, is this really the right way to do it?

  1. Take a look at https://api.mattermost.com/#tag/channels%2Fpaths%2F~1channels~1direct%2Fpost. You essentially just provide two user ids in the request body and the direct message channel will be created if it does not already exist.

  2. The “channel_type” field will be “D” for posts coming from a direct message. Use the included “channel_id” to discover exactly which channel

2ab) We use ReDoc and OpenAPI to create the API reference, you can view/search just the plain YAML at https://api.mattermost.com/static/mattermost-openapi-v4.yaml if you like.

By the way, the source for the API reference lives here https://github.com/mattermost/mattermost-api-reference

Thanks. The JSON example on that page is just:

[
“string”
]

Should it instead be this?

[ “user_id1”, “user_id2”]

Yes, that would be correct

I have this sort of working, from the bot to the user.

If I do: /msg @botname do some command

Then the bot receives the post containing “do some command”, parses it and reacts.

But if I open the DM channel by clicking on it and type: do some command

Then the bot receives a “typing” event but doesn’t receive a post of “do some command”. Doesn’t receive anything at all, aside from the typing event.

What am I missing?

To be clear, I just realized I was making an assumption from your description and reading the API reference, that a /channels/direct call will:

EITHER:

  1. respond with a JSON description of an existing direct message channel
    OR:
  2. create a direct message channel and respond with the JSON description of it

Is this correct?

Yes, that’s correct it will create the channel and return it or return the existing channel.

For your previous question, if the bot is connected to the WebSocket it should be getting “posted” events for any channels it’s in, including DMs. You can try clearing your caches by going to System Console -> General -> Configuration -> Purge All Caches but really if you’re getting “user_typing” events you should be getting the “posted” events as well

Hm, well I’m not getting the actual posts from the DM channel, just the typing events.

Here’s the JSON I get back from setting up the DM channel:

{‘create_at’: 1508821648763,
‘creator_id’: ‘’,
‘delete_at’: 0,
‘display_name’: ‘’,
‘extra_update_at’: 1508821648763,
‘header’: ‘’,
‘id’: ‘umach1cai3bpjyy193qcpnc7cc’,
‘last_post_at’: 1515729326775,
‘name’: ‘cm966xfpfpgnjrfhgsygok5dew__hs3cybr747di9nxjdxgsj1bdrc’,
‘purpose’: ‘’,
‘team_id’: ‘’,
‘total_msg_count’: 44,
‘type’: ‘D’,
‘update_at’: 1508821648763}

One thought I had: what if the DM channel is created but the bot’s not being added to it?

I took a look at the add user to channel API call to see if I could try having the bot call that and add itself to the channel:

https://api.mattermost.com/#tag/channels%2Fpaths%2F~1channels~1{channel_id}~1members%2Fpost

But I’m a bit mystified about the “post_root_id”.

Hm… well, mysteriously it’s started working. I’m not sure what changed. I suspect that there was a subtle bug in my code that was causing some sort of silent error.