Hoppa till huvudinnehållet
Utvecklare Webhooks

Posta meddelanden med en webhook

En webhook är en URL som postar i din community. Skicka JSON till den från allt som kan göra ett HTTP-anrop, som CI, övervakning, ett cron-jobb eller ett skript, så dyker meddelandet upp i kanalen.

Det här kan du göra

  • Posta text eller ett kortRen text, eller ett kort med rubrik, färg, markdown, fält och bilder.
  • Bifoga filerUpp till fem filer per meddelande: loggar, rapporter, skärmbilder.
  • Lägg till knapparLänkar, eller knappar som ändrar kortet eller når din tjänst.
  • Ändra det senareSvaret innehåller en callback-URL som uppdaterar eller raderar meddelandet.

I appen

$ curl -X POST "$MSSGS_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-H "X-Mssgs-Signature: sha256=$SIG" \
-d '{"message_container": {"title": "Bygge #1847 lyckades", ...}}'
{"success": true, "message_id": "aZZ1a2b-..."}

Ett anrop från CI, ett kort i #deploys. Namnet högst upp är namnet du gav webhooken.

Snabbstart

  1. Skapa webhooken

    Öppna Hantera community → Webhooks för din community i skrivbordsappen, skapa en webhook, välj vilka kanaler den får posta i och kopiera URL:en för en kanal. Den ser ut så här:

    url
    https://mss.gs/api/v1/webhook/{webhook_guid}/{token}/{channel_guid}
  2. Skicka ett meddelande

    Signera JSON:en med webhookens hemlighet och gör en POST med den. En webhook som du skapar i skrivbordsappen har alltid en: kopiera den under Webhook-hemlighet i webhookens inställningar.

    bash
    BODY='{"content": "Build #1847 passed on main"}'
    SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MSSGS_WEBHOOK_SECRET" | sed 's/^.* //')
    
    curl -X POST "$MSSGS_WEBHOOK_URL" \
      -H "Content-Type: application/json" \
      -H "X-Mssgs-Signature: sha256=$SIG" \
      -d "$BODY"
  3. Läs svaret

    Svaret ger dig meddelandets id och en callback_url som ändrar meddelandet senare.

    json
    {
      "success": true,
      "message_id": "aZZ1a2b-...",
      "callback_url": "https://mss.gs/api/v1/trigger-callback/8f14e45f-...",
      "stream_url": "https://mss.gs/api/v1/instant/6b1e...c0?token=a1b2c3d4-..."
    }
Alla som har URL:en och hemligheten kan posta i den kanalen. Håll båda borta från publika repon och kod på klientsidan.

Vad du kan skicka

Ett meddelande är antingen den korta formen (text med rubrik och färg) eller ett helt kort, och båda kan ha knappar och filer. Namnet högst upp på kortet är alltid webhookens eget namn. I webhookens inställningar bestämmer du också om den får posta bilder och nämna personer.

Kort form

Räcker för de flesta larm.

json
{
  "content": "Server backup completed at 03:00 UTC",
  "color": "green",
  "title": "Backup Bot"
}
FältTypVad det gör
contentstringMeddelandets text. Krävs om du inte skickar ett kort eller filer.
colorstringblue (standard), green, orange, red, yellow eller purple.
titlestringEn rubrik ovanför texten. Standard är webhookens namn.

Ett helt kort

Skicka en message_container för ett kort med länkad rubrik, underrubrik, markdown, fält och bilder. Via en webhook tar ett kort emot type, color, title, title_url, sub_title, description, fields, avatar_url, image_url, image_base64, images och laddningsfälten. Statuspillen, märket, diff-statistiken och det hopfällda resonemanget är till för kommandosvar. Alla fält finns under meddelandekort.

json
{
  "message_container": {
    "type": "embed_message",
    "color": "green",
    "title": "Build #1847 passed",
    "title_url": "https://ci.example.com/builds/1847",
    "description": "All 212 tests green on **main**.",
    "fields": [
      { "field": "Duration", "value": "2m 34s" },
      { "field": "Commit", "value": "1a2b3c4" }
    ]
  }
}
deploys
System
Meddelande från CI

Bygge #1847 lyckades

Alla 212 tester gröna på main.
Duration
2m 34s
Commit
1a2b3c4

Knappar

Lägg till en actions-array för att sätta knappar under meddelandet. Hur de fungerar står under knappar.

Filer

Posta riktiga filer med ett meddelande: en logg, en rapport, en skärmbild. De visas som vilken bilaga som helst, som en nedladdningsrad eller inbäddade för bilder, video och ljud. Ett meddelande med bara filer går bra: utelämna content och kortet.

json
{
  "message_container": {
    "color": "orange",
    "title": "Log dump: ios",
    "description": "DMs stopped arriving after switching networks"
  },
  "attachments": [
    {
      "name": "mssgs-logs-20260803-141205.log",
      "content_base64": "MjAyNi0wOC0wMyAxNDoxMjowNSBbV1NdIGNvbm5lY3RlZAo=",
      "mime_type": "text/plain"
    }
  ]
}
FältTypVad det gör
namestringFilnamnet den laddas ned som. Krävs. En sökväg kortas ned till sin sista del.
content_base64stringFilens bytes som base64, råa eller som en data:-URI. mssgs sparar filen och behåller bara en länk på meddelandet.
mime_typestringInnehållstypen för content_base64. Standard är text/plain.
urlstringEn fil som redan finns på mssgs: en /static/...-sökväg eller en https://mss.gs/...-URL.
Skicka exakt en av content_base64 eller url per fil. Båda, eller ingen av dem, är ett fel.
GränsVärde
Filer per meddelande5
Storlek per fil, efter avkodning8 MB
Filnamn200 tecken
Hela anropetCirka 10 MB. Base64 gör en fil en tredjedel större, så en enskild fil över ungefär 7 MB får inte plats.

Varför url bara tar emot mssgs-adresser

En webhook-URL hamnar ofta inklistrad i andra dashboards. En URL som har läckt får inte kunna användas för att få varje medlems app att hämta en fil från en server som någon annan har valt. Ligger din fil någon annanstans skickar du den som content_base64, så hostar mssgs den.

En misslyckad uppladdning stoppar inte meddelandet

Filerna kontrolleras direkt men laddas upp efteråt. Misslyckas en uppladdning utelämnas den filen och resten av meddelandet postas ändå, utan något fel: hellre förlora filen än rapporten. Är en fil viktig bör du kontrollera att den kom fram.

En fil från kommandoraden

bash
BODY='{"attachments":[{"name":"report.csv","content_base64":"'"$(base64 < report.csv | tr -d '\n')"'","mime_type":"text/csv"}]}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MSSGS_WEBHOOK_SECRET" | sed 's/^.* //')

printf '%s' "$BODY" | curl -sS -X POST "$MSSGS_WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -H "X-Mssgs-Signature: sha256=$SIG" \
  --data-binary @-

Signera anrop

En webhook med en hemlighet tar bara emot anrop som bevisar att de känner till den, och en webhook som du skapar i skrivbordsappen har alltid en (Webhook-hemlighet i dess inställningar). Signera den råa bodyn i anropet med HMAC-SHA256 och hemligheten, och skicka hex-digesten i gemener i headern X-Mssgs-Signature som sha256=<hex>.

javascript
import crypto from 'node:crypto';

const body = JSON.stringify({ content: 'Deploy finished' });
const signature = crypto.createHmac('sha256', process.env.MSSGS_WEBHOOK_SECRET)
  .update(body)
  .digest('hex');

await fetch(process.env.MSSGS_WEBHOOK_URL, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Mssgs-Signature': `sha256=${signature}`
  },
  body
});
Ett anrop utan giltig signatur får 401 och {"error": "INVALID_SIGNATURE"}. Bara en webhook utan hemlighet, till exempel en som skapats via MCP utan webhook_secret, tar emot osignerade anrop.

GitHubs egen header X-Hub-Signature-256 accepteras också, så en GitHub-webhook med samma hemlighet fungerar som den är. Signaturen har ingen tidsstämpel, så den hindrar inte att ett uppsnappat anrop skickas igen: det är fortfarande URL:en som är den hemlighet som räknas.

Svar och fel

Ett meddelande som har postats kommer tillbaka med sitt id och en callback_url som uppdaterar eller raderar det i 30 minuter.

json
{
  "success": true,
  "message_id": "aZZ1a2b-...",
  "callback_url": "https://mss.gs/api/v1/trigger-callback/8f14e45f-...",
  "stream_url": "https://mss.gs/api/v1/instant/6b1e...c0?token=a1b2c3d4-..."
}
Läs bodyn, inte bara statusen. En avvisad payload har orsaken som en error-kod i bodyn. Behandla varje body med en error-nyckel som ett misslyckande, oavsett statuskod.
http
HTTP/1.1 200 OK
Content-Type: application/json

{ "error": "ATTACHMENT_TOO_LARGE" }
javascript
const res = await fetch(webhookUrl, { method: 'POST', headers, body });
const reply = await res.json().catch(() => null);

// A rejected payload still comes back as 200: read the body.
if (!res.ok || (reply && reply.error)) {
  throw new Error(`webhook rejected: ${reply?.error ?? res.status}`);
}

När meddelandet har knappar innehåller svaret också en stream_url: en liveström av svaren, reaktionerna och knapptrycken på meddelandet, öppen i 10 minuter, eller en timme när du skickar "sse_event_extended_timeout": true. Se liveuppdateringar.

Statuskoder

StatusNär
401Webhooken har en hemlighet och signaturen saknas eller är fel.
403Den här webhooken får inte posta i den kanalen.
404Det finns ingen webhook på den här URL:en.
413Anropet är för stort.
429För många anrop. Sakta ned och försök igen.
502Meddelandet kunde inte levereras. Försök igen.

Felkoder

KodBetydelse
MISSING_CONTENTInget att posta: ingen text, inget kort och inga filer.
INVALID_MESSAGE_CONTAINERmessage_container är inte ett objekt.
INVALID_MESSAGE_CONTAINER_TYPEKorttypen är varken embed_message eller system_message.
MISSING_MESSAGE_CONTAINER_DESCRIPTIONEtt kort behöver en beskrivning, om det inte är ett laddningskort.
MISSING_MESSAGE_CONTAINER_LOADER_TEXTEtt laddningskort behöver loader_text.
INVALID_WEBHOOK_BINDINGDen här webhooken får inte posta i den kanalen.
INVALID_SIGNATURESignaturheadern saknas eller är fel.
REQUEST_BODY_TOO_LARGEAnropet är över storleksgränsen.
PUBLISH_FAILEDMeddelandet kunde inte levereras.
INVALID_ACTIONS_FORMAT, INVALID_ACTION_MISSING_FIELDS, DUPLICATE_ACTION_ID, INVALID_TRIGGERS_FORMAT, INVALID_TRIGGER_MISSING_ACTION, INVALID_TRIGGER_ACTION_NOT_ALLOWEDNågot är fel med en knapp. Se knappar.

Filfel

KodBetydelse
INVALID_ATTACHMENTS_FORMATattachments är inte en lista, eller en post är inte ett objekt.
TOO_MANY_ATTACHMENTSFler än fem filer.
MISSING_ATTACHMENT_NAMEEn fil saknar namn.
INVALID_ATTACHMENT_NAMENamnet blir inget användbart när det kortas ned, som ...
MISSING_ATTACHMENT_SOURCEVarken url eller content_base64.
AMBIGUOUS_ATTACHMENT_SOURCEBåde url och content_base64.
INVALID_ATTACHMENT_BASE64Base64-datan går inte att avkoda.
ATTACHMENT_TOO_LARGEEn fil är över 8 MB efter avkodning.
INVALID_ATTACHMENT_URLurl är inte en mssgs-adress.

Gränser

GränsVärde
Anropets storlekCirka 10 MB
Filer per meddelande5, på upp till 8 MB var
Kortets beskrivningUpp till 50 000 byte. Efter 1 000 byte ser medlemmarna början och en Visa mer-knapp.
Uppdatera meddelandet efteråt30 minuter, via callback_url
Liveström för ett meddelande med knappar10 minuter, eller en timme på begäran

Anropen är hastighetsbegränsade. När du får en 429 väntar du innan du skickar igen, och samlar larm som kommer i skurar i ett enda meddelande.

GitHub, UniFi och App Store Connect

Peka en av de här tjänsterna mot en webhook-URL så känner mssgs igen den och postar ett ordentligt kort, utan någon payload att skriva. Se integrationer. De här svarar med {"success": true} och ingen callback-URL.

KällaKänns igen påVad den postar
GitHubHeadern x-github-eventPushar, pull requests och granskningar, issues och kommentarer, brancher och taggar, releaser. En skur av ändringar i samma issue eller pull request samlas i ett kort.
UniFi ProtectUser agent protect-alarm-managerRingningar på dörrklockan, rörelse, och personer, fordon eller paket som dina kameror upptäcker.
App Store ConnectDess notifieringsbody eller headern x-apple-signatureNotifieringar från App Store Connect.

Bygg vidare