Webhooks
Webhooks allow TeamMessage to communicate with your systems via HTTP callbacks. Use them for message delivery, status notifications, or to forward messages to external services.
Overview
TeamMessage supports three types of webhooks:
- Webhook as Delivery Channel – Forward messages from a team list to your server
- Delivery Reports – Receive notifications when SMS are delivered or fail
- Incoming SMS – Forward received SMS to your server (sms2mail exklusiv)
Webhook as Delivery Channel
Add a webhook URL as a team member to forward all messages sent to the team list to your server. This is useful for integrating TeamMessage with ticketing systems, chat platforms, or custom applications.
Configuration
- Go to your team list → Members
- Click 'Add Member'
- Select channel: Webhook
- Enter your webhook URL (must start with https://)
Request Format
When a message is sent to the team list, TeamMessage sends a POST request with JSON:
Example request
POST /your-webhook-endpoint HTTP/1.1
Host: your-server.example.com
Content-Type: application/json; charset=UTF-8
{
"from": "+491711234567",
"message": "This is the message text",
"teamlist_id": 123,
"teamlist_email": "alerts@tmsg.de",
"recipient_name": "My Webhook",
"timestamp": 1736694000
}
Parameters
| Parameter | Type | Description |
|---|---|---|
from |
string | Sender identifier (phone number or alias) |
message |
string | The message text (UTF-8 encoded) |
teamlist_id |
integer | Internal ID of the team list |
teamlist_email |
string | Email address of the team list |
recipient_name |
string | Name of the webhook member |
timestamp |
integer | Unix timestamp (seconds since 1970-01-01) |
Expected Response
Your endpoint should return an HTTP 2xx status code (200, 201, 204) to indicate success:
Success response
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "received"}
Note
The response body is not evaluated. Only the HTTP status code matters. Timeout is 10 seconds.
Use Cases
- Forward alerts to Slack, Microsoft Teams, or Discord
- Create tickets in Jira, Zendesk, or other ticketing systems
- Log messages to a database or monitoring system
- Trigger automated workflows (Zapier, n8n, Make)
Delivery Reports
Delivery report webhooks notify you about the final status of sent SMS messages.
Configuration
Configure a webhook URL in your team list settings:
- Go to Team List Settings
- Enter your webhook URL in the 'Delivery Report URL' field
- The URL must be a valid HTTP or HTTPS endpoint
Tip
Use HTTPS for secure transmission. Your webhook endpoint should respond within 10 seconds.
Request Format
TeamMessage sends a POST request with form-encoded data:
Example request
POST /your-webhook-endpoint HTTP/1.1
Host: your-server.example.com
Content-Type: application/x-www-form-urlencoded
status=0&reason=0&to=004917012345678&msgid=123456×tamp=2025-01-08T14:30:00Z
Parameters
| Parameter | Description | Example |
|---|---|---|
status |
Delivery status code (0 = delivered) | 0 |
reason |
Reason code providing additional detail | 0 |
to |
Recipient phone number | 004917012345678 |
msgid |
Unique message identifier | 123456 |
timestamp |
Time of delivery or failure (ISO 8601) | 2025-01-08T14:30:00Z |
See Status Codes for a complete list of status and reason codes.
Retry Behavior
If your endpoint doesn't respond with HTTP 200:
- TeamMessage retries after 5 minutes
- Up to 3 retry attempts
- After all retries fail, the notification is discarded
Incoming SMS Webhooks
With sms2mail exklusiv, incoming SMS messages can be forwarded to a webhook URL instead of email.
Request Format
Incoming SMS webhook
POST /your-webhook-endpoint HTTP/1.1
Host: your-server.example.com
Content-Type: application/json
{
"from": "+491711234567",
"to": "+491512345678",
"message": "The SMS text content",
"timestamp": "2025-01-08T14:30:00Z"
}
Parameters
| Parameter | Description |
|---|---|
from |
Sender's phone number (E.164 format) |
to |
Your dedicated phone number |
message |
The SMS text content |
timestamp |
When the SMS was received (ISO 8601) |
Implementation Examples
Python (Flask)
from flask import Flask, request, jsonify
app = Flask(__name__)
# Webhook as delivery channel
@app.route('/webhook/message', methods=['POST'])
def message_webhook():
data = request.get_json()
print(f"Message from {data['from']}: {data['message']}")
print(f"Team list: {data['teamlist_email']}")
# Process the message (create ticket, forward to Slack, etc.)
# ...
return jsonify({"status": "received"}), 200
# Delivery report webhook
@app.route('/webhook/delivery', methods=['POST'])
def delivery_webhook():
status = request.form.get('status')
reason = request.form.get('reason')
to = request.form.get('to')
msgid = request.form.get('msgid')
if status == '0':
print(f"Message {msgid} delivered to {to}")
else:
print(f"Message {msgid} failed: status={status}, reason={reason}")
return 'OK', 200
PHP
<?php
// webhook_message.php - Webhook as delivery channel
$data = json_decode(file_get_contents('php://input'), true);
$from = $data['from'] ?? '';
$message = $data['message'] ?? '';
$account = $data['teamlist_email'] ?? '';
error_log("Message from {$from} to {$account}: {$message}");
// Process the message
// ...
http_response_code(200);
echo json_encode(['status' => 'received']);
// ---
// webhook_delivery.php - Delivery reports
$status = $_POST['status'] ?? '';
$reason = $_POST['reason'] ?? '';
$to = $_POST['to'] ?? '';
$msgid = $_POST['msgid'] ?? '';
if ($status === '0') {
error_log("Message {$msgid} delivered to {$to}");
} else {
error_log("Message {$msgid} failed: status={$status}, reason={$reason}");
}
http_response_code(200);
echo "OK";
Node.js (Express)
const express = require('express');
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// Webhook as delivery channel
app.post('/webhook/message', (req, res) => {
const { from, message, teamlist_email, timestamp } = req.body;
console.log(`Message from ${from}: ${message}`);
console.log(`Team list: ${teamlist_email}`);
// Process the message
// ...
res.status(200).json({ status: 'received' });
});
// Delivery report webhook
app.post('/webhook/delivery', (req, res) => {
const { status, reason, to, msgid } = req.body;
if (status === '0') {
console.log(`Message ${msgid} delivered to ${to}`);
} else {
console.log(`Message ${msgid} failed: status=${status}, reason=${reason}`);
}
res.send('OK');
});
app.listen(3000);
Testing Webhooks
Before going live, test your webhook implementation:
- Use a test tool like webhook.site or ngrok to inspect incoming requests
- Add the test URL as a webhook member in your team list
- Send a test message to the team list
- Verify the request appears on webhook.site with correct JSON payload
Tip
During development, use ngrok or a similar tool to expose your local server to the internet for testing webhooks.
Security Considerations
- Use HTTPS to encrypt webhook data in transit
- Add a secret token to your webhook URL for validation (z.B.
https://example.com/webhook?token=secret123) - Process webhooks asynchronously to avoid timeout issues
- Log all webhook requests for debugging and auditing
- Implement idempotency – handle duplicate notifications gracefully
Note
Webhook URLs are called from TeamMessage servers. If you have firewall restrictions, contact support for our IP ranges.