Webhooks
Draft
Structural skeleton — content authored separately.
Webhooks push realtime events — inbound SMS, delivery receipts and device status — to an HTTPS endpoint you control. Every delivery is signed and retried.
Example
- Node.js
- Python
- Java
- Kotlin
- PHP
- Go
- C#
import express from 'express';
import { Msgly } from '@msgly/sdk';
const app = express();
const msgly = new Msgly({ apiKey: process.env.MSGLY_API_KEY });
app.post('/webhooks/msgly', express.raw({ type: '*/*' }), (req, res) => {
const event = msgly.webhooks.verify(
req.body,
req.header('X-Msgly-Signature'),
process.env.MSGLY_WEBHOOK_SECRET,
);
if (event.type === 'message.received') {
console.log('Inbound SMS from', event.data.from, ':', event.data.text);
}
res.sendStatus(200);
});
app.listen(3000);
import os
from flask import Flask, request
from msgly import Msgly
app = Flask(__name__)
client = Msgly(api_key=os.environ["MSGLY_API_KEY"])
@app.post("/webhooks/msgly")
def handle():
event = client.webhooks.verify(
request.data,
request.headers.get("X-Msgly-Signature"),
os.environ["MSGLY_WEBHOOK_SECRET"],
)
if event.type == "message.received":
print("Inbound SMS from", event.data.sender, ":", event.data.text)
return "", 200
@PostMapping("/webhooks/msgly")
public ResponseEntity<Void> handle(
@RequestBody byte[] payload,
@RequestHeader("X-Msgly-Signature") String signature) {
MsglyEvent event = Msgly.webhooks().verify(
payload, signature, System.getenv("MSGLY_WEBHOOK_SECRET"));
if ("message.received".equals(event.type())) {
log.info("Inbound SMS from {}: {}", event.data().from(), event.data().text());
}
return ResponseEntity.ok().build();
}
post("/webhooks/msgly") {
val payload = call.receiveText()
val signature = call.request.header("X-Msgly-Signature")
val event = Msgly.webhooks.verify(
payload,
signature,
System.getenv("MSGLY_WEBHOOK_SECRET"),
)
if (event.type == "message.received") {
println("Inbound SMS from ${event.data.from}: ${event.data.text}")
}
call.respond(HttpStatusCode.OK)
}
<?php
use Msgly\Webhook;
$event = Webhook::verify(
file_get_contents('php://input'),
$_SERVER['HTTP_X_MSGLY_SIGNATURE'] ?? '',
getenv('MSGLY_WEBHOOK_SECRET'),
);
if ($event->type === 'message.received') {
error_log("Inbound SMS from {$event->data->from}: {$event->data->text}");
}
http_response_code(200);
package main
import (
"io"
"log"
"net/http"
"os"
"gitlab.com/msgly/msgly-go"
)
func handler(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
event, err := msgly.VerifyWebhook(
body,
r.Header.Get("X-Msgly-Signature"),
os.Getenv("MSGLY_WEBHOOK_SECRET"),
)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
if event.Type == "message.received" {
log.Printf("Inbound SMS from %s: %s", event.Data.From, event.Data.Text)
}
w.WriteHeader(http.StatusOK)
}
app.MapPost("/webhooks/msgly", async (HttpRequest req) =>
{
using var reader = new StreamReader(req.Body);
var payload = await reader.ReadToEndAsync();
var evt = MsglyWebhook.Verify(
payload,
req.Headers["X-Msgly-Signature"],
Environment.GetEnvironmentVariable("MSGLY_WEBHOOK_SECRET"));
if (evt.Type == "message.received")
Console.WriteLine($"Inbound SMS from {evt.Data.From}: {evt.Data.Text}");
return Results.Ok();
});