Webhooks
Notificaciones en tiempo real para mensajes SMS, WhatsApp y Email entrantes.
Descripciรณn general
RCSZilla puede enviar solicitudes HTTP POST a tu servidor cuando ocurran eventos especรญficos. Esto te permite crear integraciones en tiempo real sin polling.
| Campo | Descripciรณn | Configured in |
|---|---|---|
incoming_sms | A new SMS message was received by your Android device. | Devices → Control → Webhooks tab |
incoming_whatsapp | A new WhatsApp message was received by your Android device. | Devices → Control → Webhooks tab |
incoming_email | A new email arrived in an IMAP inbox linked to your SMTP server. | Email Servers → Edit → Incoming Email (IMAP) section |
test | A test event sent manually from the UI. | Same as above |
Configuraciรณn
Incoming SMS / WhatsApp Webhook
- Go to Devices and click the control icon for your device.
- Open the Webhooks tab.
- Enter your endpoint URL (must accept POST, return 2xx within 10 seconds).
- Optionally set a Webhook Secret for HMAC signature verification.
- Click Save, then Send Test Webhook to verify.
Incoming Email Webhook
- Go to Email Servers and edit (or add) a server.
- Expand the Incoming Email (IMAP) section.
- Enable IMAP polling and fill in the IMAP host, port, encryption, and credentials.
- Enter a webhook URL and optional secret.
- Save. A cron job checks for new emails every 2 minutes.
Formato de solicitud
Encabezados
| Header | Descripciรณn |
|---|---|
Content-Type | application/json |
User-Agent | RCSZilla-Webhook/1.0 |
X-RCSZilla-Event | Event type: incoming_sms, incoming_whatsapp, incoming_email, or test |
X-RCSZilla-Delivery | Unique delivery ID (use for deduplication) |
X-RCSZilla-Signature | sha256=<hex-hmac> — only present if you set a webhook secret. The HMAC is computed over the raw JSON body using SHA-256. |
incoming_sms / incoming_whatsapp
Fired when the Android app calls submit_reply with a new message.
{
"event": "incoming_sms",
"timestamp": "2026-05-27T14:30:00Z",
"data": {
"id": 209,
"from": "+40712345678",
"message": "Yes, I want to book an appointment",
"channel": "sms",
"device_id": 6,
"contact": {
"id": 42,
"name": "John Doe",
"phone": "+40712345678"
},
"auto_reply": "Thanks! We will get back to you shortly."
}
}
Campo
| Campo | Tipo | Descripciรณn |
|---|---|---|
event | string | incoming_sms or incoming_whatsapp |
timestamp | string | ISO 8601 UTC timestamp |
data.id | int | ID of the stored incoming message |
data.from | string | Sender phone number |
data.message | string | Message text |
data.channel | string | sms or whatsapp |
data.device_id | int | Device that received the message |
data.contact | object|null | Matched contact (id, name, phone) or null if unknown sender |
data.auto_reply | string|null | Auto-reply text sent back, or null if no rule matched |
incoming_email
Fired when the IMAP cron finds a new email in the configured mailbox.
{
"event": "incoming_email",
"timestamp": "2026-05-27T14:30:00Z",
"data": {
"id": 310,
"from_email": "customer@example.com",
"from_name": "John Doe",
"to_email": "support@yourbusiness.com",
"subject": "Re: Your order #1234",
"body_text": "Hi, when will my order arrive?",
"received_at": "2026-05-27T14:28:00Z",
"smtp_server_id": 5
}
}
Campo
| Campo | Tipo | Descripciรณn |
|---|---|---|
data.id | int | ID of the stored email |
data.from_email | string | Sender email address |
data.from_name | string | Sender display name |
data.to_email | string | Recipient (your mailbox) |
data.subject | string | Email subject line |
data.body_text | string | Plain-text body (first 2000 chars) |
data.received_at | string | Original receive timestamp |
data.smtp_server_id | int | Which SMTP/IMAP server received this |
Verificaciรณn de firmas
If you configure a webhook secret, each delivery includes an X-RCSZilla-Signature header. Verify it like this:
<?php
$payload = file_get_contents('php://input');
$secret = 'whsec_your_secret_here';
$header = $_SERVER['HTTP_X_RCSZILLA_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $header)) {
http_response_code(401);
exit('Invalid signature');
}
$data = json_decode($payload, true);
// Process the event...
http_response_code(200);
echo json_encode(['ok' => true]);
const crypto = require('crypto');
app.post('/webhook', (req, res) => {
const payload = JSON.stringify(req.body);
const secret = 'whsec_your_secret_here';
const sig = req.headers['x-rcszilla-signature'] || '';
const expected = 'sha256=' + crypto.createHmac('sha256', secret)
.update(payload).digest('hex');
if (sig !== expected) return res.status(401).send('Invalid signature');
const { event, data } = req.body;
console.log(`Received ${event}:`, data);
res.json({ ok: true });
});
import hmac, hashlib, json
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = 'whsec_your_secret_here'
@app.route('/webhook', methods=['POST'])
def webhook():
payload = request.get_data()
sig = request.headers.get('X-RCSZilla-Signature', '')
expected = 'sha256=' + hmac.new(
SECRET.encode(), payload, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(sig, expected):
abort(401)
data = json.loads(payload)
print(f"Event: {data['event']}", data['data'])
return {'ok': True}
Polรญtica de reintentos
If your endpoint returns a non-2xx status code, times out (10 seconds), or is unreachable, the delivery is retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry (final) | 12 hours |
Listar entregas de Webhook
Devuelve una lista paginada de entregas webhook para el usuario autenticado, con contadores de estado y filtrado opcional.
Parรกmetros de consulta
| Campo | Tipo | Descripciรณn | |
|---|---|---|---|
status | string | opcional | Filtrar por estado: pending, processing, sent o failed. |
event_type | string | opcional | Filtrar por tipo de evento: incoming_sms, incoming_whatsapp, incoming_email o test. |
limit | int | opcional | Resultados por pรกgina (1โ100). Por defecto: 20. |
offset | int | opcional | Desplazamiento de paginaciรณn. Por defecto: 0. |
Ejemplo de solicitud
curl "https://api.rcszilla.com/?endpoint=webhook_deliveries&status=pending&limit=10" \ -H "Authorization: Bearer YOUR-API-TOKEN"
Respuesta
{
"success": true,
"total": 42,
"limit": 10,
"offset": 0,
"counts": {
"pending": 3,
"sent": 38,
"failed": 1
},
"deliveries": [
{
"id": 156,
"event_type": "incoming_sms",
"webhook_url": "https://your-server.com/hook",
"status": "pending",
"attempts": 0,
"max_attempts": 5,
"http_status": null,
"last_error": null,
"next_retry_at": "2026-05-27T14:31:00Z",
"created_at": "2026-05-27T14:30:05",
"last_attempt_at": null
}
]
}
Contadores de estado
El objeto counts ofrece una vista rรกpida de todos los estados webhook sin paginar cada entrega. รsalo para widgets de panel o verificaciones de salud.
| Campo | Descripciรณn |
|---|---|
pending | En cola, esperando la prรณxima ejecuciรณn cron o ventana de reintento. |
processing | Siendo entregado por el worker cron. |
sent | Entregado con รฉxito (HTTP 2xx). Limpiado automรกticamente despuรฉs de 7 dรญas. |
failed | Todos los intentos de reintento agotados. Limpiado automรกticamente despuรฉs de 30 dรญas. |
Obtener entrega de Webhook
Devuelve una sola entrega webhook por ID, incluyendo el payload completo que fue (o serรก) enviado a tu endpoint.
Parรกmetros de consulta
| Campo | Tipo | Descripciรณn | |
|---|---|---|---|
id | int | obligatorio | El ID de entrega devuelto por webhook_deliveries. |
Ejemplo de solicitud
curl "https://api.rcszilla.com/?endpoint=webhook_delivery&id=156" \ -H "Authorization: Bearer YOUR-API-TOKEN"
Respuesta
{
"success": true,
"delivery": {
"id": 156,
"event_type": "incoming_sms",
"webhook_url": "https://your-server.com/hook",
"payload": {
"event": "incoming_sms",
"timestamp": "2026-05-27T14:30:00Z",
"data": {
"id": 209,
"from": "+40712345678",
"message": "Yes, I want to book",
"channel": "sms",
"device_id": 6,
"contact": {
"id": 42,
"name": "John Doe",
"phone": "+40712345678"
},
"auto_reply": null
}
},
"status": "sent",
"attempts": 1,
"max_attempts": 5,
"http_status": 200,
"last_error": null,
"next_retry_at": null,
"created_at": "2026-05-27T14:30:05",
"last_attempt_at": "2026-05-27T14:30:08"
}
}
webhook_deliveries?status=failed para monitorear endpoints rotos, o status=pending para verificar la profundidad de la cola. El campo counts en la respuesta de lista es ideal para paneles de monitoreo.n8n Integration
To receive webhooks in n8n:
- Add a Webhook node to your workflow and copy its URL.
- Paste that URL into the webhook URL field in {APP_NAME} (Devices → Webhooks or Email Servers → IMAP).
- Test to confirm n8n receives the event.
- Connect downstream nodes to process the data (e.g., send a Slack message, update a CRM, trigger a reply).
Configuraciรณn Cron
Add these cron jobs to your server:
# Fire pending webhooks (every minute) * * * * * /usr/bin/php /path/to/send_sms/cron/process_webhook_queue.php # Poll IMAP inboxes for new emails (every 2 minutes) */2 * * * * /usr/bin/php /path/to/send_sms/cron/process_incoming_emails.php