עונים לי במזכירה

בלוח הבקרה, ב«חיבורים», מדביקים כתובת: Make, Zapier, n8n או כל שרת. הסוד מוצג פעם אחת.

  • כתובת: https בלבד. כל 2xx נחשב התקבל.
  • ניסיונות חוזרים: אחרי דקה, 5 דקות, 30 דקות, שעתיים, 6 ו-24 שעות.
  • זמן תשובה: 10 שניות. יומן המשלוחים נשמר 7 ימים.
  • בלי מסלול פעיל אירוע לא נשלח, והוא גם לא נשמר לשליחה מאוחרת.
אירועמתי
call.completedשיחה נגמרה, עם סיכום ותמלול
appointment.bookedנקבע תור
appointment.rescheduledתור הוזז
appointment.cancelledתור בוטל
appointment.confirmedהלקוח אישר הגעה
pingבדיקה מלוח הבקרה
כותרתמה יש בה
X-Onimli-Eventשם האירוע
X-Onimli-Deliveryמזהה משלוח, קבוע בכל הניסיונות. לפיו מסננים כפילויות
X-Onimli-Signaturet=…,v1=…
{"id": "evt_…", "event": "call.completed", "created_at": "2026-11-03T09:12:40+02:00",
 "agent": {"id": 12, "name": "נועה"},
 "call": {"id": 991, "started_at": "2026-11-03T09:10:17+02:00", "seconds": 143,
          "caller": {"phone": "+972501234567", "name": "שירה"},
          "summary": "קבעה בדיקה כללית לשלישי 3.11 ב-10:00",
          "next_action": null, "outcome": "booked",
          "transcript": [{"who": "caller", "text": "…"}, {"who": "agent", "text": "…"}]},
 "appointment": {"id": 55, "service_name": "בדיקה כללית",
                 "starts_at": "2026-11-03T10:00:00+02:00", "ends_at": "2026-11-03T10:30:00+02:00",
                 "caller_phone": "+972501234567", "caller_name": "שירה",
                 "status": "booked", "source": "call", "call_id": 991}}
  • outcome, אחד מאלה: booked · rescheduled · cancelled · message.
  • או: transfer · info · hangup.
  • אירועי appointment.* נושאים appointment ו-agent, בלי call.

אימות חתימה

X-Onimli-Signature: t={unix},v1={hex}
v1 = hex(HMAC_SHA256(secret, "{t}.{raw body}"))

בודקים על הגוף הגולמי, לפני פענוח ה-JSON, ודוחים t ישן מ-5 דקות.

import hashlib, hmac, time

def verify(secret: str, header: str, body: bytes) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > 300:
        return False
    want = hmac.new(secret.encode(), f"{parts['t']}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(want, parts["v1"])
import crypto from "node:crypto";

export function verify(secret, header, rawBody) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const want = crypto.createHmac("sha256", secret)
    .update(`${parts.t}.`).update(rawBody).digest("hex");
  return want.length === parts.v1.length &&
    crypto.timingSafeEqual(Buffer.from(want), Buffer.from(parts.v1));
}