דלג לתוכן הראשי

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

גוף הבקשה:

שדהסוגחובהתיאור
productIdstringכןמזהה המוצר הייחודי שלך (מק"ט, מזהה מוצר)
namestringכןשם המוצר
pricenumberכןמחיר המוצר
descriptionstringלאתיאור המוצר
compareAtPricenumberלאמחיר מקורי (להנחות)
currencystringלאקוד מטבע (ברירת מחדל: USD)
categoriesstring[]לאקטגוריות המוצר
tagsstring[]לאתגיות המוצר
brandstringלאשם המותג
imageUrlstringלאכתובת תמונה ראשית
urlstringלאכתובת דף המוצר
inStockbooleanלאזמינות במלאי (ברירת מחדל: true)
skustringלאמק"ט
variantsobject[]לאוריאנטים של המוצר
customFieldsobjectלאשדות מותאמים אישית

דוגמת בקשה:

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

פרמטרי שאילתה:

פרמטרסוגתיאור
searchstringחיפוש לפי שם, תיאור או מק"ט
categoriesstring[]סינון לפי קטגוריות
tagsstring[]סינון לפי תגיות
brandstringסינון לפי מותג
inStockbooleanסינון לפי זמינות במלאי
minPricenumberמחיר מינימלי
maxPricenumberמחיר מקסימלי
limitnumberתוצאות לעמוד (ברירת מחדל: 50)
offsetnumberהיסט לדפדוף
sortBystringשדה מיון: name, price, createdAt, updatedAt
sortOrderstringasc או 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

גוף הבקשה:

שדהסוגחובהתיאור
orderIdstringכןמזהה ההזמנה שלך (מספר הזמנה מהפלטפורמה שלך)
userIdstringאחד מהשנייםמזהה המשתמש של הלקוח שלך
joryioUserIdstringאחד מהשנייםמזהה משתמש פנימי של Joryio (חלופה ל-userId)
totalnumberכןסכום ההזמנה הכולל
itemsobject[]כןפריטים בהזמנה
statusstringלאסטטוס הזמנה (ברירת מחדל: pending)
paymentStatusstringלאpaid או unpaid: האם ההזמנה שולמה. הזמנת תשלום במזומן בעת המסירה או העברה בנקאית היא processing ו-unpaid עד שהכסף מגיע, ומוצגת בדף ההזמנות כממתין לתשלום במקום שולמה. בלעדיו, הזמנה בעיבוד / שנשלחה / שנמסרה נחשבת שולמה (הזמנה קיימת שומרת את הערך שיש לה). ההכנסות אינן תלויות בו. ראו שולמה או ממתינה לתשלום.
currencystringלאקוד מטבע
subtotalnumberלאסכום ביניים לפני הנחות
discountnumberלאסכום הנחה
shippingnumberלאעלות משלוח
taxnumberלאסכום מס
totalRefundednumberלאהסכום שהוחזר עד כה, במטבע ההזמנה (ברירת מחדל 0). להחזר חלקי שלחו את הסכום החלקי עם status: partiallyRefunded; להחזר מלא הגדירו אותו ל-total עם status: refunded. החזרים מקוזזים מההכנסה המיוחסת.
refundsobject[]לאכל ההחזרים עד כה (עד 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 אחד. ראו אירועי החזר וביטול.
couponCodestringלאקופון שהופעל
couponsobject[]לאכל קודי הקופון שבהם השתמשו בהזמנה (עד 50): { "code": "SUMMER10", "amount": 10.0, "type": "fixed_amount" }. amount (ההנחה שהקוד נתן) ו-type אופציונליים. ב-upsert, coupons מחליף את הקודים השמורים ([] מנקה אותם); השמיטו אותו כדי לשמור אותם. כששולחים את שניהם, coupons גובר על couponCode
shippingAddressobjectלאכתובת משלוח
campaignIdstringלאקמפיין ייחוס
canvasIdstringלאמסע הייחוס
sourcestringלאמקור ההזמנה (email, sms, direct)
utmSourcestringלאמקור UTM
utmMediumstringלאמדיום UTM
utmCampaignstringלאקמפיין UTM
salesChannelstringלאאיפה בוצעה ההזמנה: online, pos, app, phone, marketplace או other (אותיות גדולות או קטנות). כל ערך אחר מחזיר 400. אם לא נשלח, הזמנה חדשה מקבלת online והזמנה קיימת שומרת על הערוץ שלה. ראו חנות וערוץ מכירה
storeIdstringלאהמזהה שלכם לחנות שאליה שייכת ההזמנה (חנות פיזית, סניף, אתר נוסף), עד 100 תווים. מסנן החנות בעמוד ההזמנות ותנאי הסגמנט "קנה בחנות" משווים אליו
storeNamestringלאשם התצוגה של החנות, עד 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

פרמטרי שאילתה:

פרמטרסוגתיאור
minValuenumberערך עגלה מינימלי
abandonedMinutesAgonumberמספר הדקות המרבי מאז הנטישה
limitnumberתוצאות לעמוד
offsetnumberהיסט לדפדוף

תגובה:

{
"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 מפרט אותן
errorShopify דחתה את הפיקסל; 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",
"email": "[email protected]",
"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שגיאת שרת פנימית