# واجهة برمجة تطبيقات Object tags (تجريبي)

تخزن الـ object tags بيانات منظمة عن المستخدم في tag واحد. يحتوي الـ tag من نوع `Object` على كائن واحد بحقول مسماة، مثل آخر طلب `order` مع الحقلين `amount` و `status`. ويحتوي الـ tag من نوع `ObjectList` على مصفوفة من هذه الكائنات، مثل جميع الطلبات `orders`. تُعرّف الحقول مرة واحدة، وتكتب القيم وتقرأها عبر واجهة برمجة تطبيقات الـ tags، وتنشئ الشرائح حسب قيم الحقول.

<Aside type="caution" title="تجريبي">
الـ object tags في المرحلة التجريبية ومتاحة عند الطلب. اتصل بـ [دعم Pushwoosh](https://help.pushwoosh.com/hc/en-us/requests/new) لتمكينها لحسابك. خلال المرحلة التجريبية، تعمل الـ object tags عبر الـ API فقط:

- لا توجد في Control Panel شاشة للـ object tags.
- لا يمكن إدراج حقول الـ object tags في محتوى الرسالة.
- لا يدعم Customer Journey الـ object tags.
</Aside>

## كيف تعمل الـ object tags

للـ object tag مخطط وقيمة. المخطط هو اسم الـ tag وقائمة الحقول، ولكل حقل نوعه العددي (scalar) الخاص. تُخزَّن القيمة في الحقول، بشكل منفصل لكل مستخدم.

- **الحقل.** كل حقل هو tag باسم `<object>.<field>`، مثل `order.amount`. تنشئ الشرائح حسب الحقول، ويمكنك كتابة حقل من tag من نوع `Object` بهذا الاسم.
- **قيمة `Object`.** كائن واحد لكل مستخدم، مثل `"order": {"amount": 120, "status": "paid"}`.
- **قيمة `ObjectList`.** مصفوفة من الكائنات بالحقول نفسها، مثل `"orders": [{"amount": 120, "status": "paid"}, {"amount": 50}]`.

الـ object tags دائمًا من نوع User-specific، أي أن القيمة تخص المستخدم وليس جهازًا واحدًا، وتُنسخ إلى جميع أجهزة المستخدم. للاطلاع على الـ tags العادية، راجع [واجهة برمجة تطبيقات Tags](/ar/developer/api-reference/tags/).

## قواعد المخطط

يتحقق Pushwoosh من هذه القواعد عند إنشاء object tag أو إضافة حقل:

- تحتوي أسماء الكائنات والحقول على أحرف لاتينية وأرقام و `_` فقط.
- لا يتجاوز الاسم الكامل للحقل `<object>.<field>` 64 حرفًا.
- يحتوي الـ object tag على 1 إلى 20 حقلًا. أسماء الحقول غير حساسة لحالة الأحرف، لذا فإن `Amount` و `amount` هما الحقل نفسه.
- يكون للحقل أحد هذه الأنواع: `INTEGER`، `STRING`، `LIST`، `DATE`، `BOOLEAN`، `PRICE`، `VERSION`. حقول المنطقة الزمنية والكائنات المتداخلة غير مدعومة.
- لا يمكن أن يأخذ الحقل اسمًا يحمله tag آخر بالفعل. إذا كان الـ tag `order.note` موجودًا، تفشل إضافة الحقل `note` إلى `order` بالخطأ `tag order.note already exists`.
- لا يمكن أن يفقد الـ object tag آخر حقل فيه. احذف الـ object tag بدلًا من ذلك.
- لا يمكن حذف حقل أو object tag قيد الاستخدام. يسرد الخطأ أماكن الاستخدام، مثل `field is in use: segment Big buyers, in-app Spring sale`. تُحتسب كاستخدامات: الشرائح، والـ In-Apps، وحملات Customer Journey الجارية، والـ presets، وقوالب البريد الإلكتروني، والعناصر الأخرى التي تشير إلى الـ tag.

## إدارة المخطط

أنشئ الـ object tags وعدّلها باستخدام أساليب REST أدناه. استخدم `/json/1.3/addTag` للـ tags العادية فقط، لأنه لا يستطيع تعريف الحقول.

### عنوان URL الأساسي

```
https://rpc-api.svc-nue.pushwoosh.com
```

### المصادقة

يجب أن يتضمن كل طلب ترويسة `Authorization` تحتوي على [رمز Server API](/ar/developer/api-reference/api-access-token/#server-api-token) الخاص بك. يحصل الطلب برمز Device API على HTTP 403 `a device API token cannot call this method, use an account API token`.

```
Authorization: Api YOUR_API_TOKEN
```

### نقاط النهاية

تدير هذه الأساليب مخطط الـ object tags:

| الأسلوب | المسار | الوصف |
| :---- | :---- | :---- |
| `POST` | `/api/tags` | إنشاء object tag مع حقوله |
| `GET` | `/api/tags/{name}` | الحصول على object tag مع حقوله |
| `GET` | `/api/tags` | سرد الـ tags. يُعاد الـ object tag مع `fields` الخاصة به، ولا تُسرد الحقول كـ tags منفصلة |
| `POST` | `/api/tags/{name}/fields` | إضافة حقل |
| `DELETE` | `/api/tags/{name}/fields/{field}` | حذف حقل |
| `DELETE` | `/api/tags/{name}` | حذف object tag مع جميع حقوله |

يُعيد `POST /api/tags` وكلا أسلوبي الحقول الـ object tag بعد التغيير، ملفوفًا في `{"tag": {...}}`. ويُعيد `DELETE /api/tags/{name}` القيمة `{}`.

إذا لم تكن الـ object tags مُمكّنة لحسابك، يفشل `POST /api/tags` مع نوع كائن وكلا أسلوبي الحقول بالخطأ HTTP 403 `object tags are not enabled for the account`. ويُعيد `GET /api/tags/{name}` و `DELETE /api/tags/{name}` الخطأ HTTP 404 `tag not found`، ولا يسرد `GET /api/tags` الـ object tags. من دون تمكين الـ object tags لا يمكنك إنشاء أي منها، لذا لا يوجد ما تُكتب فيه القيم.

<span id="create-an-object-tag" />

### إنشاء object tag

`POST` `/api/tags`

##### نص الطلب

| الاسم | النوع | الوصف |
| :---- | :---- | :---- |
| name\* | string | اسم الـ object tag. |
| type\* | string | `OBJECT` لكائن واحد أو `OBJECT_LIST` لقائمة كائنات. |
| fields\* | array | حقول الكائن، من 1 إلى 20. |
| fields[].name\* | string | اسم الحقل. يصبح الحقل الـ tag `<name>.<fields[].name>`. |
| fields[].type\* | string | نوع الحقل: `INTEGER` أو `STRING` أو `LIST` أو `DATE` أو `BOOLEAN` أو `PRICE` أو `VERSION`. |

```json title="مثال"
{
  "name": "orders",
  "type": "OBJECT_LIST",
  "fields": [
    { "name": "amount", "type": "INTEGER" },
    { "name": "status", "type": "STRING" }
  ]
}
```

```json title="الاستجابة"
{
  "tag": {
    "name": "orders",
    "type": "OBJECT_LIST",
    "system": false,
    "user_specific": true,
    "has_right_ace_modify": true,
    "fields": [
      { "name": "amount", "type": "INTEGER" },
      { "name": "status", "type": "STRING" }
    ]
  }
}
```

يُنشأ الـ tag من نوع User-specific بغض النظر عن قيمة `user_specific`. يُعيد `GET /api/tags/{name}` الكائن نفسه من دون الغلاف `tag`. تُرتَّب الحقول حسب الاسم.

### إضافة حقل

`POST` `/api/tags/{name}/fields`

```json title="مثال: POST /api/tags/orders/fields"
{
  "field": { "name": "note", "type": "STRING" }
}
```

يمكنك كتابة الحقل الجديد فورًا كجزء من قيمة الـ tag الكاملة. تفشل إضافة الحقل إذا كان الـ object tag يحتوي بالفعل على 20 حقلًا أو إذا كان هناك tag موجود بالاسم الكامل للحقل، راجع [الأخطاء](#errors).

### حذف حقل

`DELETE` `/api/tags/{name}/fields/{field}`

على سبيل المثال، يحذف `DELETE /api/tags/orders/fields/note` الحقل `orders.note`. لا يمكنك حذف آخر حقل أو حقل قيد الاستخدام، راجع [الأخطاء](#errors).

<span id="errors" />

### الأخطاء

تأتي الأخطاء بالتنسيق `{"code": <n>, "message": "...", "details": [...]}`. عند إنشاء object tag، تبدأ رسائل الخطأ 400 بـ `validate: `.

| حالة HTTP | الرسالة | السبب |
| :---- | :---- | :---- |
| 400 | `object tag and field names must contain only letters, digits and underscores` | يحتوي الاسم على حرف آخر. |
| 400 | `an object tag needs 1 to 20 fields` | لا توجد حقول أو أكثر من 20 حقلًا عند الإنشاء. |
| 400 | `an object tag has at most 20 fields` | يحتوي الـ object tag بالفعل على 20 حقلًا. |
| 400 | `field <name> is given twice` | لحقلين الاسم نفسه، بغض النظر عن حالة الأحرف. |
| 400 | `<object>.<field>: object and field names together cannot be longer than 64 characters` | الاسم الكامل للحقل طويل جدًا. |
| 400 | `<object>.<field>: field type must be INTEGER, STRING, LIST, DATE, BOOLEAN, PRICE or VERSION` | نوع حقل غير مدعوم. |
| 400 | `an object tag needs at least one field; delete the object tag instead` | حاولت حذف آخر حقل. |
| 400 | `field is in use: ...`, `tag is in use: ...` | الحقل أو الـ object tag مستخدم في الشرائح أو الـ In-Apps أو حملات Customer Journey أو عناصر أخرى. |
| 403 | `object tags are not enabled for the account` | الـ object tags غير مُمكّنة للحساب. |
| 403 | `a device API token cannot call this method, use an account API token` | يستخدم الطلب رمز Device API. |
| 404 | `tag not found` | `GET` أو `DELETE /api/tags/{name}`: لا يوجد tag بهذا الاسم، أو الاسم لحقل، أو الـ object tags غير مُمكّنة. |
| 404 | `object tag not found`, `field not found` | أساليب الحقول: لا يوجد object tag أو حقل بهذا الاسم. |
| 409 | `tag already exists` | يوجد tag باسم الـ object tag. |
| 409 | `tag <object>.<field> already exists` | يوجد tag بالاسم الكامل للحقل. |

## كتابة القيم

اكتب قيم الـ object tags باستخدام [`/setTags`](/ar/developer/api-reference/device-api/#settags) و [`/bulkSetTags`](/ar/developer/api-reference/audience-api/#bulksettags). تحتفظ هذه الأساليب بمصادقتها الخاصة: يأخذ `/setTags` رمز Device API في الترويسة `Authorization: Token`، ويأخذ `/bulkSetTags` رمز الوصول إلى API في `auth`. أرسل قيمة `Object` ككائن JSON، وقيمة `ObjectList` كمصفوفة من الكائنات:

```json title="مثال: /json/1.3/setTags"
{
  "request": {
    "application": "XXXXX-XXXXX",
    "userId": "user_42",
    "tags": {
      "order": { "amount": 120, "status": "paid" },
      "orders": [
        { "amount": 120, "status": "paid" },
        { "amount": 50 }
      ]
    }
  }
}
```

إذا عيّنت القيمة حسب HWID، فإنها تُخزَّن لدى مستخدم ذلك الجهاز.

يأخذ كل حقل قيمة بتنسيق نوعه:

| نوع الحقل | مثال على القيمة |
| :---- | :---- |
| `INTEGER` | `120` |
| `STRING` | `"paid"` |
| `LIST` | `["gift", "express"]` |
| `DATE` | `"2026-10-02 22:11"` (UTC)، أو `"2026-10-02"`، أو طابع زمني Unix بالثواني |
| `BOOLEAN` | `true` أو `false` |
| `PRICE` | `19.95` |
| `VERSION` | `"1.0.0"` |

### الكتابة تستبدل القيمة بالكامل

تستبدل كل عملية كتابة القيمة المخزنة للـ object tag:

- يُحذف الحقل غير الموجود في القيمة الجديدة. ويُحذف أيضًا الحقل المُرسل بقيمة `null`.
- تحذف `null` أو `[]` أو `""` القيمة بالكامل.
- تحذف `{}` جميع حقول الـ tag من نوع `Object`.
- يُتجاوز المفتاح الذي ليس حقلًا في الكائن.
- إذا لم تطابق قيمة الحقل نوع الحقل، تُرفض قيمة الـ tag بالكامل وتبقى القيمة المخزنة كما هي.

لا يُبلغ `/setTags` عن القيمة المرفوضة في استجابته. تحقق من النتيجة باستخدام [`/getTags`](#read-values) أو استخدم `/bulkSetTags`، الذي يُبلغ عن نتيجة لكل tag.

### كتابة حقل واحد من Object

اكتب حقلًا واحدًا من tag من نوع `Object` باسمه الكامل. تعمل `increment` والعمليات الأخرى في [`/setTags`](/ar/developer/api-reference/device-api/#settags) على الحقول:

```json
"tags": {
  "order.status": "shipped",
  "order.amount": { "operation": "increment", "value": 5 }
}
```

لا يمكن كتابة حقل من tag من نوع `ObjectList` بمفرده، لأنه ليس من الواضح أي عنصر يجب تغييره. يتجاهل `/setTags` مثل هذه القيمة. أرسل القائمة بالكامل بدلًا من ذلك.

### لا تُنشأ الـ object tags تلقائيًا

تُتجاوز القيمة التي تحتوي على كائن أو مصفوفة كائنات لـ tag غير موجود. لا يُنشئ الإنشاء التلقائي للـ tags أي object tags، لذا أنشئ المخطط أولًا باستخدام [`POST /api/tags`](#create-an-object-tag).

### نتائج bulkSetTags

مع `detailed=true`، يُعيد [حالة `/bulkSetTags`](/ar/developer/api-reference/audience-api/#bulksettags-status) إحدى هذه النتائج للـ object tag، بالإضافة إلى `ok` و `tag not found` و `wrong value. expect :<type>`:

| النتيجة | السبب |
| :---- | :---- |
| `object tags are stored on the user only` | الـ object tag ليس من نوع User-specific. |
| `cannot load the fields of the object` | تعذّر على Pushwoosh قراءة حقول الـ object tag. |
| `wrong value. expect an object (a map) or, for a list of objects, an array of maps` | القيمة لا تناسب الـ object tag، أو قيمة الحقل لا تطابق نوعه. |
| `a field of a list of objects cannot be set on its own, set the whole list` | تُعيَّن القيمة لحقل من tag من نوع `ObjectList`. |

<span id="read-values" />

## قراءة القيم

يُعيد [`/getTags`](/ar/developer/api-reference/device-api/#gettags) قيمة `Object` ككائن JSON، وقيمة `ObjectList` كمصفوفة من الكائنات:

```json title="الاستجابة"
{
  "status_code": 200,
  "status_message": "OK",
  "response": {
    "result": {
      "order": { "amount": 120, "status": "paid" },
      "orders": [
        { "amount": 120, "status": "paid" },
        { "amount": 50 }
      ]
    }
  }
}
```

تُعاد قيم الحقول في `/getTags` بالطريقة نفسها التي تُعاد بها قيم الـ tags العادية: Date كطابع زمني Unix بالثواني، و Price كسلسلة نصية مثل `"120.00"`، و Boolean كـ `1` أو `0`.

<span id="segment-by-fields" />

## التقسيم إلى شرائح حسب الحقول

عيّن شروط الشريحة على الحقول، وليس على الـ object tag نفسه. في [لغة التجزئة](/ar/developer/api-reference/segmentation-filters-api/segmentation-language/)، الحقل هو tag باسم يحتوي على نقطة، ويأخذ عوامل نوعه الخاص:

```
AT("XXXXX-XXXXX", "order.amount", gte, 100)
```

يفشل الشرط على الـ object tag نفسه بالخطأ `object tag has no value of its own, use one of its fields`.

### الشروط على ObjectList

يتطابق الشرط على حقل من tag من نوع `ObjectList` مع المستخدم عندما يستوفي عنصر واحد على الأقل من القائمة الشرط. يجب أن تتطابق الشروط على حقول القائمة نفسها المربوطة بـ AND مع العنصر نفسه:

```
AT("XXXXX-XXXXX", "orders.amount", gte, 100) * AT("XXXXX-XXXXX", "orders.status", eq, "paid")
```

تضم هذه الشريحة المستخدمين الذين لديهم طلب واحد على الأقل تبلغ قيمته 100 أو أكثر ومدفوع في الوقت نفسه. لا يتطابق المستخدم الذي لديه طلب كبير غير مدفوع وطلب صغير مدفوع. لا يُشترط أن تتطابق الشروط المربوطة بـ OR مع العنصر نفسه. تُفحص الشروط على قائمتين مختلفتين لكل قائمة على حدة.

تعمل بعض العوامل بشكل مختلف على حقل من tag من نوع `ObjectList`:

- **`notset`.** لا يحتوي أي عنصر في القائمة على قيمة في هذا الحقل. ويتطابق أيضًا المستخدم الذي ليس لديه القائمة.
- **`noteq`.** يحتوي عنصر واحد على الأقل على قيمة في هذا الحقل، وتختلف هذه القيمة عن القيمة المحددة. لا تُحتسب العناصر التي لا تحتوي على الحقل. يتطابق المستخدم الذي لديه طلبات بالحالتين `paid` و `new` مع `noteq "paid"`.
- **`notin` على حقل من نوع List.** لا يحتوي أي عنصر على أي من القيم المحددة.
- **`notin` على حقل من نوع آخر.** يحتوي عنصر واحد على الأقل على قيمة في هذا الحقل ليست من بين القيم المحددة.

لا يرتبط `notset` و `notin` على حقل من نوع List بالعنصر نفسه الذي ترتبط به الشروط الأخرى المربوطة بـ AND.

## تصدير الشرائح مع الـ object tags

يُصدّر [`/exportSegment`](/ar/developer/api-reference/segmentation-filters-api/#exportsegment) حقول الـ object tags:

- **CSV.** كل حقل هو عمود منفصل باسم `<object>.<field>`، ولا تحصل الـ object tags نفسها على عمود. يحتوي حقل ObjectList على جميع القيم المميزة عبر العناصر كمصفوفة JSON، بالطريقة نفسها التي يعمل بها tag من نوع List: `["120","50"]`.
- **`json` و `json_each_line`.** تأتي حقول الـ tag من نوع `Object` كـ tags منفصلة باسم `<object>.<field>`. ويأتي الـ tag من نوع `ObjectList` كإدخال واحد في `tags` مع العناصر في `object_list.items`. يسرد كل عنصر حقوله بأسماء قصيرة، ويحمل كل حقل قيمته تحت مفتاح مسمى باسم نوعه: `integer` أو `string` أو `list` أو `date` أو `boolean` أو `price` أو `version`. تأتي قيم Integer كسلاسل نصية:

```json
{
  "name": "orders",
  "object_list": {
    "items": [
      { "fields": [{ "name": "amount", "integer": "120" }, { "name": "status", "string": "paid" }] },
      { "fields": [{ "name": "amount", "integer": "50" }] }
    ]
  }
}
```

إذا ذكر `tagsList` اسم object tag، تُصدَّر جميع حقوله.