<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;600;700&display=swap" />

אינטגרציית קופה

Webhooks יוצאים על כל אירוע הזמנה, ו-REST API נכנס לקופות, למדפסות ולאוטומציות.

מדריך למפתחים. עודכן לאחרונה: 10.11.2026.

סקירה

האינטגרציה דו-כיוונית. eato שולחת Webhook חתום לכתובת שלכם בכל אירוע הזמנה, והמערכת שלכם מחזירה סטטוסים, יוצרת הזמנות טלפוניות ומעדכנת זמינות דרך ה-API. מתאים לקופות כמו Restigo, Tabit ו-ResApp, ולכל קופה שיודעת לקבל הזמנות ולהחזיר סטטוס.

כל הנתיבים יושבים תחת כתובת בסיס אחת:

https://eato.co.il/api/v1/merchant

  • Restigo
  • Tabit
  • ResApp
  • Make
  • Zapier
  • n8n
  • Pipedream
  • Slack
  • Telegram

אין סביבת Sandbox ציבורית. אפשר לבקש חשבון בדיקה עם תפריט לדוגמה.

אימות

כל קריאה ל-/api/v1/merchant/* נושאת מפתח Bearer בכותרת Authorization. המפתח בנוי כך: eak_live_<12 hex>_<32 base62>. הוא מוצג פעם אחת בלבד בזמן היצירה, ונשמר אצלנו כגיבוב בלבד, כך שגם אנחנו לא יכולים לשחזר אותו.

יוצרים ומבטלים מפתחות בלוח הבקרה, תחת הגדרות ומפתחים. אפשר להחזיק כמה מפתחות פעילים במקביל, והביטול מיידי.

Authorization header
GET /api/v1/merchant/orders?status=preparing HTTP/1.1
Host: eato.co.il
Authorization: Bearer eak_live_a1b2c3d4e5f6_<32-char-secret>
Accept: application/json

שרת לשרת בלבד. ה-API לא פתוח ל-CORS מדפדפן, ומפתח לא נכנס לאפליקציה או לקוד לקוח.

שגיאות

כל שגיאה חוזרת במבנה אחיד. השדה field מופיע רק בשגיאות אימות של הגוף.

Error body
{
  "error": {
    "code": "validation_error",
    "message": "quantity must be at least 1",
    "field": "lines[0].quantity"
  }
}
קודי שגיאה
HTTPקודמשמעות
401unauthorized מפתח חסר, שגוי או שבוטל
403forbidden למפתח אין הרשאה לפעולה, למשל החזר בלי הרשאת בעלים או מנהל
404not_found המשאב לא קיים
409conflict התנגשות עסקית, למשל החזר כפול או אותו Idempotency-Key עם גוף אחר
409invalid_transition מעבר סטטוס לא מותר
422validation_error הגוף לא עומד בסכמה. כולל field
429rate_limited חריגה מהמגבלה. כולל Retry-After
500internal_error תקלה בצד שלנו. אם זה חוזר, דווחו עם השעה והנתיב

Webhooks

אנחנו שולחים POST עם גוף JSON לכתובת שרשמתם, ומצפים לתשובת 2xx תוך 8 שניות. כל תוצאה אחרת מפעילה ניסיון חוזר. רושמים כתובת בלוח הבקרה או דרך ה-API, ולכל כתובת יש כפתור בדיקה ששולח אירוע order.created חתום לדוגמה.

כותרות

כותרות Webhook
כותרתתפקיד
Content-Typeapplication/json
X-Eato-Signature חתימת HMAC במבנה t=<unix>,v1=<hex>
X-Eato-Event סוג האירוע, למשל order.created
X-Eato-Delivery מזהה המשלוח. קבוע לאורך כל הניסיונות החוזרים, ומשמש למניעת כפילויות
User-Agenteato-webhooks/1.0

מעטפת

Webhook envelope
{
  "id": "7b1c2f6e-3d4a-4c1b-9f20-5a6b7c8d9e0f",
  "event": "order.created",
  "created_at": "2026-11-10T19:30:45.123Z",
  "tenant_id": "napoli",
  "data": {
    "order_id": "9d2e4b1a-6c3f-4e8d-a1b2-c3d4e5f60718",
    "number": 1247,
    "status": "confirmed",
    "total": 12700,
    "method": "delivery",
    "channel": "web",
    "payment_method": "card",
    "customer": { "name": "Dana", "phone": "+972541234567" },
    "items": [
      {
        "item_id": "marg",
        "name": "Margherita",
        "quantity": 1,
        "total": 5800,
        "size": "family",
        "modifiers": ["Right half: mushrooms"],
        "note": null
      }
    ],
    "created_at": "2026-11-10T19:30:41.002Z"
  }
}

אירועים

אירועי Webhook
אירועמתי נשלחשדות ב-data
order.created ההזמנה אושרה: מיד במזומן, אחרי אישור תשלום בכרטיס order_id, number, total, method, items[]
order.status_changed כל מעבר סטטוס, חוץ מביטול והחזר order_id, from, to, changed_at, courier_id
order.cancelled ההזמנה בוטלה order_id, number, reason, cancelled_at
order.refunded ההזמנה סומנה כהחזר order_id, number, amount, payment_method, reason
order.ready_for_print מתוכנן, עדיין לא נשלח טרם הוגדר

ניסיונות חוזרים

לוח ניסיונות חוזרים
ניסיוןמתי
1 מיד
2 דקה אחרי הכישלון
3 5 דקות אחרי
4 15 דקות אחרי
5 שעה אחרי
6 6 שעות אחרי

שישה ניסיונות לאורך כ-7.4 שעות. אחרי הכישלון השישי המשלוח מסומן abandoned. הוא נשאר בלוח הבקרה עם היסטוריה מלאה וכפתור Retry ידני.

אימות חתימה

הכותרת X-Eato-Signature בנויה כך: t=<unix>,v1=<hex>. הערך v1 הוא HMAC-SHA256 על t.raw_body עם הסוד של הכתובת. מאמתים מול הגוף הגולמי לפני פענוח ה-JSON, עם חלון של 5 דקות נגד שידור חוזר, ובהשוואה בזמן קבוע. חתימה לא תקינה מקבלת 401 ולא מעובדת.

אימות חתימה, Node
const crypto = require("node:crypto");

function verifyEato(rawBody, header, secret) {
  if (!header) return false;
  const parts = Object.fromEntries(
    header.split(",").map((p) => {
      const i = p.indexOf("=");
      return [p.slice(0, i).trim(), p.slice(i + 1).trim()];
    })
  );
  const t = Number(parts.t);
  if (!Number.isInteger(t) || !parts.v1) return false;
  if (Math.abs(Date.now() / 1000 - t) > 300) return false; // 5 minute window

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody}`, "utf8")
    .digest("hex");
  const a = Buffer.from(expected, "utf8");
  const b = Buffer.from(parts.v1, "utf8");
  if (a.length !== b.length) return false; // timingSafeEqual throws on different lengths
  return crypto.timingSafeEqual(a, b);
}

// Express: keep the raw body, verify before JSON.parse
app.post("/eato/webhook", express.raw({ type: "application/json" }), (req, res) => {
  const raw = req.body.toString("utf8");
  if (!verifyEato(raw, req.get("X-Eato-Signature"), process.env.EATO_WEBHOOK_SECRET)) {
    return res.status(401).end();
  }
  const delivery = req.get("X-Eato-Delivery"); // dedupe on this id
  queue.push({ delivery, event: JSON.parse(raw) }); // process async
  res.status(200).end(); // answer within 8 seconds
});

Orders API

נתיבי הזמנות
Methodנתיבמה עושהפרמטרים
GET/orders רשימת הזמנות status, page, per_page (30, max 100)
GET/orders/{id} הזמנה מלאה עם לקוח, פריטים, אפשרויות וסכומים
PATCH/orders/{id}/status עדכון סטטוס. ביטול מחייב reason status, courier_id, reason
POST/orders/{id}/refund סימון החזר (בעלים או מנהל) reason (max 500)
POST/orders/manual הזמנה טלפונית או בדלפק customer_phone, method, payment_method, lines[]
POST/webhooks/endpoints רישום כתובת Webhook url, events[], active

הזמנה ידנית (טלפון או דלפק)

טלפון בפורמט ישראלי מומר ל-E.164. בלי payment_method ההזמנה נרשמת כמזומן.

POST /orders/manual
curl -X POST https://eato.co.il/api/v1/merchant/orders/manual \
  -H "Authorization: Bearer $EATO_API_KEY" \
  -H "Idempotency-Key: 2f1e7c1a-8b9d-4e2f-a3c4-d5e6f7a8b9c0" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_phone": "054-1234567",
    "customer_name": "Dana",
    "method": "pickup",
    "payment_method": "cash",
    "notes": "no onion",
    "lines": [
      { "item_id": "marg", "quantity": 1, "size_id": "family", "option_ids": [] }
    ]
  }'
תשובה
HTTP/1.1 201 Created
Content-Type: application/json

{
  "order": {
    "id": "5c7d9e1f-2a3b-4c5d-8e9f-0a1b2c3d4e5f",
    "number": 1248,
    "status": "pending",
    "total": 5800,
    "eta_at": "2026-11-10T19:52:00.000Z"
  }
}

החזר

בהחזר בכרטיס, הכסף עצמו מוחזר ידנית בממשק של ספק הסליקה. הקריאה רושמת את הכוונה ומחזירה money_action_required. החזר דורש מפתח של בעלים או מנהל.

POST /orders/{id}/refund, תשובה
{
  "refund": {
    "amount": 5800,
    "reason": "customer cancelled",
    "money_action_required": true,
    "message": "Refund the card in the payment provider panel"
  },
  "money_action_required": true
}

מעברי סטטוס

מעברי סטטוס מותרים
מסטטוסלסטטוס
pendingconfirmed, preparing, cancelled
confirmedpreparing, cancelled
preparingin_oven, ready, cancelled
in_ovenready, cancelled
readyout_for_delivery, delivered, cancelled
out_for_deliverydelivered, cancelled
deliveredrefunded
cancelledrefunded

מעבר לא חוקי מחזיר 409 invalid_transition. החזר עובר רק דרך POST /orders/{id}/refund. כל PATCH שולח גם Webhook לכל המנויים, כולל למי ששלח אותו, ולכן צריך מנגנון נגד לולאות.

Idempotency

שולחים כותרת Idempotency-Key עם UUID לכל פעולה לוגית. אותו מפתח עם אותו גוף מחזיר את התשובה המקורית עם X-Eato-Idempotent-Replay: true. אותו מפתח עם גוף אחר מחזיר 409 conflict. מפתחות פגים אחרי 24 שעות.

נתמך כרגע ב-POST /orders/manual. תמיכה בעדכון סטטוס ובהחזר מתוכננת.

מגבלת קריאות

600 קריאות בדקה לכל מפתח, בערך 10 בשנייה. חריגה מחזירה 429 עם Retry-After. מי שמתקרב למגבלה בדרך כלל נמצא בלולאה לא מסונכרנת, ועדיף לעבור ל-Webhooks במקום לשאול שוב ושוב.

כותרות מגבלת קריאות
כותרת בתשובהערך
X-RateLimit-Limit600
X-RateLimit-Remaining כמה קריאות נשארו בדקה הנוכחית
X-RateLimit-Reset מתי המונה מתאפס
Retry-After בתשובת 429 בלבד: כמה שניות לחכות

CORS, IP ותעבורה

HTTPS בלבד. כתובת Webhook בלי HTTPS, או כתובת פנימית, נדחית ברישום. ל-Webhooks היוצאים אין כתובת IP קבועה. מי שצריך רשימת IP מורשים פונה לתמיכה לקבלת פרוקסי ייעודי. עיבוד כבד כדאי להעביר לתור, כי המתנה לתשובה מוגבלת ל-8 שניות.

מוסכמות

מוסכמות נתונים
נושאמוסכמה
כסף מספר שלם באגורות. ₪10.50 = 1050. המטבע תמיד שקל ולא נשלח כשדה
זמן ISO-8601 ב-UTC עם אלפיות שנייה
טלפון E.164, למשל +972541234567. פורמט ישראלי מקומי מומר אוטומטית
טקסט UTF-8, כולל עברית
זמינות available_from ו-available_to בדקות מחצות (660 = 11:00), available_days מסכת 7 ביטים (127 = כל הימים)
מספר הזמנה number הוא מספר רץ לכל מסעדה, מ-1001. המזהה הייחודי הוא order_id

רשימת בדיקה לפני עלייה לאוויר

רשימת בדיקה לפני עלייה לאוויר

סומנו 0 מתוך 8.

שאלות ותמיכה

אין Sandbox ציבורי. לפי בקשה פותחים חשבון בדיקה עם תפריט לדוגמה.

נתקעתם? כתבו ל-[למילוי: מייל מפתחים] עם מזהה המשלוח מהכותרת X-Eato-Delivery, או דרך צור קשר.

מחברים קופה? מתחילים בחשבון ניסיון.

7 ימי ניסיון בלי כרטיס אשראי. יוצרים מפתח API בלוח הבקרה ומחברים את הקופה באותו יום.