E-Commerce API
ניהול קטלוג המוצרים שלך, מעקב אחר הזמנות, ניטור פעילות עגלות וניתוח פלחי לקוחות RFM.
כל נקודות הקצה בעמוד זה יחסיות לכתובת הבסיס: https://api-eu1.joryio.com/api - ראו סקירת API.
הרשאות
קריאת נתוני קטלוג, עגלות והזמנות דורשת analytics:read. יצירה או עדכון של מוצרים, עגלות והזמנות דורשת ecommerce:write. שתיהן ניתנות להענקה למפתח API תחת הגדרות → מפתחות API.
בעבר נתיבי הכתיבה דרשו integrations:write, שאינה מוצעת למפתחות API מכיוון שהיא שולטת גם ב־OAuth של מחברים ובהגדרות סנכרון המחסן. הם עדיין מקבלים אותה, כך שקוראים קיימים אינם מושפעים.
מוסכמת שמות מזהים
Joryio משתמש במוסכמת שמות ברורה למזהים:
המזהים שלך (השתמש בהם בעת יצירה/מעקב של נתונים)
| שדה | תיאור | דוגמה |
|---|---|---|
productId | מזהה המוצר שלך (מק"ט, מזהה מוצר מהפלטפורמה שלך) | "SKU-12345" |
orderId | מזהה ההזמנה שלך (מספר הזמנה מהפלטפורמה שלך) | "ORD-2024-001" |
userId | מזהה המשתמש שלך | "user-123" |
מזהי Joryio (מוחזרים בתגובות API)
| שדה | תיאור | מתי להשתמש |
|---|---|---|
id | המזהה הפנימי של Joryio למוצרים/הזמנות | מוחזר בתגובות API, השתמש לעדכונים/מחיקות |
joryioUserId | מזהה משתמש פנימי של Joryio (ה-id בן 24 התווים המוחזר בתגובות ה-API של משתמשים) | חלופה ל-userId כאשר רוצים להתייחס למזהה של Joryio |
זיהוי משתמשים גמיש
בעת יצירת הזמנות או מעקב אחר אירועים, ניתן לזהות משתמשים באמצעות אחד מהבאים:
userId- מזהה המשתמש שלך (הנפוץ ביותר)joryioUserId- מזהה משתמש פנימי של Joryio
// Using your user ID (recommended)
{ "orderId": "ORD-001", "userId": "user-123", ... }
// Using Joryio's internal user ID
{ "orderId": "ORD-001", "joryioUserId": "66a1f2c3d4e5f6a7b8c9d0e1", ... }
אימות
כל הבקשות דורשות אימות JWT:
Authorization: Bearer your_jwt_token
Content-Type: application/json
X-Workspace-Id: your_workspace_id
קטלוג מוצרים
יצירת מוצר
יצירת מוצר חדש בקטלוג.
POST /catalog/products
גוף הבקשה:
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
productId | string | כן | מזהה המוצר הייחודי שלך (מק"ט, מזהה מוצר) |
name | string | כן | שם המוצר |
price | number | כן | מחיר המוצר |
description | string | לא | תיאור המוצר |
compareAtPrice | number | לא | מחיר מקורי (להנחות) |
currency | string | לא | קוד מטבע (ברירת מחדל: USD) |
categories | string[] | לא | קטגוריות המוצר |
tags | string[] | לא | תגיות המוצר |
brand | string | לא | שם המותג |
imageUrl | string | לא | כתובת תמונה ראשית |
url | string | לא | כתובת דף המוצר |
inStock | boolean | לא | זמינות במלאי (ברירת מחדל: true) |
sku | string | לא | מק"ט |
variants | object[] | לא | וריאנטים של המוצר |
customFields | object | לא | שדות מותאמים אישית |
דוגמת בקשה:
curl -X POST https://api-eu1.joryio.com/api/catalog/products \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"productId": "SKU-12345",
"name": "Classic Blue T-Shirt",
"price": 29.99,
"compareAtPrice": 39.99,
"currency": "USD",
"categories": ["Clothing", "T-Shirts"],
"tags": ["sale", "bestseller"],
"brand": "Acme Apparel",
"imageUrl": "https://example.com/images/blue-tshirt.jpg",
"url": "https://example.com/products/blue-tshirt",
"inStock": true,
"sku": "BTS-001-BL",
"variants": [
{
"id": "var-s",
"name": "Small",
"sku": "BTS-001-BL-S",
"price": 29.99,
"inStock": true,
"options": { "size": "S", "color": "Blue" }
},
{
"id": "var-m",
"name": "Medium",
"sku": "BTS-001-BL-M",
"price": 29.99,
"inStock": true,
"options": { "size": "M", "color": "Blue" }
}
]
}'
תגובה:
{
"id": "prod_abc123",
"productId": "SKU-12345",
"name": "Classic Blue T-Shirt",
"price": 29.99,
"createdAt": "2024-01-20T10:00:00.000Z"
}
יצירה או עדכון של מוצרים בכמות גדולה (array body)
אין נקודת קצה נפרדת לפעולה באצווה: POST /catalog/products מקבל או אובייקט מוצר יחיד או מערך JSON חשוף של אובייקטי מוצר (ללא אובייקט עוטף). צורת המערך יוצרת או מעדכנת עד 500 מוצרים בבקשה אחת, לפי productId.
POST /catalog/products
גוף הבקשה:
מערך JSON (עד 500 איברים; מערך ריק או יותר מ־500 מחזיר 400). כל איבר באותו פורמט כמו הצורה של אובייקט בודד, כולל שדה source אופציונלי לכל מוצר.
כל איבר עובר תיקוף מלא. איבר לא תקין מדווח ב־failed לפי האינדקס שלו במערך - הוא לעולם אינו מתקבל ללא התראה - ושאר האיברים התקינים עדיין נכתבים.
[
{ "productId": "SKU-001", "name": "Product 1", "price": 19.99 },
{ "productId": "SKU-002", "name": "Product 2", "price": 29.99, "source": "shopify" }
]
תגובה:
בשונה מצורת האובייקט (שמחזירה את המוצר שנוצר), צורת המערך מחזירה סיכום מצרפי:
{
"processed": 2,
"upserted": 2,
"failed": []
}
| שדה | תיאור |
|---|---|
processed | מספר האיברים שהתקבלו במערך הבקשה |
upserted | מוצרים שנוצרו או עודכנו בפועל |
failed | כשלים לכל איבר: index (מיקום במערך הבקשה), productId / sku (כשקיימים על האיבר), reason |
רשימת מוצרים
שאילתת מוצרים עם סינון ודפדוף.
GET /catalog/products
פרמטרי שאילתה:
| פרמטר | סוג | תיאור |
|---|---|---|
search | string | חיפוש לפי שם, תיאור או מק"ט |
categories | string[] | סינון לפי קטגוריות |
tags | string[] | סינון לפי תגיות |
brand | string | סינון לפי מותג |
inStock | boolean | סינון לפי זמינות במלאי |
minPrice | number | מחיר מינימלי |
maxPrice | number | מחיר מקסימלי |
limit | number | תוצאות לעמוד (ברירת מחדל: 50) |
offset | number | היסט לדפדוף |
sortBy | string | שדה מיון: name, price, createdAt, updatedAt |
sortOrder | string | asc או desc |
דוגמה:
curl "https://api-eu1.joryio.com/api/catalog/products?categories=T-Shirts&inStock=true&limit=20" \
-H "Authorization: Bearer $TOKEN"
שדות שממלאות אינטגרציות חנות. תגובות מוצר כוללות גם שדות שחנות מחוברת (WooCommerce) ממלאת ושנתיבי היצירה והעדכון לא מקבלים: gtin (GTIN, UPC, EAN או ISBN, או null), attributes (שם מאפיין לערכים שלו, לדוגמה {"Material": ["Linen"]}, או null), variants[].gtin, ו-sourceModifiedAt (מתי החנות שינתה את המוצר לאחרונה). brand ו-description (טקסט רגיל) מתמלאים באותו אופן במוצרים מסונכרנים.
קבלת קטגוריות
רשימת כל קטגוריות המוצרים.
GET /catalog/categories
קבלת מותגים
רשימת כל מותגי המוצרים.
GET /catalog/brands
סטטיסטיקות קטלוג
סיכומים ותקינות הקטלוג, מחושבים על כל המוצרים - אף פעם לא על עמוד בודד.
GET /catalog/stats
תגובה:
{
"productCount": 8214,
"categoryCount": 37,
"brandCount": 12,
"outOfStockCount": 341,
"lowStockCount": 96,
"unclassifiedCount": 18,
"lowStockThreshold": 10
}
| שדה | תיאור |
|---|---|
outOfStockCount | מוצרים עם quantity 0, או inStock: false כשאין מעקב כמות |
lowStockCount | מוצרים עם quantity בין 1 ל-lowStockThreshold |
unclassifiedCount | מוצרים ללא קטגוריה או ללא מותג |
lowStockThreshold | סף היחידות שלפיו חושב lowStockCount |
הזמנות
יצירת הזמנה
מעקב אחר הזמנה חדשה.
POST /orders
גוף הבקשה:
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
orderId | string | כן | מזהה ההזמנה שלך (מספר הזמנה מהפלטפורמה שלך) |
userId | string | אחד מהשניים | מזהה המשתמש של הלקוח שלך |
joryioUserId | string | אחד מהשניים | מזהה משתמש פנימי של Joryio (חלופה ל-userId) |
total | number | כן | סכום ההזמנה הכולל |
items | object[] | כן | פריטים בהזמנה |
status | string | לא | סטטוס הזמנה (ברירת מחדל: pending) |
paymentStatus | string | לא | paid או unpaid: האם ההזמנה שולמה. הזמנת תשלום במזומן בעת המסירה או העברה בנקאית היא processing ו-unpaid עד שהכסף מגיע, ומוצגת בדף ההזמנות כממתין לתשלום במקום שולמה. בלעדיו, הזמנה בעיבוד / שנשלחה / שנמסרה נחשבת שולמה (הזמנה קיימת שומרת את הערך שיש לה). ההכנסות אינן תלויות בו. ראו שולמה או ממתינה לתשלום. |
currency | string | לא | קוד מטבע |
subtotal | number | לא | סכום ביניים לפני הנחות |
discount | number | לא | סכום הנחה |
shipping | number | לא | עלות משלוח |
tax | number | לא | סכום מס |
totalRefunded | number | לא | הסכום שהוחזר עד כה, במטבע ההזמנה (ברירת מחדל 0). להחזר חלקי שלחו את הסכום החלקי עם status: partiallyRefunded; להחזר מלא הגדירו אותו ל-total עם status: refunded. החזרים מקוזזים מההכנסה המיוחסת. |
refunds | object[] | לא | כל ההחזרים עד כה (עד 100): { "id": "RF-1", "amount": 29.99, "createdAt": "2026-06-03T09:00:00Z", "reason": "Wrong size", "items": [{ "productId": "SKU-1", "quantity": 1 }] } - רק amount חובה. כל החזר חדש יוצר אירוע Order Refunded אחד (לפי id; בלעדיו, לפי עליית הסכום שהוחזר), והחזר שכבר דווח לא יוצר שום דבר שוב. כשנשלחים בלי totalRefunded, הסכום שלהם הוא הסכום שהוחזר. מעבר ל-status: cancelled (או POST /orders/:id/cancel) יוצר אירוע Order Cancelled אחד. ראו אירועי החזר וביטול. |
couponCode | string | לא | קופון שהופעל |
coupons | object[] | לא | כל קודי הקופון שבהם השתמשו בהזמנה (עד 50): { "code": "SUMMER10", "amount": 10.0, "type": "fixed_amount" }. amount (ההנחה שהקוד נתן) ו-type אופציונליים. ב-upsert, coupons מחליף את הקודים השמורים ([] מנקה אותם); השמיטו אותו כדי לשמור אותם. כששולחים את שניהם, coupons גובר על couponCode |
shippingAddress | object | לא | כתובת משלוח |
campaignId | string | לא | קמפיין ייחוס |
canvasId | string | לא | מסע הייחוס |
source | string | לא | מקור ההזמנה (email, sms, direct) |
utmSource | string | לא | מקור UTM |
utmMedium | string | לא | מדיום UTM |
utmCampaign | string | לא | קמפיין UTM |
salesChannel | string | לא | איפה בוצעה ההזמנה: online, pos, app, phone, marketplace או other (אותיות גדולות או קטנות). כל ערך אחר מחזיר 400. אם לא נשלח, הזמנה חדשה מקבלת online והזמנה קיימת שומרת על הערוץ שלה. ראו חנות וערוץ מכירה |
storeId | string | לא | המזהה שלכם לחנות שאליה שייכת ההזמנה (חנות פיזית, סניף, אתר נוסף), עד 100 תווים. מסנן החנות בעמוד ההזמנות ותנאי הסגמנט "קנה בחנות" משווים אליו |
storeName | string | לא | שם התצוגה של החנות, עד 255 תווים, מוצג לצד storeId |
יש לספק userId או joryioUserId. השתמש ב-userId עם מזהי המשתמשים שלך (הנפוץ ביותר). השתמש ב-joryioUserId כאשר יש לך את מזהה המשתמש הפנימי של Joryio (ה-id בן 24 התווים המוחזר בתגובות ה-API).
מבנה פריט:
{
"productId": "prod_abc123",
"name": "Blue T-Shirt",
"sku": "BTS-001",
"quantity": 2,
"price": 29.99,
"total": 59.98,
"imageUrl": "https://example.com/image.jpg"
}
דוגמת בקשה:
curl -X POST https://api-eu1.joryio.com/api/orders \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"orderId": "ORD-2024-001",
"userId": "user-123",
"total": 89.97,
"subtotal": 99.97,
"discount": 10.00,
"shipping": 5.99,
"tax": 4.99,
"currency": "USD",
"coupons": [
{ "code": "SAVE10", "amount": 10.00, "type": "fixed_amount" }
],
"items": [
{
"productId": "prod_abc123",
"name": "Blue T-Shirt",
"quantity": 2,
"price": 29.99,
"total": 59.98
},
{
"productId": "prod_def456",
"name": "Black Jeans",
"quantity": 1,
"price": 49.99,
"total": 49.99
}
],
"source": "email",
"salesChannel": "pos",
"storeId": "tlv-dizengoff",
"storeName": "תל אביב - דיזנגוף",
"campaignId": "camp_xyz789"
}'
חנות וערוץ מכירה
כל הזמנה מציינת איפה היא נמכרה (salesChannel), ואם נשלחה חנות - לאיזו חנות היא שייכת (storeId). כך סוחר עם חנות פיזית ואתר, או עם שתי חנויות, יכול לסנן ולפצל הזמנות לפי כל אחת מהן ולבנות סגמנטים כמו "קנה בחנות הפיזית ב-90 הימים האחרונים".
salesChannel | משמעות |
|---|---|
online | האתר או הקופה המקוונת שלכם (ברירת המחדל) |
pos | קופה בחנות פיזית |
app | האפליקציה שלכם |
phone | הזמנה שהוזנה על ידי צוות: טלפון, מייל, הזמנה ידנית או טיוטה |
marketplace | מרקטפלייס של צד שלישי |
other | כל דבר אחר |
הערכים קבועים וזהים בכל מקום: ב-API הזה, במאפייני אירועים (sales_channel), בתנאי סגמנט ובייצוא ה-CSV של ההזמנות.
חנויות מחוברות ממלאות את שניהם בשבילכם. החנות היא החיבור לחנות עצמו, והערוץ נקבע לפי מה שהפלטפורמה רושמת:
| חנות | ערוץ מכירה |
|---|---|
| Shopify | לפי source_name של ההזמנה: web, online_store, checkout והזמנות מנוי הם online; pos הוא pos; shopify_draft_order, iphone ו-android (הזמנות שהצוות יוצר בממשק הניהול או באפליקציית Shopify) הם phone; כל השאר other |
| WooCommerce | לפי created_via: checkout ו-store-api הם online; admin הוא phone; תוסף קופה הוא pos; rest-api וכל השאר other |
| Magento | הזמנה שנוצרה בממשק הניהול (בלי כתובת IP של קונה) היא phone; כל הזמנה אחרת online |
| PrestaShop | תמיד online - PrestaShop לא רושמת איפה בוצעה ההזמנה |
אירוע Order Completed מה-SDK יכול לשלוח sales_channel (וגם store_id, store_name). בלי זה, הזמנה מאפליקציית iOS או Android מקבלת app והזמנה מאתר מקבלת online. האירועים Order Completed, Order Refunded ו-Order Cancelled כוללים את sales_channel, ואם להזמנה יש חנות גם את store_id, כך שמסע יכול להתחיל לפיהם.
סימון הזמנה כנשלחה
סימון הזמנה כנשלחה.
POST /orders/:id/fulfill
גוף הבקשה:
{
"trackingNumber": "1Z999AA10123456784",
"carrier": "UPS"
}
ביטול הזמנה
ביטול הזמנה.
POST /orders/:id/cancel
גוף הבקשה:
{
"reason": "Customer requested cancellation"
}
החזר כספי להזמנה
עיבוד החזר כספי.
POST /orders/:id/refund
גוף הבקשה:
{
"refundAmount": 29.99,
"reason": "Product defective",
"partial": true
}
סטטיסטיקות הזמנות
קבלת סטטיסטיקות הזמנות לטווח תאריכים.
GET /orders/stats?startDate=2024-01-01&endDate=2024-01-31
תגובה:
{
"totalOrders": 156,
"totalRevenue": 12450.50,
"averageOrderValue": 79.81,
"ordersByStatus": {
"pending": 5,
"processing": 12,
"shipped": 45,
"delivered": 90,
"cancelled": 4
}
}
מעקב עגלות
עדכון עגלה
מעקב או עדכון עגלת משתמש.
PUT /carts
גוף הבקשה:
{
"userId": "user_123",
"items": [
{
"productId": "prod_abc123",
"name": "Blue T-Shirt",
"price": 29.99,
"quantity": 2,
"total": 59.98,
"imageUrl": "https://example.com/image.jpg"
}
],
"value": 59.98,
"subtotal": 59.98,
"currency": "USD",
"checkoutUrl": "https://store.example.com/checkout?cart=abc123"
}
value הוא סכום העגלה כפי שאתם סופרים אותו (יכול לכלול משלוח ומס). subtotal אופציונלי: סכום הפריטים, לפני משלוח ומס - כשהוא לא נשלח הוא מחושב מהפריטים (ה-total של כל שורה, אחרת price x quantity). סכום הפריטים הוא ערך העגלה ב-מסחר אלקטרוני ← עגלות, במסנן הסגמנט ערך עגלה, ב-minValue וב-totalAbandonedValue.
הוספה לעגלה
הוספת פריט לעגלת משתמש.
POST /carts/add
גוף הבקשה:
{
"userId": "user_123",
"item": {
"productId": "prod_abc123",
"name": "Blue T-Shirt",
"price": 29.99,
"quantity": 1,
"total": 29.99
}
}
קבלת עגלות נטושות
רשימת עגלות נטושות לקמפיינים של שחזור.
GET /carts/abandoned
פרמטרי שאילתה:
| פרמטר | סוג | תיאור |
|---|---|---|
minValue | number | ערך עגלה מינימלי |
abandonedMinutesAgo | number | מספר הדקות המרבי מאז הנטישה |
limit | number | תוצאות לעמוד |
offset | number | היסט לדפדוף |
תגובה:
{
"data": [
{
"id": "cart_123",
"userId": "user_456",
"items": [...],
"value": 149.99,
"abandonedAt": "2024-01-20T15:30:00.000Z",
"checkoutUrl": "https://store.example.com/checkout?cart=abc"
}
],
"total": 42,
"hasMore": true
}
סטטיסטיקות עגלות
קבלת סטטיסטיקות עגלות ונטישה.
GET /carts/stats
תגובה:
{
"totalCarts": 1250,
"abandonedCarts": 312,
"recoveredCarts": 87,
"totalAbandonedValue": 45670.50,
"recoveryRate": 27.88
}
ניתוח RFM
ניתוח RFM (עדכניות, תדירות, ערך כספי) מפלח לקוחות על סמך התנהגות רכישה.
קבלת נתוני RFM של משתמש
קבלת ציוני RFM ופלח עבור משתמש ספציפי.
GET /rfm/user/:userId
:userId הוא מזהה המשתמש הפנימי או המזהה החיצוני שבו האפליקציה שלכם מזהה את האדם; מזהה לא מוכר מחזיר 404.
תגובה:
{
"totalOrders": 12,
"totalSpent": 849.50,
"averageOrderValue": 70.79,
"firstOrderDate": "2023-06-15T10:00:00.000Z",
"lastOrderDate": "2024-01-18T14:30:00.000Z",
"daysSinceLastOrder": 2,
"hasActiveCart": false,
"rfmRecency": 5,
"rfmFrequency": 4,
"rfmMonetary": 4,
"rfmScore": "544",
"rfmSegment": "champions"
}
שדות ה־RFM הם null עבור איש קשר ללא הזמנה שנספרה (הזמנות שבוטלו או הוחזרו אינן נספרות).
קבלת התפלגות RFM
קבלת התפלגות לקוחות על פני פלחי RFM.
GET /rfm/distribution
תגובה:
{
"champions": { "count": 150, "totalValue": 125000 },
"loyal": { "count": 320, "totalValue": 89000 },
"potential_loyalists": { "count": 180, "totalValue": 32000 },
"new_customers": { "count": 450, "totalValue": 28000 },
"at_risk": { "count": 95, "totalValue": 42000 },
"lost": { "count": 280, "totalValue": 15000 },
"scoring": {
"computedAt": "2026-09-02T02:00:00.000Z",
"method": "quantile",
"buyers": 1475
}
}
הדרגות הן חמישונים בתוך החנות (method: "quantile"): כל אחד מהמדדים - עדכניות, תדירות והוצאה נטו - מדורג על פני קוני החנות ומחולק לחמש קבוצות שוות, כך שדרגה עליונה פירושה החמישית העליונה של הלקוחות שלכם, בכל מטבע. חנות עם פחות מ־25 קונים משתמשת בספים קבועים (method: "fixed"). הציונים מחושבים מחדש מדי לילה ובכל הזמנה; scoring.computedAt מציין מתי.
פלחי RFM
| פלח | תיאור | ציוני RFM אופייניים |
|---|---|---|
| Champions (אלופים) | הלקוחות הטובים ביותר, קונים לעיתים קרובות, מוציאים הכי הרבה | 555, 554, 545 |
| Loyal (נאמנים) | לקוחות עקביים | 444, 443, 434 |
| Potential Loyalists (נאמנים פוטנציאליים) | לקוחות אחרונים עם תדירות ממוצעת | 433, 343, 333 |
| New Customers (לקוחות חדשים) | רק ביצעו רכישה ראשונה | 511, 512, 411 |
| Promising (מבטיחים) | אחרונים אך תדירות נמוכה | 422, 322, 312 |
| Needs Attention (דורשים תשומת לב) | ממוצעים, מעורבות יורדת | 332, 322, 233 |
| About to Sleep (עומדים להירדם) | מתחת לממוצע, בסיכון | 211, 212, 221 |
| At Risk (בסיכון) | היו נאמנים, לא קנו לאחרונה | 144, 143, 244 |
| Can't Lose (אסור לאבד) | היו הלקוחות הטובים ביותר, כעת לא פעילים | 155, 154, 255 |
| Hibernating (במצב שינה) | מעורבות נמוכה, לא פעילים זמן רב | 122, 121, 112 |
| Lost (אבודים) | ציונים נמוכים ביותר, כנראה נטשו | 111 |
מעקב בחנות Shopify
מפעיל (או מרענן) את הפיקסל של Joryio בחנות Shopify המחוברת - אירועי חנות וקופה - וכותב את ההגדרות שה-app embed של Joryio קורא. כשהפיקסל פעיל, סקריפט המעקב הישן של החנות (חנויות שחוברו לפני אוקטובר 2026) מפסיק לשלוח אירועים - Joryio לא מוחקת אותו; Shopify מסירה אותו כשמסירים את האפליקציה ומפסיקה לטעון אותו ב-1 במרץ 2027. אפשר לקרוא לו שוב בבטחה. נדרשת ההרשאה integrations:write.
POST /api/integrations/shopify/storefront-tracking
Authorization: Bearer YOUR_API_KEY
{
"pixel": { "status": "active", "id": "gid://shopify/WebPixel/123", "error": null, "checkedAt": "2026-10-03T10:00:00.000Z" },
"missingScopes": [],
"legacyScriptTag": false,
"appEmbed": {
"configured": true,
"themeEditorUrl": "https://my-store.myshopify.com/admin/themes/current/editor?context=apps&activateAppId=<api-key>/joryio-embed"
}
}
pixel.status | משמעות |
|---|---|
active | הפיקסל מותקן בחנות ושולח אירועים |
needs_scopes | החנות לא אישרה את write_pixels ו-read_customer_events. התחילו שוב את החיבור ל-Shopify (בעל החנות יתבקש לאשר אותן); missingScopes מפרט אותן |
error | Shopify דחתה את הפיקסל; pixel.error מסביר למה |
not_registered | עדיין לא הוגדר |
GET /api/integrations/shopify מחזיר את אותו אובייקט בשדה storefrontTracking. ראו חיבור Shopify.
הוא מחזיר גם את themeEmbed, השורה חלונות קופצים בחנות: activateUrl פותח את עורך ערכת העיצוב כש-embed של Joryio מופעל (בעל החנות לוחץ על שמירה; null כשלשרת אין אפליקציית Shopify מוגדרת), ו-status הוא on כשה-SDK של החנות דיווח ב-7 הימים האחרונים, אחרת not_reported. ראו הפעלת חלונות קופצים.
"themeEmbed": {
"activateUrl": "https://my-store.myshopify.com/admin/themes/current/editor?context=apps&activateAppId=<api-key>/joryio-embed",
"status": "not_reported"
}
installUrl (גם כשאין חנות מחוברת) הוא הכתובת שאליה התקנת Joryio מ-Shopify שולח סוחר שעדיין לא התקין את Joryio: דף אפליקציית Joryio ב-Shopify App Store או קישור התקנה, או null כשלשרת לא הוגדרה כתובת (לוח הבקרה מקשר אז לשלבי ההתקנה). Joryio לא מבקשת אף פעם את כתובת החנות - חנות מותקנת מ-Shopify ומקושרת. ראו חיבור החנות.
פתיחת האפליקציה מ-Shopify
כשסוחר מתקין או פותח את אפליקציית Joryio מ-Shopify, Shopify מוסיפה לכתובת האפליקציה פרמטרים חתומים (shop, hmac, timestamp, host). שלחו אותם כמו שהם; Joryio בודקת את החתימה של Shopify ושהקישור אינו ישן משעה, ומחזירה את מצב החנות בסביבת העבודה הנוכחית. הקריאה אף פעם לא מחברת דבר. דורש integrations:read.
POST /api/integrations/shopify/app-launch
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "query": { "shop": "my-store.myshopify.com", "host": "YWRtaW4uc2hvcGlmeS5jb20vc3RvcmUvbXktc3RvcmU", "timestamp": "1760000000", "hmac": "<from Shopify>" } }
{ "status": "not_connected", "shopDomain": "my-store.myshopify.com" }
status | משמעות |
|---|---|
connected_here | החנות מחוברת לסביבת העבודה הזו |
connected_elsewhere | מחוברת לסביבת עבודה אחרת בארגון; workspaceId מציין אותה |
not_connected | לא מחוברת בארגון - התחילו חיבור עם POST /api/integrations/shopify/oauth/initiate |
פרמטרים לא חתומים, ששונו או ישנים משעה מקבלים 400. ראו אינטגרציית Shopify.
הגדרת רישום מחדש בקופה של החנות
מפעילה או מכבה את ההגדרה לאפשר לסימון הסכמה בקופה לרשום מחדש אנשים שהסירו את עצמם בחיבור החנות. :platform הוא shopify, woocommerce, magento או prestashop. כבויה כברירת מחדל. כשהיא פועלת, הסכמה בקופה או ברשומת הלקוח מהחנות הזו - כולל קופה כאורח - שתאריכה אחרי ההסרה האחרונה של איש הקשר רושמת אותו מחדש. היא אף פעם לא גוברת על תלונת ספאם, החזרה קשה, STOP ב-SMS (רק אישור הצטרפות כפול), חסימה ברמת הארגון או הסרה של איש קשר אחר. כל שינוי נרשם ביומן הביקורת. דורש settings:write.
PUT /api/integrations/shopify/consent-settings
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "checkoutResubscribe": true }
{ "checkoutResubscribe": true }
GET /api/integrations/<platform> מחזיר את הערך הנוכחי כ-checkoutResubscribe. ראו הסכמה שיווקית מהחנות.
אמצעי הגנה לסימון הסכמה בקופה (WooCommerce, Magento, PrestaShop)
אותו נתיב מקבל את אמצעי ההגנה של Record consent immediately בחיבור WooCommerce או Magento, ואת אותם אמצעי הגנה עבור תיבת הניוזלטר בקופה של PrestaShop, שתמיד מגיעה ל-Joryio לפני ההזמנה (מודול 1.2.8 ואילך - ראו מתי סימון נחשב). :platform הוא woocommerce, magento או prestashop; Shopify מקבל 400. סימון בקופה שמגיע לפני הזמנה נספר מיד רק עבור קונה מוכר או מנוי; כל אחד אחר נשמר בהמתנה עד ההזמנה שלו או קישור האישור - ראו מתי סימון נחשב. checkoutConsentConfirmEmail (ברירת מחדל false) שולח לאורח כזה קישור אישור אחד במייל. checkoutConsentTickLimit (1-100, ברירת מחדל 3) הוא מספר הסימונים שמתקבלים לכל כתובת IP של קונה, לכל קופה ולכל כתובת אימייל בשעה; סימון מעבר לכך לא נרשם. שלחו אחד מהם או את שניהם, לבד או יחד עם checkoutResubscribe. כל שינוי נרשם ביומן הביקורת. נדרשת הרשאת settings:write.
PUT /api/integrations/magento/consent-settings
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "checkoutConsentConfirmEmail": true, "checkoutConsentTickLimit": 5 }
{ "checkoutConsentConfirmEmail": true, "checkoutConsentTickLimit": 5 }
GET /api/integrations/woocommerce, GET /api/integrations/magento ו-GET /api/integrations/prestashop מחזירים את שני הערכים.
newShopperOptIns - הסכמות של קונים חדשים (שעוד לא קנו) - הוא hold (ברירת מחדל) או immediate. הוא חל על כל הסכמה שמגיעה בלי הזמנה ממי ש-Joryio עוד לא מכירה: סימון בקופה שנשלח לפני ההזמנה, והסכמה בהרשמה, בדף החשבון, בניוזלטר או מסנכרון הלקוחות. hold משאיר אותה בהמתנה עד ההזמנה או קישור האישור; immediate סופר אותה מיד (פחות מחמיר - כל מבקר יכול להזין כל כתובת מייל). קונים ומנויים מוכרים נספרים מיד בכל מקרה, הסרה מרשימת התפוצה תמיד חלה מיד, ו-checkoutConsentTickLimit נשאר בתוקף. אותו נתיב ואותן פלטפורמות, לבד או עם השדות האחרים; כל שינוי נרשם ביומן הביקורת; נדרשת ההרשאה settings:write. GET /api/integrations/<platform> מחזיר אותו כ-newShopperOptIns.
PUT /api/integrations/woocommerce/consent-settings
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "newShopperOptIns": "immediate" }
{ "newShopperOptIns": "immediate" }
GET /api/integrations/woocommerce ו-GET /api/integrations/magento מחזירים גם storeCheckoutOptIn: הגדרות ההסכמה בקופה של התוסף עצמו כפי שדיווח עליהן לאחרונה (תוסף WooCommerce בגרסה 1.6.16 ומעלה, הרחבת Magento בגרסה 1.4.17 ומעלה). הן לקריאה בלבד - מוגדרות בחנות, אף פעם לא דרך ה-API הזה - והערך הוא null עד שהתוסף מדווח עליהן. recordMode הוא order (רק כשההזמנה מתבצעת) או immediate (רישום הסכמה מיד).
{ "storeCheckoutOptIn": { "pluginVersion": "1.6.16", "checkoutBox": true, "preTicked": false, "recordMode": "order", "reportedAt": "2026-10-27T10:00:00.000Z" } }
זהות מבקרים: זיהוי מבקרים לפי האימייל שהם מקלידים
Recognise visitors by the email they type - ראו WooCommerce ו-Shopify. מופעלת כברירת מחדל: אימייל שהוקלד בקופה או בטופס מזהה את הדפדפן של המבקר כאיש הקשר עם האימייל הזה. כבויה (זהות קפדנית): אימייל שהוקלד לעולם לא מזהה את הדפדפן; עגלות, הזמנות והגשות טפסים עדיין עוברות לאיש הקשר של האימייל.
GET /api/integrations/<platform> מחזיר visitorIdentity: identifyByTypedEmail, source (default - עדיין לא דווח או הוגדר דבר, כלומר מופעלת; plugin - דווח על ידי תוסף WooCommerce בגרסה 1.6.22 ומעלה, הרחבת Magento בגרסה 1.4.21 ומעלה או מודול PrestaShop בגרסה 1.2.10 ומעלה; joryio - הוגדר ב-Joryio), pluginVersion ו-reportedAt. ב-WooCommerce, Magento ו-PrestaShop ההגדרה נמצאת בתוסף של החנות והיא לקריאה בלבד כאן. ב-Shopify מגדירים אותה עם הנתיב שלהלן; פלטפורמות אחרות מקבלות 400. כל שינוי נרשם ביומן הביקורת. דורש settings:write.
PUT /api/integrations/shopify/visitor-identity
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "identifyByTypedEmail": false }
{ "visitorIdentity": { "identifyByTypedEmail": false, "source": "joryio", "pluginVersion": null, "reportedAt": "2026-11-01T10:00:00.000Z" } }
חיבור PrestaShop (גישה מוקדמת)
קריאה וניהול של חיבור ה-PrestaShop של סביבת העבודה (חנות PrestaShop אחת לכל חיבור; ראו אינטגרציית PrestaShop). GET מחזיר { "connected": false, "platform": "prestashop" } כשאין חיבור. הנתיב api-key מחזיר את מפתח ה-jry_ps_ שמדביקים במודול (דורש integrations:write, כמו settings, sync ו-DELETE). GET מחזיר גם workspaceId, prestashopVersion ו-moduleVersion. sync מקבל type: full (ברירת מחדל), delta (מוצרים, לקוחות והזמנות שהשתנו מאז הסנכרון התקין האחרון), products, customers, orders או carts (עגלות פתוחות מ-24 השעות האחרונות), וחוזר מיד בזמן שהסנכרון רץ. DELETE מנתק את החנות ומבטל את המפתח.
GET /api/integrations/prestashop
Authorization: Bearer YOUR_API_KEY
{
"connected": true,
"status": "connected",
"platform": "prestashop",
"storeName": "My Shop",
"storeUrl": "https://shop.example.com",
"shopId": 1,
"workspaceId": "6f1c2d3e-...",
"prestashopVersion": "8.2.1",
"moduleVersion": "1.0.0",
"syncSettings": { "syncProducts": true, "syncOrders": true, "syncCustomers": true, "syncCarts": true, "historicalDays": 90 },
"checkoutResubscribe": false,
"syncStats": { "productCount": 120, "orderCount": 860, "customerCount": 540 },
"lastSyncAt": "2026-10-21T10:00:00.000Z",
"connectedAt": "2026-10-21T09:58:00.000Z"
}
connectedAt הוא מועד החיבור האחרון של החנות (כל חיבור מחדש מעדכן אותו); גם GET /api/integrations/shopify, /woocommerce ו-/magento מחזירים אותו. לחיבור שנוצר לפני שהשדה נרשם מוחזר מועד יצירת הרשומה.
GET /api/integrations/prestashop/api-key
Authorization: Bearer YOUR_API_KEY
{ "apiKey": "jry_ps_...", "isNew": false }
PUT /api/integrations/prestashop/settings
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "syncCarts": true, "historicalDays": 90 }
POST /api/integrations/prestashop/sync
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "type": "full" }
DELETE /api/integrations/prestashop
Authorization: Bearer YOUR_API_KEY
Webhooks
אירועי מסחר אלקטרוני שולחים Webhooks שיכולים להפעיל מסעות:
| אירוע | תיאור |
|---|---|
ecommerce.order.created | הזמנה חדשה בוצעה |
ecommerce.order.fulfilled | הזמנה נשלחה |
ecommerce.order.cancelled | הזמנה בוטלה |
ecommerce.order.refunded | הזמנה הוחזרה |
ecommerce.order.status_changed | סטטוס הזמנה השתנה |
ecommerce.cart.abandoned | עגלה סומנה כנטושה |
ecommerce.cart.recovered | עגלה נטושה שוחזרה |
ecommerce.cart.updated | תוכן העגלה השתנה |
חיפוש לפי המזהים שלכם
קבלת מוצר לפי מזהה המוצר שלך
קבלת מוצר באמצעות מזהה המוצר שלך.
GET /catalog/products/by-product-id/:productId
מזהה שאין לו רשומה תואמת מחזיר 404, ולא 200 עם גוף ריק.
דוגמה:
curl "https://api-eu1.joryio.com/api/catalog/products/by-product-id/SKU-12345" \
-H "Authorization: Bearer $TOKEN"
קבלת הזמנה לפי מזהה ההזמנה שלך
קבלת הזמנה באמצעות מזהה ההזמנה שלך.
GET /orders/by-order-id/:orderId
מזהה שאין לו רשומה תואמת מחזיר 404, ולא 200 עם גוף ריק.
דוגמה:
curl "https://api-eu1.joryio.com/api/orders/by-order-id/ORD-2024-001" \
-H "Authorization: Bearer $TOKEN"
הזמנות, עגלות ו־RFM דרך ה־API
עדכון/יצירת הזמנות בכמות
POST /orders/upsert
הדרך העיקרית שבה חנות שאינה על Shopify, WooCommerce או Magento שולחת את ההזמנות שלה. אידמפוטנטי לפי orderId: שליחה חוזרת של אותה הזמנה מעדכנת אותה במקום ליצור כפילות, ולכן ניסיון חוזר אחרי כשל רשת בטוח.
שלחו כל הזמנה במטבע שבו שולמה, בלי להמיר דבר: Joryio ממירה את total למטבע הדיווח של סביבת העבודה לפי שער הבנק המרכזי האירופי של תאריך placedAt של ההזמנה, והדוחות מסכמים את הסכום המומר.
גוף הבקשה:
{
"orders": [
{
"orderId": "1001",
"userId": "user_123",
"total": 89.90,
"currency": "EUR",
"placedAt": "2026-08-27T10:15:00Z",
"status": "completed",
"items": [
{ "productId": "prod_abc123", "quantity": 2, "price": 29.95 }
]
}
]
}
תגובה:
{ "upserted": 1, "created": 1, "updated": 0 }
מגמת הכנסות
GET /orders/revenue-trend?days=30&granularity=day
הכנסה נטו לאורך זמן (ללא החזרים וביטולים). granularity הוא day, week או month.
תגובה:
{
"currency": "EUR",
"points": [
{ "date": "2026-08-25", "revenue": 1240.50, "orders": 14 },
{ "date": "2026-08-26", "revenue": 980.00, "orders": 11 }
]
}
מחזור חיי העגלה
POST /carts/remove
POST /carts/clear
POST /carts/mark-abandoned
POST /carts/recovered
ארבע פעולות שמניעות מסעי שחזור עגלה. clear ו־recovered שתיהן מסיימות את העגלה ואינן חליפיות: recovered אומרת שהשחזור הצליח ומזכה אותו, clear אומרת שהעגלה פשוט נעלמה. שימוש ב־clear אחרי רכישה מוחק בשקט את הראיה שמסע השחזור הניב משהו.
{ "userId": "user_123", "orderId": "1001" }
רשימת מקטעי RFM
GET /rfm/segments
מקטעי ה־RFM במרחב העבודה עם הגדלים הנוכחיים שלהם, כדי שאינטגרציה תוכל לכוון אליהם בלי לחשב מחדש את הניקוד.
תגובה:
{
"segments": [
{ "segment": "champions", "users": 412, "avgRecencyDays": 8, "avgOrders": 6.2 },
{ "segment": "at_risk", "users": 1180, "avgRecencyDays": 96, "avgOrders": 2.1 }
],
"computedAt": "2026-08-27T02:10:00Z"
}
תגובות שגיאה
{
"statusCode": 404,
"message": "Product SKU-12345 not found",
"error": "Not Found"
}
| קוד סטטוס | תיאור |
|---|---|
| 400 | גוף בקשה לא תקין |
| 401 | נדרש אימות |
| 403 | הרשאות לא מספיקות |
| 404 | משאב לא נמצא |
| 409 | התנגשות (מזהה חיצוני כפול) |
| 500 | שגיאת שרת פנימית |