# القوالب

قوالب واتساب المعتمدة: اعرف ما يحتاجه كل قالب وأنشئ قوالب جديدة.

القالب رسالة اعتمدها واتساب مسبقًا. وهو الطريقة الوحيدة لبدء محادثة أو للكتابة بعد نافذة الـ24 ساعة، لذلك تستخدمه تحديثات الطلبات والتذكيرات ورموز التحقق والحملات.

## اعرف ما يحتاجه القالب {#variables}

يعرض [`GET /templates`](/docs/reference/templates#listTemplates) قوالبك، ويوضح كل قالب ما يجب تعبئته عند الإرسال:

```json
{
  "id": "tpl_27",
  "name": "order_update",
  "language": "ar",
  "status": "approved",
  "variables": { "body": 2, "buttons": [{ "index": 0, "type": "url" }] },
  "send_example": {
    "type": "template",
    "template": {
      "name": "order_update",
      "language": "ar",
      "variables": { "body": ["value 1", "value 2"], "buttons": { "0": { "url_suffix": "value" } } }
    }
  }
}
```

`send_example` جسم جاهز لـ [`POST /messages`](/docs/reference/messages#sendMessage): أضف `to` واستبدل القيم ثم أرسل. لا يمكن إرسال إلا القوالب ذات الحالة `approved`.

## أرسل قالبًا {#send}

```json
{
  "to": "+966501234567",
  "type": "template",
  "template": {
    "name": "order_update",
    "language": "ar",
    "variables": {
      "body": ["سارة", "#10482"],
      "buttons": { "0": { "url_suffix": "10482" } }
    }
  }
}
```

| المتغير | ما يعبّئه |
|---|---|
| `body` | المتغيرات `{{1}}` و`{{2}}`… في نص القالب، بالترتيب |
| `header_text` | المتغير `{{1}}` في ترويسة نصية |
| `header_media_link` | ترويسة صورة أو فيديو أو مستند، كرابط `https://` عام |
| `buttons` | حسب ترتيب الزر: `url_suffix` (المتغير `{{1}}` في زر الرابط)، و`coupon_code` (زر نسخ الرمز)، و`payload` (زر الرد السريع) |

يُرفض العدد الخاطئ لقيم النص فورًا بالخطأ [`template_variables_mismatch`](/docs/errors#template_variables_mismatch)، بدل أن يفشل لاحقًا عند واتساب.

:::note
يُرفض القالب المرسل إلى جهة اتصال ألغت اشتراكها بالخطأ `recipient_not_consented`. أرسل `"consent_confirmed": true` فقط إن وافقت من جديد، وتُسجَّل كل موافقة في سجل التدقيق. تُستثنى قوالب التحقق (OTP): فالعميل الذي يطلب رمزًا ينتظره.
:::

## أنشئ قالبًا {#create}

يرسل [`POST /templates`](/docs/reference/templates#createTemplate) القالب إلى واتساب. يأخذ مكوّنات واتساب نفسها، ويحتاج كل متغير `{{n}}` إلى قيمة مثال:

```json
{
  "name": "order_shipped",
  "language": "ar",
  "category": "utility",
  "components": [
    {
      "type": "BODY",
      "text": "مرحبًا {{1}}، شُحن طلبك رقم {{2}} وسيصلك خلال يومين.",
      "example": { "body_text": [["سارة", "10482"]] }
    },
    {
      "type": "BUTTONS",
      "buttons": [
        { "type": "URL", "text": "تتبّع الشحنة", "url": "https://shop.example.com/track/{{1}}", "example": ["https://shop.example.com/track/10482"] }
      ]
    }
  ]
}
```

- **الفئات.** `utility` لشيء ينتظره العميل (طلب أو موعد)، و`marketing` للعروض الترويجية، و`authentication` للرموز لمرة واحدة وتأخذ `otp` بدل `components`.
- **ترويسات الوسائط.** ارفع الملف عبر [`POST /media`](/docs/reference/media#uploadMedia) وضع معرّفه `med_…` في `example.header_handle` للترويسة: نسلّمه نحن إلى واتساب، وتستخدم الإرسالات اللاحقة هذا الملف ما لم ترسل `header_media_link`.
- **الفحوص أولًا.** تُفحص صيغة الاسم (حروف صغيرة وأرقام و`_`)، وأطوال المكوّنات، وعدد الأزرار، وقائمة اللغات، وتفرّد الاسم على حساب واتساب للرقم، قبل أن يصل أي شيء إلى واتساب.

## الاعتماد {#approval}

يبدأ القالب الجديد بحالة `pending`. عادةً يقرر واتساب خلال دقائق، وأحيانًا حتى 24 ساعة، ويصلك حدث [`template.status_changed`](/docs/events#template-status_changed):

| الحالة | المعنى |
|---|---|
| `approved` | جاهز للإرسال |
| `rejected` | مرفوض، ويذكر `rejection_reason` سبب واتساب إن أعطى سببًا |
| `paused` | أوقفه واتساب مؤقتًا بعد ملاحظات سلبية |
| `disabled` | أُوقف نهائيًا |

قد ينقل واتساب قالبًا معتمدًا إلى فئة أخرى (مثلًا من utility إلى marketing)، فيتغير سعره. يعرض الحقل `category` دائمًا الفئة الحالية.

## احذف قالبًا {#delete}

يحذف [`DELETE /templates/{id}`](/docs/reference/templates#deleteTemplate) القالب هنا وفي واتساب. يُرفض ما دامت حملة مجدولة أو جارية تستخدمه. ولا يسمح واتساب باستخدام الاسم نفسه مجددًا لمدة 30 يومًا.

## عرض القوالب

```
GET https://api.saei.automize.sa/v1/templates
```

قوالب رسائل واتساب الخاصة بك. يوضّح كل قالب ما يحتاج تعبئته (`variables`) ويحمل `send_example` جاهزًا للصق في `POST /v1/messages`.

- الصلاحية: templates:read
- يعمل في وضع الاختبار

### المعاملات

- `limit` (query): عدد العناصر المطلوبة، من 1 إلى 100.
- `cursor` (query): قيمة `next_cursor` من الصفحة السابقة.
- `status` (query): 
- `category` (query): 
- `language` (query): رمز لغة، مثل `ar` أو `en_US`.
- `name` (query): اسم القالب بالضبط.

### الاستجابة 200

صفحة من القوالب.

```json
{
  "object": "list",
  "data": [
    {
      "id": "tpl_27",
      "object": "template",
      "name": "string",
      "language": "string",
      "category": "marketing",
      "status": "string",
      "rejection_reason": "string",
      "components": [],
      "variables": {
        "header": "string",
        "body": 0,
        "buttons": [
          {
            "index": null,
            "type": null
          }
        ]
      },
      "send_example": {},
      "created_at": "2026-10-01T09:30:00Z",
      "updated_at": "2026-10-01T09:30:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": "string"
}
```

### الاستجابة 401

مفتاح API مفقود أو غير صالح أو ملغى أو منتهي الصلاحية.

```json
{
  "error": {
    "type": "authentication_error",
    "code": "api_key_invalid",
    "message": "The API key is not valid.",
    "doc_url": "https://app.example.com/docs/errors#api_key_invalid",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الاستجابة 403

المفتاح ينقصه صلاحية، أو الباقة لا تشمل الوصول للواجهة، أو الطلب غير متاح في هذا الوضع.

```json
{
  "error": {
    "type": "permission_error",
    "code": "insufficient_scope",
    "message": "This API key does not have the \"messages:send\" scope. Create a key with it in Developers > API keys.",
    "required_scope": "messages:send",
    "doc_url": "https://app.example.com/docs/errors#insufficient_scope",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الأخطاء المحتملة

`parameter_invalid`, `rate_limited`

## إنشاء قالب

```
POST https://api.saei.automize.sa/v1/templates
```

يرسل قالبًا جديدًا إلى واتساب لاعتماده. يعود بحالة `pending`، وعادةً يقرر واتساب خلال دقائق (وأحيانًا حتى 24 ساعة)، ويصلك حدث `template.status_changed` عند القرار.

`components` هي مكوّنات واتساب نفسها: `HEADER` و`BODY` (إلزامي) و`FOOTER` و`BUTTONS`. يحتاج كل متغير `{{n}}` إلى قيمة `example`، وإلا رفض واتساب القالب. تُجرى فحوص منشئ القوالب أولًا (الأطوال، عدد الأزرار، قائمة اللغات، تفرّد الاسم لكل حساب واتساب)، فتعود معظم الأخطاء فورًا كـ `parameter_invalid`.

لترويسة صورة أو فيديو أو مستند، ارفع الملف عبر `POST /v1/media` وضع معرّفه `med_…` في `example.header_handle`: نسلّمه نحن إلى واتساب، ويُرسل القالب بهذا الملف افتراضيًا.

قوالب التحقق (OTP) تأخذ `otp` بدل `components`، وتحتاج باقة تشمل التحقق عبر OTP ونشاطًا تجاريًا موثّقًا من Meta.


- الصلاحية: templates:write
- لمفاتيح التشغيل فقط
- يقبل Idempotency-Key

### المعاملات

- `Idempotency-Key` (header): أي نص فريد (يُفضّل UUID). إعادة الطلب بنفس المفتاح ونفس الجسم تُرجع الاستجابة الأولى بدل التنفيذ مرتين. يُحفظ لمدة 24 ساعة.

### الطلب: تحديث طلب مع زر تتبّع

```json
{
  "name": "order_shipped",
  "language": "ar",
  "category": "utility",
  "components": [
    {
      "type": "BODY",
      "text": "مرحبًا {{1}}، شُحن طلبك رقم {{2}} وسيصلك خلال يومين.",
      "example": {
        "body_text": [
          [
            "سارة",
            "10482"
          ]
        ]
      }
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "URL",
          "text": "تتبّع الشحنة",
          "url": "https://shop.example.com/track/{{1}}",
          "example": [
            "https://shop.example.com/track/10482"
          ]
        }
      ]
    }
  ]
}
```

### الطلب: عرض مع صورة

```json
{
  "name": "weekend_offer",
  "language": "ar",
  "category": "marketing",
  "components": [
    {
      "type": "HEADER",
      "format": "IMAGE",
      "example": {
        "header_handle": [
          "med_381"
        ]
      }
    },
    {
      "type": "BODY",
      "text": "خصم {{1}} على كل الطلبات هذا الأسبوع 🎉",
      "example": {
        "body_text": [
          [
            "20٪"
          ]
        ]
      }
    },
    {
      "type": "FOOTER",
      "text": "للإلغاء أرسل \"إيقاف\""
    }
  ]
}
```

### الاستجابة 201

أُرسل إلى واتساب، والحالة `pending`.

```json
{
  "id": "tpl_27",
  "object": "template",
  "name": "string",
  "language": "string",
  "category": "marketing",
  "status": "string",
  "rejection_reason": "string",
  "components": [],
  "variables": {
    "header": "string",
    "body": 0,
    "buttons": [
      {
        "index": 0,
        "type": "string"
      }
    ]
  },
  "send_example": {},
  "created_at": "2026-10-01T09:30:00Z",
  "updated_at": "2026-10-01T09:30:00Z"
}
```

### الاستجابة 401

مفتاح API مفقود أو غير صالح أو ملغى أو منتهي الصلاحية.

```json
{
  "error": {
    "type": "authentication_error",
    "code": "api_key_invalid",
    "message": "The API key is not valid.",
    "doc_url": "https://app.example.com/docs/errors#api_key_invalid",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الاستجابة 403

المفتاح ينقصه صلاحية، أو الباقة لا تشمل الوصول للواجهة، أو الطلب غير متاح في هذا الوضع.

```json
{
  "error": {
    "type": "permission_error",
    "code": "insufficient_scope",
    "message": "This API key does not have the \"messages:send\" scope. Create a key with it in Developers > API keys.",
    "required_scope": "messages:send",
    "doc_url": "https://app.example.com/docs/errors#insufficient_scope",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الاستجابة 409

يوجد قالب بنفس الاسم واللغة على حساب واتساب لهذا الرقم.

```json
{
  "error": {
    "type": "authentication_error",
    "code": "string",
    "message": "string",
    "param": "string",
    "doc_url": "string",
    "request_id": "string",
    "details": [
      {
        "param": "string",
        "code": "string",
        "message": "string"
      }
    ],
    "channel_error": {
      "provider": "string",
      "code": 0,
      "subcode": 0,
      "title": "string",
      "message": "string"
    }
  }
}
```

### الاستجابة 422

الطلب غير صالح. يوضّح `details` كل حقل به خطأ.

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "The to field is required.",
    "param": "to",
    "details": [
      {
        "param": "to",
        "code": "parameter_missing",
        "message": "The to field is required."
      }
    ],
    "doc_url": "https://app.example.com/docs/errors#parameter_missing",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الأخطاء المحتملة

`parameter_missing`, `parameter_invalid`, `resource_exists`, `resource_missing`, `sender_not_configured`, `capability_disabled`, `channel_error`, `test_mode_unsupported`, `rate_limited`

## جلب قالب

```
GET https://api.saei.automize.sa/v1/templates/{id}
```

قالب واحد ومكوّناته كما اعتمدها واتساب، وسبب الرفض من واتساب للقالب المرفوض إن ذكره.

- الصلاحية: templates:read
- يعمل في وضع الاختبار

### المعاملات

- `id` (path, مطلوب): معرّف العنصر.

### الاستجابة 200

القالب.

```json
{
  "id": "tpl_27",
  "object": "template",
  "name": "order_update",
  "language": "ar",
  "category": "utility",
  "status": "approved",
  "rejection_reason": null,
  "components": [
    {
      "type": "BODY",
      "text": "مرحبًا {{1}}، طلبك {{2}} في الطريق."
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "URL",
          "text": "تتبّع الطلب",
          "url": "https://shop.example.com/track/{{1}}"
        }
      ]
    }
  ],
  "variables": {
    "body": 2,
    "buttons": [
      {
        "index": 0,
        "type": "url"
      }
    ]
  },
  "send_example": {
    "type": "template",
    "template": {
      "name": "order_update",
      "language": "ar",
      "variables": {
        "body": [
          "value 1",
          "value 2"
        ],
        "buttons": [
          {
            "url_suffix": "value"
          }
        ]
      }
    }
  },
  "created_at": "2026-08-01T10:00:00Z",
  "updated_at": "2026-08-02T07:30:00Z"
}
```

### الاستجابة 401

مفتاح API مفقود أو غير صالح أو ملغى أو منتهي الصلاحية.

```json
{
  "error": {
    "type": "authentication_error",
    "code": "api_key_invalid",
    "message": "The API key is not valid.",
    "doc_url": "https://app.example.com/docs/errors#api_key_invalid",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الاستجابة 403

المفتاح ينقصه صلاحية، أو الباقة لا تشمل الوصول للواجهة، أو الطلب غير متاح في هذا الوضع.

```json
{
  "error": {
    "type": "permission_error",
    "code": "insufficient_scope",
    "message": "This API key does not have the \"messages:send\" scope. Create a key with it in Developers > API keys.",
    "required_scope": "messages:send",
    "doc_url": "https://app.example.com/docs/errors#insufficient_scope",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الاستجابة 404

لا يوجد عنصر بهذا المعرّف في مساحة العمل هذه (وفي هذا الوضع).

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "resource_missing",
    "message": "No such message: msg_999.",
    "param": "id",
    "doc_url": "https://app.example.com/docs/errors#resource_missing",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الأخطاء المحتملة

`resource_missing`, `rate_limited`

## حذف قالب

```
DELETE https://api.saei.automize.sa/v1/templates/{id}
```

يحذف القالب هنا وفي واتساب. يُرفض بـ `resource_in_use` ما دامت حملة مجدولة أو جارية تستخدمه. لا يسمح واتساب بإعادة استخدام الاسم نفسه لمدة 30 يومًا.

- الصلاحية: templates:write
- لمفاتيح التشغيل فقط

### المعاملات

- `id` (path, مطلوب): معرّف العنصر.

### الاستجابة 200

تم الحذف.

```json
{
  "id": "tpl_27",
  "object": "template",
  "deleted": true
}
```

### الاستجابة 401

مفتاح API مفقود أو غير صالح أو ملغى أو منتهي الصلاحية.

```json
{
  "error": {
    "type": "authentication_error",
    "code": "api_key_invalid",
    "message": "The API key is not valid.",
    "doc_url": "https://app.example.com/docs/errors#api_key_invalid",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الاستجابة 403

المفتاح ينقصه صلاحية، أو الباقة لا تشمل الوصول للواجهة، أو الطلب غير متاح في هذا الوضع.

```json
{
  "error": {
    "type": "permission_error",
    "code": "insufficient_scope",
    "message": "This API key does not have the \"messages:send\" scope. Create a key with it in Developers > API keys.",
    "required_scope": "messages:send",
    "doc_url": "https://app.example.com/docs/errors#insufficient_scope",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الاستجابة 404

لا يوجد عنصر بهذا المعرّف في مساحة العمل هذه (وفي هذا الوضع).

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "resource_missing",
    "message": "No such message: msg_999.",
    "param": "id",
    "doc_url": "https://app.example.com/docs/errors#resource_missing",
    "request_id": "req_01j9x3k2m4n5p6q7r8s9t0v1w2"
  }
}
```

### الاستجابة 409

تستخدمه حملة مجدولة أو جارية.

```json
{
  "error": {
    "type": "authentication_error",
    "code": "string",
    "message": "string",
    "param": "string",
    "doc_url": "string",
    "request_id": "string",
    "details": [
      {
        "param": "string",
        "code": "string",
        "message": "string"
      }
    ],
    "channel_error": {
      "provider": "string",
      "code": 0,
      "subcode": 0,
      "title": "string",
      "message": "string"
    }
  }
}
```

### الأخطاء المحتملة

`resource_missing`, `resource_in_use`, `test_mode_unsupported`, `rate_limited`
