وبهوکها
وقتی در رشتا اتفاقی میافتد (مخاطب ساخته میشود، معامله برنده میشود، سفارش ثبت میشود) رشتا یک درخواست POST امضاشده به نشانی شما میفرستد. لازم نیست مدام API را بپرسید.
- فقط نشانی HTTPS روی آدرس عمومی پذیرفته میشود؛ آدرس شبکهٔ داخلی رد میشود و ریدایرکت دنبال نمیشود.
- فقط رویدادهای بعد از ساختن وبهوک فرستاده میشوند.
- رکوردهایی که از ورود فایل یا دادهٔ نمونه میآیند رویداد وبهوک نمیفرستند.
کاتالوگ رویدادها
۱۸ رویدادنام هر رویداد «موضوع.فعل» است. بدنه فقط شناسهها را دارد (و در ویرایش، نام فیلدهای تغییرکرده)؛ برای جزئیات، رکورد را با API بخوانید.
POST https://example.com/reshta/webhookContent-Type: application/jsonUser-Agent: Reshta-Webhooks/1Reshta-Event: deal.wonReshta-Delivery: 0192c5a1-3a5b-7c6d-8e7f-90a1b2c3d4e5Reshta-Signature: t=1793022003,v1=b5230efdbd5ecead2c10e5373c02395791808788f66ebe612cd0bf9557a6bfc6{ "id": "0192c5a1-2f4e-7a10-8b3c-1d2e3f405162", "type": "deal.won", "created_at": "2026-10-26T14:20:03.000Z", "data": { "deal_id": "0192c5a0-9e8d-7c6b-5a49-382716051f2e" }}همهٔ رویدادها همین قالب را دارند: id یکتای رویداد برای حذف تکراری، type، created_at و data. سرآیندهای Reshta-Event و Reshta-Delivery هم نام رویداد و شناسهٔ ارسال را دارند.
امضای نمونه با رمز whsec_example روی همین بدنه حساب شده است.
تأیید امضا
هر درخواست سرآیند Reshta-Signature دارد: t زمان ارسال (ثانیهٔ یونیکس) و v1 امضای HMAC-SHA256 با رمز امضای همان وبهوک.
Reshta-Signature: t=1793022003,v1=b5230efdbd5ecead2c10e5373c02395791808788f66ebe612cd0bf9557a6bfc6- ۱t و v1 را از سرآیند جدا کنید.
- ۲HMAC-SHA256 رشتهٔ «t، نقطه، بدنهٔ خام» را با رمز امضا حساب کنید (hex).
- ۳نتیجه را با v1 در زمان ثابت مقایسه کنید.
- ۴پیشنهاد ما: اگر t بیش از ۵ دقیقه با ساعت شما فاصله دارد، درخواست را رد کنید؛ t داخل رشتهٔ امضاشده است و قابل جعل نیست.
import crypto from "node:crypto";// rawBody: the request body exactly as received (a string or Buffer).export function verify(rawBody, header, secret) { const p = Object.fromEntries(header.split(",").map((kv) => kv.split("="))); const expected = crypto .createHmac("sha256", secret) .update(`${p.t}.${rawBody}`) .digest("hex"); const fresh = Math.abs(Date.now() / 1000 - Number(p.t)) < 300; const a = Buffer.from(expected), b = Buffer.from(p.v1 ?? ""); return fresh && a.length === b.length && crypto.timingSafeEqual(a, b);}تلاش دوباره و تاریخچهٔ ارسال
اگر نشانی شما پاسخ 2xx ندهد، رشتا همان رویداد را با فاصلههای زیر دوباره میفرستد؛ روی هم حدود ۲۴ ساعت.
- ۱ارسال اولفوری
- ۲۱ دقیقهبعد
- ۳۵ دقیقهبعد
- ۴۳۰ دقیقهبعد
- ۵۲ ساعتبعد
- ۶۶ ساعتبعد
- ۷۱۵ ساعتبعد
- ✕ناموفقدر تاریخچه
تاریخچهٔ ارسال در اپ
| رویداد | وضعیت | تلاشها | آخرین پاسخ | زمان ایجاد | ارسال دوباره |
|---|---|---|---|---|---|
| deal.won | تحویل شد | ۱ از ۷ | 200 | امروز ۱۴:۲۰ | |
| order.created | تلاش دوباره | ۳ از ۷ | 503 | امروز ۱۴:۰۵ | |
| contact.created | ناموفق | ۷ از ۷ | 500 | دیروز ۰۹:۱۲ | ارسال دوباره |
| deal.stage_changed | تحویل شد | ۲ از ۷ | 200 | دیروز ۰۸:۴۰ | ارسال دوباره |
| form.submitted | در انتظار ارسال | ۰ از ۷ | — | امروز ۱۴:۲۱ |