وبهوک وضعیت پیام
بهجای پرسش مداوم از GET /sms/messages، آدرسی از سرور خودتان ثبت کنید تا هر تغییر وضعیت پیام به آن اعلام شود. وبهوک را در پنل ← وبسرویس تعریف میکنید.
رویدادها
| message.sent | پیام به اپراتور تحویل داده شد (هزینه قطعی شد). |
| message.delivered | گزارش تحویل به گیرنده رسید. |
| message.failed | ارسال یا تحویل ناموفق بود؛ هزینه به اعتبار شما بازگشت. |
| webhook.test | رویداد آزمایشی دکمه «آزمایش» در پنل. |
پیامهای آزمایشی (Sandbox) وبهوک نمیفرستند.
ساختار درخواست
یک POST با بدنه JSON و این هدرها:
X-Irnoti-Event— نوع رویدادX-Irnoti-Delivery— شناسه یکتای این ارسال (برای جلوگیری از پردازش تکراری)X-Irnoti-Signature— امضا، به شکلt=<زمان>,v1=<hex>
{
"id": "4821",
"event": "message.delivered",
"createdAt": "2026-10-07T10:20:03.000Z",
"data": {
"messageId": "5521",
"to": "09121234567",
"status": "delivered",
"parts": 1,
"totalPrice": "980",
"error": null,
"sentAt": "2026-10-07T10:20:01.000Z",
"deliveredAt": "2026-10-07T10:20:03.000Z"
}
}با هر پاسخ ۲xx ارسال موفق ثبت میشود؛ بدنه پاسخ خوانده نمیشود. مقادیر مبلغ رشته و به ریال هستند.
تأیید امضا
امضا HMAC-SHA256 روی رشته "<t>.<بدنه خام>" با «کلید امضا» (whsec_…) است. حتما بدنه خام (پیش از JSON parse) را امضا کنید، با مقایسه ثابتزمان تطبیق دهید و درخواستهایی با t قدیمیتر از ۵ دقیقه را رد کنید.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
// Keep the RAW body: the signature covers the exact bytes we sent.
app.post('/irnoti-hook', express.raw({ type: 'application/json' }), (req, res) => {
const header = req.get('x-irnoti-signature') ?? '';
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header);
if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return res.sendStatus(400);
const expected = crypto.createHmac('sha256', process.env.IRNOTI_WEBHOOK_SECRET)
.update(`${m[1]}.${req.body.toString('utf8')}`).digest();
if (!crypto.timingSafeEqual(expected, Buffer.from(m[2], 'hex'))) return res.sendStatus(400);
const event = JSON.parse(req.body.toString('utf8'));
// ...handle event.event / event.data (dedupe on event.id) ...
res.sendStatus(200);
});تلاش مجدد و محدودیتها
- در صورت پاسخ غیر ۲xx یا قطع اتصال، ارسال با فاصلههای ۱ دقیقه، ۵ دقیقه، ۳۰ دقیقه، ۲ ساعت و ۶ ساعت تکرار میشود (در مجموع ۶ تلاش).
- مهلت پاسخ ۸ ثانیه است؛ سریع پاسخ ۲۰۰ بدهید و کار سنگین را بعدا انجام دهید.
- ترتیب رویدادها تضمین نمیشود و ممکن است یک رویداد دوبار برسد؛ با
X-Irnoti-Deliveryتکراریها را نادیده بگیرید. - آدرس باید
httpsو عمومی باشد؛ آدرسهای شبکه داخلی و ریدایرکت پذیرفته نمیشود. - پس از ۲۰ ارسال ناموفق پیاپی، وبهوک غیرفعال میشود و از پنل میتوانید دوباره فعالش کنید.