Add slash commands
Give your community its own /commands. When a member types one, mssgs sends the message to your web service and posts what it answers: a card, buttons, a reply only they can see.
What you can do
- Answer with a cardReply with JSON and it appears in the channel as a card.
- Know who askedYou get the member and their roles, so you can check who may do what.
- Reply privatelyShow the answer only to the member who asked.
- Take your timeAnswer with a loader in 5 seconds, then finish through the callback URL.
In the app
Type / and the community's commands appear
Your service answers, mssgs posts the card
The picker and the card are the app's own. The footer says who used which command.
Quick start
Create the trigger
In the desktop app, open your community's Manage Server → Triggers and add one: the command it reacts to, such as
/weather, and the URL of your web service.Receive the message
When a member sends a message that starts with
/weather, mssgs POSTs it to your URL:json{ "server_guid": "abc12345-...", "channel_guid": "def67890-...", "trigger_match": "/weather", "message": { "id": "d01ZZdef6-...", "content": "/weather Amsterdam", "member_guid": "member-guid", "user_guid": "user-guid", "group_guids": ["group-guid-1", "group-guid-2"], "cms": 1790000000000 }, "callback_url": "https://mss.gs/api/v1/trigger-callback/...", "stream_url": "https://mss.gs/api/v1/instant/...?token=..." }Answer with JSON
Answer within 5 seconds with a 2xx status and JSON. It becomes a card in the channel.
json{ "message_container": { "color": "blue", "title": "Amsterdam", "description": "14 °C, light rain until 16:00", "fields": [ { "field": "Wind", "value": "SW 18 km/h" }, { "field": "Humidity", "value": "82%" } ] } }general
Settings
Each trigger has these settings in Manage Server → Triggers.
| Setting | What it does |
|---|---|
| Trigger Name | What the trigger is called, shown next to the command in the picker. |
| Word to Match | The text a message has to start with, such as /weather. A slash is usual, not required. |
| URL Endpoint | Where mssgs sends the message. |
| Webhook Secret | Optional. mssgs signs every request with it, see below. |
| Active | Switch the trigger off without deleting it. |
| Post Matching Message | Whether the member's own /weather Amsterdam stays in the channel above your answer. |
| Show Loading Reply | Show a loading card while your service works. |
| Allowed User Groups | Only members of these roles fire it. For anyone else it is an ordinary message. |
/deploy and /deploy-prod: which one fires is not fixed. Messages from bots and forwarded messages never fire a trigger.What you receive
A POST with a JSON body. The headers include User-Agent: mssgs-webhook/1.0.
| Field | Type | What it is |
|---|---|---|
server_guid | string | The community. |
channel_guid | string | The channel the message was sent in. |
trigger_match | string | The command that matched, such as /weather. |
message.content | string | The whole message, command included. |
message.member_guid | string | The member who sent it, in this community. |
message.user_guid | string | The same person's account, the same in every community. |
message.group_guids | array | The roles the member has. |
message.cms | number | When it was sent, in milliseconds. |
message.is_action_button | boolean | true when a button fired the trigger, not a typed command. |
message.action_payload | object | The button's payload, for button presses. |
callback_url | string | Update or delete your answer later, for 30 minutes. |
stream_url | string | A live stream of replies, reactions and button presses on your answer, for 10 minutes. |
X-Mssgs-Signature: sha256=<hex>: an HMAC-SHA256 of the raw body with your secret. Compute it yourself and compare before you trust the request.Checking who may do what
Compare message.group_guids with the roles you trust, for example to let only moderators run /ban. To keep a command away from everyone else entirely, set its roles in the trigger's settings.
What you answer
Any 2xx status with a JSON body, up to 4 MB. Send at least one of message_container or actions.
| Field | Type | What it is |
|---|---|---|
message_container | object | The card. Every field on message cards works here, including the status pill, badge, diff stats and folded reasoning. |
title, description, color, ... | string | Shorthand: card fields at the top level are wrapped into a card for you. |
actions | array | Buttons under the card. See buttons. |
visible_to_member_guids | array | Only these members see the answer. See private replies. |
content line is not shown on a command reply's card, so put what matters in the card itself.Five seconds
mssgs waits 5 seconds for your answer. If you need longer, answer straight away with a loader card and finish through callback_url, which stays valid for 30 minutes.
// Answer within 5 seconds with a loader...
res.json({ message_container: { loader: true, loader_text: 'Looking it up…' } });
// ...then finish in your own time with the callback URL.
await fetch(req.body.callback_url, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message_container: { color: 'blue', title: 'Done', description: result } })
});Private replies
Put member ids in visible_to_member_guids and only they see your answer. Use the member_guid from the request to answer only the person who asked.
{
"message_container": {
"color": "green",
"title": "You're on the list",
"description": "Only you can see this reply."
},
"visible_to_member_guids": ["<message.member_guid from the request>"]
}A full example
A /weather command in Node.js with Express, answering with a card.
import express from 'express';
const app = express();
app.use(express.json());
app.post('/mssgs/weather', async (req, res) => {
const city = req.body.message.content.replace('/weather', '').trim() || 'Amsterdam';
const w = await getWeather(city); // your own lookup
res.json({
message_container: {
color: 'blue',
title: city,
description: `${w.temp} °C, ${w.summary}`,
fields: [
{ field: 'Wind', value: w.wind },
{ field: 'Humidity', value: `${w.humidity}%` }
]
}
});
});
app.listen(3000);Limits
| Limit | Value |
|---|---|
| Time to answer | 5 seconds |
| Answer size | 4 MB |
| Commands per member | 5 every 5 seconds |
| Updating the answer afterwards | 30 minutes, through callback_url |
| Live stream of the answer | 10 minutes, through stream_url |