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

Entities API

REST API לניהול ישויות מותאמות והרשומות שלהן.

כל נקודות הקצה בעמוד זה יחסיות לכתובת הבסיס: https://api-eu1.joryio.com - ראו סקירת API.

סקירה

Entities API מאפשר גישה תכנותית לפעולות הבאות:

  • יצירה וניהול של הגדרות ישות (סכמות)
  • הוספה, עדכון ומחיקה של רשומות ישות (נתונים)
  • ביצוע שאילתות וחיפוש ברשומות
  • ניהול שדות וקשרים בין ישויות

אימות

כל נקודות הקצה דורשות אימות באמצעות טוקן Bearer:

Authorization: Bearer YOUR_API_KEY

וכן ציון סביבת העבודה באמצעות כותרת:

X-Workspace-Id: YOUR_WORKSPACE_ID

הגדרות ישות

רשימת כל הישויות

קבלת כל הגדרות הישויות בסביבת העבודה הנוכחית.

GET /entities

תגובה:

[
{
"id": "uuid",
"organizationId": "uuid",
"workspaceId": "uuid",
"name": "products",
"displayName": "Products",
"description": "Product catalog",
"collectionName": "entity_products",
"primaryKey": "_id",
"displayField": "name",
"settings": {
"allowDuplicates": false,
"enableAudit": true,
"enableVersioning": false,
"softDelete": true
},
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
]

קבלת ישות לפי מזהה

שליפת הגדרת ישות ספציפית.

GET /entities/:entityId

תגובה:

{
"id": "uuid",
"name": "products",
"displayName": "Products",
...
}

יצירת ישות

יצירת הגדרת ישות חדשה עם שדות.

POST /entities

גוף בקשה:

{
"name": "products",
"displayName": "Products",
"description": "Product catalog with pricing",
"displayField": "name",
"fields": [
{
"name": "sku",
"displayName": "SKU",
"fieldType": "string",
"validation": {
"required": true,
"unique": true,
"minLength": 5,
"maxLength": 20
},
"indexed": true,
"displayOrder": 0
},
{
"name": "name",
"displayName": "Product Name",
"fieldType": "string",
"validation": {
"required": true,
"maxLength": 255
},
"displayOrder": 1
},
{
"name": "price",
"displayName": "Price",
"fieldType": "currency",
"validation": {
"required": true,
"min": 0
},
"displayOrder": 2
},
{
"name": "description",
"displayName": "Description",
"fieldType": "markdown",
"displayOrder": 3
},
{
"name": "active",
"displayName": "Active",
"fieldType": "boolean",
"validation": {
"default": true
},
"displayOrder": 4
}
],
"settings": {
"allowDuplicates": false,
"enableAudit": true,
"enableVersioning": false,
"softDelete": true
}
}

סוגי שדות:

  • string, email, phone, url
  • number, integer, currency, percentage
  • boolean
  • date, datetime
  • markdown, html, json
  • image_url, file_url

תגובה:

{
"id": "uuid",
"name": "products",
...
}

עדכון ישות

עדכון הגדרת ישות (שם, תיאור, הגדרות).

PUT /entities/:entityId

גוף בקשה:

{
"displayName": "Updated Products",
"description": "Updated description",
"displayField": "sku",
"settings": {
"enableAudit": false
}
}

מחיקת ישות

מחיקת ישות וכל הרשומות שלה.

DELETE /entities/:entityId

תגובה: 204 No Content

אזהרה: פעולה זו מוחקת לצמיתות את סכמת הישות ואת כל הרשומות!

שדות ישות

רשימת שדות

קבלת כל השדות של ישות.

GET /entities/:entityId/fields

תגובה:

[
{
"id": "uuid",
"entityDefinitionId": "uuid",
"name": "sku",
"displayName": "SKU",
"description": "Product SKU",
"fieldType": "string",
"validation": {
"required": true,
"unique": true,
"minLength": 5,
"maxLength": 20
},
"indexed": true,
"indexType": "btree",
"displayOrder": 0,
"hidden": false,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
]

הוספת שדה

הוספת שדה חדש לישות.

POST /entities/:entityId/fields

גוף בקשה:

{
"name": "category",
"displayName": "Category",
"fieldType": "string",
"validation": {
"required": false
},
"indexed": true,
"displayOrder": 5
}

מחיקת שדה

הסרת שדה מישות.

DELETE /entities/:entityId/fields/:fieldId

תגובה: 204 No Content

אזהרה: פעולה זו מסירה את הגדרת השדה. נתוני הרשומות הקיימים לא נמחקים אך אינם נגישים.

רשומות ישות

רשימת רשומות

שליפת רשומות מישות עם סינון אופציונלי.

GET /entities/:entityId/records

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

  • filter - אובייקט סינון JSON (מקודד ל־URL)
  • sort - אובייקט מיון JSON (מקודד ל־URL)
  • limit - מספר הרשומות המרבי (ברירת מחדל: 50)
  • offset - מספר רשומות לדילוג (ברירת מחדל: 0)

דוגמאות:

# All active products
GET /entities/ENTITY_ID/records?filter={"active":true}

# Products sorted by price descending
GET /entities/ENTITY_ID/records?sort={"price":-1}

# Paginated results
GET /entities/ENTITY_ID/records?limit=20&offset=40

תגובה:

{
"data": [
{
"_id": "665f1c0a9b2e4d0012ab34cd",
"sku": "PROD-001",
"name": "Widget",
"price": 29.99,
"description": "A great widget",
"active": true,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"total": 150
}

קבלת רשומה לפי מזהה

שליפת רשומה ספציפית.

GET /entities/:entityId/records/:recordId

תגובה:

{
"_id": "665f1c0a9b2e4d0012ab34cd",
"sku": "PROD-001",
"name": "Widget",
...
}

יצירת רשומה

הוספת רשומה חדשה לישות.

POST /entities/:entityId/records

גוף בקשה:

{
"sku": "PROD-001",
"name": "Widget",
"price": 29.99,
"description": "A great widget",
"active": true
}

תיקוף:

  • שדות חובה חייבים להופיע
  • שדות ייחודיים חייבים להיות ייחודיים
  • ערכים חייבים להתאים לסוגי השדות
  • מגבלות מזעריות ומרביות נאכפות

תגובה:

{
"_id": "665f1c0a9b2e4d0012ab34cd",
"sku": "PROD-001",
...
}

עדכון רשומה

עדכון רשומה קיימת.

PUT /entities/:entityId/records/:recordId

גוף בקשה:

{
"price": 34.99,
"description": "An even better widget"
}

יש תמיכה בעדכונים חלקיים - שלחו רק את השדות שברצונכם לשנות.

מחיקת רשומה

הסרת רשומה מישות.

DELETE /entities/:entityId/records/:recordId

תגובה: 204 No Content

אם מחיקה רכה מופעלת, הרשומה מסומנת כמחוקה. אחרת היא נמחקת לצמיתות.

יצירת רשומות מרובות (גוף מסוג מערך)

אין נקודת קצה נפרדת לפעולה קבוצתית: POST /entities/:entityId/records מקבל או אובייקט רשומה יחיד או מערך JSON חשוף של אובייקטי רשומה (ללא אובייקט עוטף). צורת המערך יוצרת עד 1000 רשומות בבקשה אחת.

POST /entities/:entityId/records

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

  • triggerAlerts - הגדירו true כדי להפעיל התראות על קשרים (חזרה למלאי וכדומה) עבור רשומות שמצבן משתנה בייבוא הזה (ברירת מחדל: false)

גוף בקשה:

מערך JSON (עד 1000 איברים; מערך ריק או יותר מ־1000 מחזיר 400). כל איבר משתמש באותה מעטפת data כמו הצורה של אובייקט בודד.

המעטפת של כל איבר עוברת תיקוף בנפרד: איבר ללא אובייקט data מדווח ב־failed לפי האינדקס שלו במערך - הוא לעולם אינו מתקבל ללא התראה - ושאר האיברים התקינים עדיין נוספים. תיקוף הגדרות השדות (שדות חובה, סוגים ומגבלות מזעריות ומרביות) חל על האצווה כולה, בדיוק כמו ביצירה יחידה.

[
{
"data": {
"sku": "PROD-001",
"name": "Widget A",
"price": 29.99
}
},
{
"data": {
"sku": "PROD-002",
"name": "Widget B",
"price": 39.99
}
}
]

תגובה:

בשונה מצורת האובייקט (שמחזירה את הרשומה שנוצרה), צורת המערך מחזירה סיכום מצרפי:

{
"processed": 2,
"inserted": 2,
"insertedIds": ["id-1", "id-2"],
"failed": []
}
שדהתיאור
processedמספר האיברים שהתקבלו במערך הבקשה
insertedרשומות שנוצרו בפועל
insertedIdsמזהי הרשומות שנוצרו, לפי סדר ההכנסה
failedכשלי מעטפת לכל איבר: index (המיקום במערך הבקשה), reason

חיפוש

חיפוש רשומות

חיפוש טקסט מלא בשדות שצוינו.

GET /entities/:entityId/search

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

  • q - מחרוזת חיפוש (חובה)
  • fields - רשימת שדות לחיפוש מופרדת בפסיקים (אופציונלי)
  • limit - מספר התוצאות המרבי (ברירת מחדל: 10)

דוגמאות:

# Search across all indexed fields
GET /entities/ENTITY_ID/search?q=widget

# Search specific fields
GET /entities/ENTITY_ID/search?q=PROD-001&fields=sku,name

# Limit results
GET /entities/ENTITY_ID/search?q=widget&limit=5

תגובה:

[
{
"_id": "id",
"sku": "PROD-001",
"name": "Widget",
...
}
]

שאילתות מתקדמות

צבירה

ביצוע פעולות צבירה על רשומות ישות.

POST /entities/:entityId/aggregate

גוף בקשה:

{
"groupBy": "category",
"aggregations": [
{
"field": "price",
"operation": "avg",
"as": "avgPrice"
},
{
"field": "price",
"operation": "sum",
"as": "totalValue"
},
{
"operation": "count",
"as": "productCount"
}
]
}

פעולות:

  • count - ספירת רשומות
  • sum - סכום ערכים
  • avg - ממוצע ערכים
  • min - ערך מינימלי
  • max - ערך מקסימלי

תגובה:

{
"results": [
{
"category": "Electronics",
"avgPrice": 45.99,
"totalValue": 2299.50,
"productCount": 50
},
{
"category": "Clothing",
"avgPrice": 29.99,
"totalValue": 1499.50,
"productCount": 50
}
]
}

שאילתות מורכבות

ביצוע שאילתות מורכבות בסגנון MongoDB.

POST /entities/query

גוף בקשה:

{
"entity": "products",
"pipeline": [
{
"$match": {
"price": { "$gte": 20, "$lte": 50 },
"active": true
}
},
{
"$group": {
"_id": "$category",
"count": { "$sum": 1 },
"avgPrice": { "$avg": "$price" }
}
},
{
"$sort": { "avgPrice": -1 }
}
]
}

אופרטורים לסינון

בעת שימוש במסננים, ניתן להשתמש באופרטורים בסגנון MongoDB:

השוואה

  • $eq - שווה ל
  • $ne - לא שווה ל
  • $gt - גדול מ
  • $gte - גדול או שווה
  • $lt - קטן מ
  • $lte - קטן או שווה
  • $in - ערך במערך
  • $nin - ערך לא במערך

לוגיקה

  • $and - AND לוגי
  • $or - OR לוגי
  • $not - NOT לוגי
  • $nor - NOR לוגי

איבר

  • $exists - שדה קיים
  • $type - בדיקת סוג שדה

מחרוזת

  • $regex - התאמה לביטוי רגולרי

דוגמאות:

// Price between 10 and 100
{
"price": { "$gte": 10, "$lte": 100 }
}

// Active products in specific categories
{
"active": true,
"category": { "$in": ["Electronics", "Computers"] }
}

// Complex condition
{
"$or": [
{ "price": { "$lte": 20 } },
{ "onSale": true }
],
"active": true
}

תגובות שגיאה

400 Bad Request

{
"statusCode": 400,
"message": "Validation failed",
"errors": [
{
"field": "price",
"message": "price must be greater than or equal to 0"
}
]
}

401 Unauthorized

{
"statusCode": 401,
"message": "Unauthorized"
}

404 Not Found

{
"statusCode": 404,
"message": "Entity not found"
}

409 Conflict

{
"statusCode": 409,
"message": "Duplicate value for unique field 'sku'"
}

מגבלות קצב

ל־Entities API אין כיום מגבלות קצב קבועות לכל נקודת קצה - ראו סקירת API: הגבלת קצב להסבר על ההתנהגות ברמת הפלטפורמה ועל הטיפול בתגובות 429.

שיטות עבודה מומלצות

ביצועים

  1. השתמשו באינדקסים - צרו אינדקסים לשדות שאתם מסננים או מחפשים לפיהם לעיתים קרובות
  2. השתמשו בעימוד - אל תשלפו את כל הרשומות בבת אחת
  3. הגבילו את בחירת השדות - שלפו רק את השדות שאתם צריכים
  4. שמרו תגובות במטמון - שמרו במטמון נתונים שניגשים אליהם לעיתים קרובות
  5. השתמשו בפעולות באצווה - השתמשו בנקודות קצה קבוצתיות כשאפשר

איכות נתונים

  1. תקפו נתונים לפני הוספתם - בדקו את הנתונים בצד הלקוח
  2. טפלו בשגיאות - ממשו טיפול נאות בשגיאות
  3. השתמשו בטרנזקציות - בפעולות שכוללות רשומות מרובות
  4. נקו באופן סדיר - העבירו רשומות ישנות לארכיון או מחקו אותן

אבטחה

  1. לעולם אל תחשפו מפתחות API - שמרו אותם בצד השרת
  2. תקפו קלט משתמשים - טהרו אותו לפני שליחתו ל־API
  3. השתמשו ב־HTTPS בלבד - לעולם אל תשתמשו ב־HTTP
  4. החליפו מפתחות באופן סדיר - עדכנו את מפתחות ה־API מעת לעת
  5. ממשו הגבלת קצב - גם בצד שלכם

דוגמאות קוד

JavaScript/Node.js

const axios = require('axios');

const api = axios.create({
baseURL: 'https://api-eu1.joryio.com',
headers: {
'Authorization': `Bearer ${process.env.HIPPO_API_KEY}`,
'X-Workspace-Id': process.env.WORKSPACE_ID
}
});

// Create entity
const entity = await api.post('/entities', {
name: 'products',
displayName: 'Products',
fields: [/* ... */]
});

// Create record
const record = await api.post(`/entities/${entity.data.id}/records`, {
sku: 'PROD-001',
name: 'Widget',
price: 29.99
});

// Search records
const results = await api.get(`/entities/${entity.data.id}/search`, {
params: { q: 'widget' }
});

Python

import requests
import os

api_key = os.getenv('HIPPO_API_KEY')
workspace_id = os.getenv('WORKSPACE_ID')

headers = {
'Authorization': f'Bearer {api_key}',
'X-Workspace-Id': workspace_id
}

# Create entity
response = requests.post(
'https://api-eu1.joryio.com/entities',
json={
'name': 'products',
'displayName': 'Products',
'fields': [...]
},
headers=headers
)
entity = response.json()

# Create record
response = requests.post(
f'https://api-eu1.joryio.com/entities/{entity["id"]}/records',
json={
'sku': 'PROD-001',
'name': 'Widget',
'price': 29.99
},
headers=headers
)

תיעוד קשור