{
  "openapi": "3.1.0",
  "info": {
    "title": "Mursilat Public API v2",
    "description": "REST API to run WhatsApp numbers with Mursilat: numbers & pairing, every message type (now or scheduled), safe bulk campaigns, auto-replies, OTP, the Number Shield (health, pauses, stricter limits), statistics, groups (read) and signed webhooks.\n\n**Auth** — `Authorization: Bearer wsl_live_…` (account key from Settings → API keys: scopes, number restriction, optional IP allowlist; shown once). A number key (`x-api-key`) also works on message endpoints of its own number.\n\n**Conventions** — JSON, camelCase, ISO 8601 times. Lists: `?limit=&cursor=` → `{ data, nextCursor }`. Writes accept `Idempotency-Key` (required on sends, campaigns and OTP; replays carry `Idempotent-Replayed: true`). Errors: `{ error: { code, message, details?, docsUrl, requestId } }`. Every answer carries `X-RateLimit-Limit / Remaining / Reset` and `X-Request-Id`; 429/423 add `Retry-After`.\n\n**Safety** — every send goes through the Number Shield (warm-up caps, pacing, quiet hours for campaigns, opt-outs, content rules) and your plan quota. It lowers the risk of restrictions; nothing can promise a number is never restricted.\n\n**Privacy** — Mursilat does not store message content. No endpoint returns message content or conversation history; inbound messages reach you only through your webhook, live. Message / campaign / delivery endpoints return metadata only, and campaign content + recipients are deleted after the campaign ends.",
    "version": "2026-10",
    "contact": {},
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Mursilat"
    }
  },
  "servers": [
    {
      "url": "https://mursilat.com"
    }
  ],
  "tags": [
    {
      "name": "Account & keys",
      "description": "Create account API keys in Settings → API keys: choose scopes, numbers and optionally allowed IPs. The key is shown once.",
      "x-name-ar": "الحساب والمفاتيح",
      "x-description-ar": "اعمل مفاتيح الحساب من الإعدادات ← مفاتيح API: اختار الصلاحيات والأرقام وعناوين الـ IP المسموحة (اختياري). المفتاح بيظهر مرة واحدة بس."
    },
    {
      "name": "Numbers",
      "description": "Add numbers, pair them with a QR or a pairing code, follow their connection and manage their webhooks. Tip: a WhatsApp Business number with a real profile (name, photo, description) is trusted more by customers and by WhatsApp.",
      "x-name-ar": "الأرقام",
      "x-description-ar": "ضيف أرقام واربطها بـ QR أو بكود ربط، تابع اتصالها واضبط الويب هوك بتاعها. نصيحة: رقم واتساب بيزنس ببروفايل حقيقي (اسم وصورة ووصف) بيبقى موثوق أكتر عند العملاء وعند واتساب."
    },
    {
      "name": "Messages",
      "description": "One endpoint for every message type, now or scheduled. Every send goes through the Number Shield (warm-up caps, pacing, opt-outs, content rules) and your plan quota. Status endpoints return metadata only: the API never returns message content.",
      "x-name-ar": "الرسايل",
      "x-description-ar": "endpoint واحد لكل أنواع الرسايل، دلوقتي أو مجدولة. كل رسالة بتعدي على حماية الرقم (حدود التسخين والفواصل والإلغاء وقواعد المحتوى) ورصيد باقتك. الحالة بس: الـ API عمره ما بيرجّع محتوى الرسايل."
    },
    {
      "name": "Campaigns (bulk)",
      "description": "Send one message to many people safely: the Number Shield paces it, respects quiet hours, skips opted-out and invalid numbers and pauses on bad signals. Content and recipients are deleted automatically after the campaign ends (keep window up to 24 h); only totals remain.",
      "x-name-ar": "الحملات (إرسال جماعي)",
      "x-description-ar": "ابعت رسالة واحدة لناس كتير بأمان: حماية الرقم بتنظم السرعة وتحترم ساعات الهدوء وتتخطى الأرقام اللي لغت أو غلط وتوقف لو فيه مؤشرات وحشة. المحتوى والمستلمين بيتمسحوا لوحدهم بعد ما الحملة تخلص (لحد 24 ساعة)؛ الإجماليات بس اللي بتفضل."
    },
    {
      "name": "Auto-replies",
      "description": "Keyword (exact, contains, starts with, or a regular expression), welcome (first message) and away (outside business hours) rules per number. Opt-out keywords always win; replies go out as replies (short pacing).",
      "x-name-ar": "الردود التلقائية",
      "x-description-ar": "قواعد بالكلمات (تطابق تام، تحتوي، تبدأ بـ، أو تعبير نمطي) وترحيب (أول رسالة) وغياب (برا مواعيد العمل) لكل رقم. كلمات الإلغاء ليها الأولوية دايمًا؛ الردود بتطلع كردود (بفاصل قصير)."
    },
    {
      "name": "OTP (verification codes)",
      "description": "Mursilat generates the code, sends it from your number and keeps only a hash — the code is never returned, stored or logged. Verify with a constant-time check and limited attempts. Deliverability: send OTPs only to people who asked for them, the text is fixed and localized — only your app name is added.",
      "x-name-ar": "أكواد التحقق (OTP)",
      "x-description-ar": "مرسلات بتولّد الكود وتبعته من رقمك وبتحتفظ بالـ hash بس — الكود عمره ما بيرجع ولا بيتخزن ولا بيتكتب في اللوج. التحقق بمقارنة آمنة وعدد محاولات محدود. ابعت الكود للي طلبه بس؛ النص ثابت ومترجم وبيتضاف له اسم تطبيقك بس."
    },
    {
      "name": "Number Shield & stats",
      "description": "See how healthy a number is, pause it, make it slower than the Number Shield (never faster) and read daily statistics. No tool can promise a number is never restricted; these lower the risk.",
      "x-name-ar": "حماية الرقم والإحصائيات",
      "x-description-ar": "اعرف صحة الرقم، وقّفه، خليه أبطأ من حماية الرقم (عمرها ما تبقى أسرع)، واقرا الإحصائيات اليومية. مفيش أداة تضمن إن الرقم ميتقيدش؛ دي بتقلل الخطر."
    },
    {
      "name": "Groups",
      "description": "Read the groups of a number. Sending to groups is blocked by the Number Shield on purpose: spam reports from groups get numbers banned fastest. This is a safety decision, not a missing feature.",
      "x-name-ar": "الجروبات",
      "x-description-ar": "اقرا جروبات الرقم. الإرسال للجروبات مقفول عن قصد من حماية الرقم: البلاغات من الجروبات هي أسرع سبب لحظر الأرقام. ده قرار أمان مش ميزة ناقصة."
    },
    {
      "name": "Webhooks",
      "description": "Real-time events signed with HMAC-SHA256 (X-Wasla-Signature: t=…,v1=…), retried for about an hour. One account-level URL for all numbers, and/or one per number. The delivery log keeps metadata only (7 days).",
      "x-name-ar": "الويب هوك",
      "x-description-ar": "أحداث لحظية موقعة بـ HMAC-SHA256 (X-Wasla-Signature: t=…,v1=…) وبتتعاد لمدة حوالي ساعة. رابط واحد للحساب كله و/أو رابط لكل رقم. سجل التسليم بيحتفظ بالبيانات الوصفية بس (7 أيام)."
    },
    {
      "name": "Website button & WhatsApp links",
      "description": "A chat button for your website (one script tag) and tracked wa.me links / QR codes for ads, bios and print. Every click gets a short ref code in the prefilled text; when the visitor writes, Mursilat links the chat to the page / ad / campaign (webhook conversation.attributed). Inbound-first chats are the safest for your number. No visitor IP, cookie or full URL is stored.",
      "x-name-ar": "زرار الموقع وروابط واتساب",
      "x-description-ar": "زرار شات لموقعك (سطر واحد) وروابط wa.me متتبَّعة وأكواد QR للإعلانات والبايو والمطبوعات. كل ضغطة بتاخد كود قصير جوه الرسالة الجاهزة؛ ولما الزائر يكتب، مرسلات بتربط المحادثة بالصفحة أو الإعلان أو الحملة (ويب هوك conversation.attributed). المحادثات اللي العميل بيبدأها هي الأأمن لرقمك. مش بنخزن IP الزائر ولا كوكيز ولا الرابط كامل."
    }
  ],
  "paths": {
    "/api/v2/me": {
      "get": {
        "description": "The account and key behind this request: scopes, number restriction, rate limits. Handy as a connectivity test.",
        "operationId": "me",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "accountId": "cmv0…",
                  "keyType": "account",
                  "key": {
                    "id": "cmv7…",
                    "name": "Shop backend",
                    "prefix": "wsl_live_Ab12Cd34",
                    "expiresAt": null
                  },
                  "scopes": [
                    "messages:send",
                    "messages:read"
                  ],
                  "numbers": "ALL",
                  "clientIp": "203.0.113.10"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: API_KEY_REQUIRED, API_KEY_INVALID, IP_NOT_ALLOWED, API_ACCESS_NOT_IN_PLAN (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Who am I (connectivity test)",
        "tags": [
          "v2 · Account"
        ],
        "x-summary-ar": "مين أنا (اختبار الاتصال)",
        "x-description-ar": "بيرجع الحساب وبداية المفتاح والصلاحيات والأرقام والـ IP بتاعك زي ما مرسلات شايفاه.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/me\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/me', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/me\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/me');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers": {
      "get": {
        "description": "Scope: `numbers:read`.",
        "operationId": "numbers.list",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100 (default 25)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {}
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "CONNECTED | PAIRING | DISCONNECTED | …",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "cm1abcd2345efgh6789ijkl",
                      "name": "فرع المعادي",
                      "phone": "201001234567",
                      "status": "CONNECTED",
                      "health": {
                        "level": "good",
                        "score": 92
                      },
                      "numberStatus": "ACTIVE",
                      "warmupStage": "WEEK_2",
                      "webhook": {
                        "configured": true,
                        "version": 2,
                        "disabled": false
                      },
                      "createdAt": "2026-10-01T09:00:00.000Z",
                      "updatedAt": "2026-10-13T08:00:00.000Z"
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "List numbers",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "عرض الأرقام",
        "x-description-ar": "الأرقام اللي المفتاح ده يقدر يستخدمها، الأحدث الأول.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "post": {
        "description": "Creates a number slot (plan NUMBERS limit applies) and starts linking. Returns a QR (raw + PNG data URL) or, with pairing.method=\"code\" and the phone, an 8-character pairing code for WhatsApp → Linked devices → Link with phone number.\n\nScope: `numbers:write`.",
        "operationId": "numbers.create",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 100,
                    "example": "فرع المعادي"
                  },
                  "pairing": {
                    "type": "object",
                    "properties": {
                      "method": {
                        "type": "string",
                        "enum": [
                          "qr",
                          "code"
                        ],
                        "default": "qr"
                      },
                      "phone": {
                        "type": "string",
                        "example": "201001234567",
                        "description": "Required for method=code"
                      }
                    }
                  }
                }
              },
              "examples": {
                "numbers.create": {
                  "summary": "Add a number and start pairing",
                  "value": {
                    "name": "فرع المعادي",
                    "pairing": {
                      "method": "qr"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "number": {
                    "id": "cm1abcd2345efgh6789ijkl",
                    "name": "فرع المعادي",
                    "phone": null,
                    "status": "PAIRING",
                    "health": null,
                    "numberStatus": "ACTIVE",
                    "warmupStage": "WEEK_2",
                    "webhook": {
                      "configured": true,
                      "version": 2,
                      "disabled": false
                    },
                    "createdAt": "2026-10-01T09:00:00.000Z",
                    "updatedAt": "2026-10-13T08:00:00.000Z"
                  },
                  "pairing": {
                    "method": "qr",
                    "qr": {
                      "raw": "2@AbCdEf…",
                      "dataUrl": "data:image/png;base64,iVBORw0KGgo…"
                    },
                    "pairingCode": null,
                    "expiresAt": "2026-10-13T08:00:20.000Z",
                    "instructions": "On the phone: WhatsApp → Settings → Linked devices → Link a device, then scan."
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: PLAN_NUMBERS_LIMIT_REACHED, KEY_NUMBER_RESTRICTED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Add a number and start pairing",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "إضافة رقم وبدء الربط",
        "x-description-ar": "بيعمل رقم جديد (حسب عدد الأرقام في باقتك) ويرجّع QR (نص + صورة PNG)، أو مع pairing.method = \"code\" والرقم بيرجّع كود من 8 حروف تكتبه في واتساب.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"name\": \"فرع المعادي\",\n  \"pairing\": {\n    \"method\": \"qr\"\n  }\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"name\": \"فرع المعادي\",\n    \"pairing\": {\n      \"method\": \"qr\"\n    }\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers\",\n    headers=headers,\n    json={\n        \"name\": \"فرع المعادي\",\n        \"pairing\": {\n            \"method\": \"qr\"\n        }\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'name' => 'فرع المعادي',\n        'pairing' => [\n            'method' => 'qr'\n        ]\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}": {
      "get": {
        "description": "Scope: `numbers:read`.",
        "operationId": "numbers.get",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm1abcd2345efgh6789ijkl",
                  "name": "فرع المعادي",
                  "phone": "201001234567",
                  "status": "CONNECTED",
                  "health": {
                    "level": "good",
                    "score": 92
                  },
                  "numberStatus": "ACTIVE",
                  "warmupStage": "WEEK_2",
                  "webhook": {
                    "configured": true,
                    "version": 2,
                    "disabled": false
                  },
                  "createdAt": "2026-10-01T09:00:00.000Z",
                  "updatedAt": "2026-10-13T08:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: NUMBER_NOT_FOUND, NUMBER_NOT_ALLOWED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Get a number",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "تفاصيل رقم",
        "x-description-ar": "الحالة ومستوى الصحة ومرحلة التسخين وحالة الويب هوك.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "patch": {
        "description": "Scope: `numbers:write`.",
        "operationId": "numbers.rename",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 100
                  }
                }
              },
              "examples": {
                "numbers.rename": {
                  "summary": "Rename a number",
                  "value": {
                    "name": "فرع مدينة نصر"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm1abcd2345efgh6789ijkl",
                  "name": "فرع مدينة نصر",
                  "phone": "201001234567",
                  "status": "CONNECTED",
                  "health": {
                    "level": "good",
                    "score": 92
                  },
                  "numberStatus": "ACTIVE",
                  "warmupStage": "WEEK_2",
                  "webhook": {
                    "configured": true,
                    "version": 2,
                    "disabled": false
                  },
                  "createdAt": "2026-10-01T09:00:00.000Z",
                  "updatedAt": "2026-10-13T08:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Rename a number",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "تغيير اسم الرقم",
        "x-description-ar": "الاسم جوه مرسلات بس.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PATCH \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"name\": \"فرع مدينة نصر\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl', {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"name\": \"فرع مدينة نصر\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.patch(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl\",\n    headers=headers,\n    json={\n        \"name\": \"فرع مدينة نصر\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PATCH',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'name' => 'فرع مدينة نصر'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "delete": {
        "description": "Scope: `numbers:write`.",
        "operationId": "numbers.delete",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confirm",
            "required": true,
            "in": "query",
            "description": "Must equal the number id",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm1abcd2345efgh6789ijkl",
                  "deleted": true
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CONFIRMATION_REQUIRED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Delete a number",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "حذف رقم",
        "x-description-ar": "نهائي. بيفضّي مكان في باقتك.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl?confirm=cm1abcd2345efgh6789ijkl\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl?confirm=cm1abcd2345efgh6789ijkl', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl?confirm=cm1abcd2345efgh6789ijkl\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl?confirm=cm1abcd2345efgh6789ijkl');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/status": {
      "get": {
        "description": "Scope: `numbers:read`.",
        "operationId": "numbers.status",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm1abcd2345efgh6789ijkl",
                  "status": "CONNECTED",
                  "running": true,
                  "connected": true,
                  "phone": "201001234567",
                  "updatedAt": "2026-10-13T08:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Connection status",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "حالة الاتصال",
        "x-description-ar": "حالة اتصال الرقم دلوقتي.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/status\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/status', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/status\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/status');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/qr": {
      "get": {
        "description": "The QR links a device to the number: treat it as a secret (scope numbers:write).\n\nScope: `numbers:write`.",
        "operationId": "numbers.qr",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "method": "qr",
                  "qr": {
                    "raw": "2@AbCdEf…",
                    "dataUrl": "data:image/png;base64,iVBORw0KGgo…"
                  },
                  "pairingCode": null,
                  "expiresAt": "2026-10-13T08:00:20.000Z",
                  "instructions": "On the phone: WhatsApp → Settings → Linked devices → Link a device, then scan."
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: NUMBER_ALREADY_CONNECTED, NUMBER_NOT_PAIRING (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Current QR",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "الـ QR الحالي",
        "x-description-ar": "الـ QR بيتغير كل حوالي 20 ثانية؛ هاته تاني بعد expiresAt.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/qr\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/qr', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/qr\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/qr');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/pairing-code": {
      "post": {
        "description": "Scope: `numbers:write`.",
        "operationId": "numbers.pairingCode",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone"
                ],
                "properties": {
                  "phone": {
                    "type": "string",
                    "example": "201001234567"
                  }
                }
              },
              "examples": {
                "numbers.pairingCode": {
                  "summary": "Pairing code (no QR)",
                  "value": {
                    "phone": "201001234567"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "method": "code",
                  "qr": null,
                  "pairingCode": "K7Q2M9XD",
                  "expiresAt": "2026-10-13T08:02:00.000Z",
                  "instructions": "…"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: NUMBER_NOT_PAIRING, PAIRING_CODE_UNAVAILABLE, PAIRING_CODE_FAILED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Pairing code (no QR)",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "كود ربط (من غير QR)",
        "x-description-ar": "للسيرفرات اللي من غير شاشة: واتساب ← الأجهزة المرتبطة ← الربط برقم الهاتف، واكتب الكود.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/pairing-code\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"phone\": \"201001234567\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/pairing-code', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"phone\": \"201001234567\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/pairing-code\",\n    headers=headers,\n    json={\n        \"phone\": \"201001234567\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/pairing-code');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'phone' => '201001234567'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/reconnect": {
      "post": {
        "description": "Starts the number on the server. Paired numbers reconnect without a QR; unpaired ones return a fresh QR.\n\nScope: `numbers:write`.",
        "operationId": "numbers.reconnect",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm1abcd2345efgh6789ijkl",
                  "status": "CONNECTING",
                  "running": true,
                  "connected": false,
                  "phone": "201001234567",
                  "updatedAt": "…",
                  "pairing": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: NUMBER_BANNED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Reconnect",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "إعادة الاتصال",
        "x-description-ar": "الأرقام المربوطة بترجع من غير QR؛ اللي مش مربوطة بيرجعلها QR جديد.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/reconnect\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/reconnect', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/reconnect\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/reconnect');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/logout": {
      "post": {
        "description": "Scope: `numbers:write`.",
        "operationId": "numbers.logout",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm1abcd2345efgh6789ijkl",
                  "status": "LOGGED_OUT",
                  "running": false,
                  "connected": false,
                  "phone": "201001234567",
                  "updatedAt": "…"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Log out (unlink)",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "تسجيل خروج (فك الربط)",
        "x-description-ar": "بيفك ربط الجهاز ويمسح بياناته. لازم تربطه تاني.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/logout\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/logout', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/logout\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/logout');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/webhook": {
      "get": {
        "description": "Scope: `webhooks:read`.",
        "operationId": "numbers.webhook.get",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "url": "https://example.com/mursilat",
                  "version": 2,
                  "events": [
                    "message.received",
                    "message.status",
                    "interactive.reply"
                  ],
                  "availableEvents": [
                    "message.received",
                    "message.status",
                    "interactive.reply",
                    "poll.vote",
                    "contact.opted_out",
                    "contact.opted_in",
                    "session.status",
                    "number.status",
                    "number.restricted",
                    "campaign.status",
                    "otp.verified",
                    "conversation.attributed"
                  ],
                  "secretConfigured": true,
                  "disabledAt": null,
                  "disabledReason": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Webhook of a number",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "ويب هوك الرقم",
        "x-description-ar": "الرابط والأحداث والحالة.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "put": {
        "description": "Public https URL only (SSRF guard: DNS checked, private / internal addresses refused, ports 443/80). The signing secret is returned once, the first time a webhook is set; later use rotate-secret.\n\nScope: `webhooks:write`.",
        "operationId": "numbers.webhook.put",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "example": "https://example.com/mursilat/webhook"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Omit for all events"
                  },
                  "version": {
                    "type": "integer",
                    "enum": [
                      2
                    ],
                    "default": 2
                  }
                }
              },
              "examples": {
                "numbers.webhook.put": {
                  "summary": "Set the webhook of a number",
                  "value": {
                    "url": "https://example.com/mursilat",
                    "events": [
                      "message.received",
                      "message.status",
                      "interactive.reply"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "url": "https://example.com/mursilat",
                  "version": 2,
                  "events": [
                    "message.received",
                    "message.status",
                    "interactive.reply"
                  ],
                  "availableEvents": [
                    "message.received",
                    "message.status",
                    "interactive.reply",
                    "poll.vote",
                    "contact.opted_out",
                    "contact.opted_in",
                    "session.status",
                    "number.status",
                    "number.restricted",
                    "campaign.status",
                    "otp.verified",
                    "conversation.attributed"
                  ],
                  "secretConfigured": true,
                  "disabledAt": null,
                  "disabledReason": null,
                  "secret": "whsec_…(shown once)"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: URL_PRIVATE_ADDRESS, URL_PORT_NOT_ALLOWED, WEBHOOKS_NOT_IN_PLAN, WEBHOOK_EVENTS_INVALID (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Set the webhook of a number",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "ضبط ويب هوك الرقم",
        "x-description-ar": "رابط https عام بس (العناوين الداخلية مرفوضة). مفتاح التوقيع بيرجع مرة واحدة.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PUT \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"url\": \"https://example.com/mursilat\",\n  \"events\": [\n    \"message.received\",\n    \"message.status\",\n    \"interactive.reply\"\n  ]\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook', {\n  method: 'PUT',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"url\": \"https://example.com/mursilat\",\n    \"events\": [\n      \"message.received\",\n      \"message.status\",\n      \"interactive.reply\"\n    ]\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.put(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook\",\n    headers=headers,\n    json={\n        \"url\": \"https://example.com/mursilat\",\n        \"events\": [\n            \"message.received\",\n            \"message.status\",\n            \"interactive.reply\"\n        ]\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PUT',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'url' => 'https://example.com/mursilat',\n        'events' => [\n            'message.received',\n            'message.status',\n            'interactive.reply'\n        ]\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "delete": {
        "description": "Scope: `webhooks:write`.",
        "operationId": "numbers.webhook.delete",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "url": null,
                  "version": 2,
                  "events": [
                    "message.received",
                    "message.status",
                    "interactive.reply"
                  ],
                  "availableEvents": [
                    "message.received",
                    "message.status",
                    "interactive.reply",
                    "poll.vote",
                    "contact.opted_out",
                    "contact.opted_in",
                    "session.status",
                    "number.status",
                    "number.restricted",
                    "campaign.status",
                    "otp.verified",
                    "conversation.attributed"
                  ],
                  "secretConfigured": true,
                  "disabledAt": null,
                  "disabledReason": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Remove the webhook of a number",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "إزالة ويب هوك الرقم",
        "x-description-ar": "المحاولات المعلقة للرابط القديم بتتلغي.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/webhook/test": {
      "post": {
        "description": "Scope: `webhooks:write`.",
        "operationId": "numbers.webhook.test",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "eventId": "evt_…",
                  "deliveryId": "dlv_…",
                  "status": "PENDING"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Send a test event",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "إرسال حدث تجريبي",
        "x-description-ar": "بيبعت webhook.test؛ تابع سجل التسليم.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook/test\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook/test', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook/test\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook/test');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/webhook/rotate-secret": {
      "post": {
        "description": "Scope: `webhooks:write`.",
        "operationId": "numbers.webhook.rotate",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "secret": "whsec_…"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Rotate the signing secret",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "تغيير مفتاح التوقيع",
        "x-description-ar": "المفتاح الجديد بيظهر مرة واحدة والقديم بيقف فورًا.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook/rotate-secret\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook/rotate-secret', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook/rotate-secret\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/webhook/rotate-secret');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/contacts/check": {
      "post": {
        "description": "Answers from a 30-day cache first, then live lookups within the per-minute budget of the number (protects it from looking like a scraper). More than 50 → 422; for big lists create a campaign (it checks in safe batches).\n\nScope: `numbers:read`.",
        "operationId": "numbers.contactsCheck",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phones"
                ],
                "properties": {
                  "phones": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 50
                  }
                }
              },
              "examples": {
                "numbers.contactsCheck": {
                  "summary": "Check numbers on WhatsApp (1–50)",
                  "value": {
                    "phones": [
                      "201001234567",
                      "966501234567"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "input": "201001234567",
                      "phone": "201001234567",
                      "onWhatsApp": true,
                      "jid": "201001234567@s.whatsapp.net",
                      "status": "ON_WHATSAPP"
                    }
                  ],
                  "checked": 1,
                  "fromCache": 1,
                  "unknown": 0
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CONTACT_CHECK_TOO_MANY (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Check numbers on WhatsApp (1–50)",
        "tags": [
          "v2 · Numbers"
        ],
        "x-summary-ar": "التأكد إن الأرقام عليها واتساب (1–50)",
        "x-description-ar": "من الكاش الأول (30 يوم) وبعدين بحث مباشر في حدود كل دقيقة عشان نحمي رقمك.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/contacts/check\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"phones\": [\n    \"201001234567\",\n    \"966501234567\"\n  ]\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/contacts/check', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"phones\": [\n      \"201001234567\",\n      \"966501234567\"\n    ]\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/contacts/check\",\n    headers=headers,\n    json={\n        \"phones\": [\n            \"201001234567\",\n            \"966501234567\"\n        ]\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/contacts/check');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'phones' => [\n            '201001234567',\n            '966501234567'\n        ]\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/webhooks/events": {
      "get": {
        "description": "Scope: `webhooks:read`.",
        "operationId": "webhooks.events",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "type": "campaign.status",
                      "description": "A campaign started, paused, resumed, completed, failed or was cancelled (with reason)."
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Event catalog",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "قائمة الأحداث",
        "x-description-ar": "كل أنواع الأحداث مع وصف.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/webhooks/events\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhooks/events', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/webhooks/events\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhooks/events');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/webhook": {
      "get": {
        "description": "Scope: `webhooks:read`.",
        "operationId": "webhook.get",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "url": "https://example.com/mursilat",
                  "events": [
                    "message.received",
                    "message.status",
                    "interactive.reply",
                    "poll.vote",
                    "contact.opted_out",
                    "contact.opted_in",
                    "session.status",
                    "number.status",
                    "number.restricted",
                    "campaign.status",
                    "otp.verified",
                    "conversation.attributed"
                  ],
                  "availableEvents": [
                    "message.received",
                    "message.status",
                    "interactive.reply",
                    "poll.vote",
                    "contact.opted_out",
                    "contact.opted_in",
                    "session.status",
                    "number.status",
                    "number.restricted",
                    "campaign.status",
                    "otp.verified",
                    "conversation.attributed"
                  ],
                  "secretConfigured": true,
                  "disabledAt": null,
                  "disabledReason": null,
                  "apiVersion": "2026-10"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Account webhook",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "ويب هوك الحساب",
        "x-description-ar": "رابط واحد لكل الأرقام.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/webhook\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhook', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/webhook\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhook');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "put": {
        "description": "Receives the events of every number of the account, in addition to per-number webhooks (same envelope and event id). Public https URL only (SSRF guard). The signing secret is returned once when the webhook is first created.\n\nScope: `webhooks:write`.",
        "operationId": "webhook.put",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "example": "https://example.com/mursilat"
                  },
                  "events": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "examples": {
                "webhook.put": {
                  "summary": "Set the account webhook",
                  "value": {
                    "url": "https://example.com/mursilat",
                    "events": null
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "url": "https://example.com/mursilat",
                  "events": [
                    "message.received",
                    "message.status",
                    "interactive.reply",
                    "poll.vote",
                    "contact.opted_out",
                    "contact.opted_in",
                    "session.status",
                    "number.status",
                    "number.restricted",
                    "campaign.status",
                    "otp.verified",
                    "conversation.attributed"
                  ],
                  "secretConfigured": true,
                  "secret": "whsec_…(shown once)"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: URL_PRIVATE_ADDRESS, URL_PORT_NOT_ALLOWED, WEBHOOK_EVENTS_INVALID, KEY_NUMBER_RESTRICTED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Set the account webhook",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "ضبط ويب هوك الحساب",
        "x-description-ar": "رابط https عام (متشيك ضد SSRF). المفتاح بيرجع مرة واحدة عند الإنشاء.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PUT \"https://mursilat.com/api/v2/webhook\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"url\": \"https://example.com/mursilat\",\n  \"events\": null\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhook', {\n  method: 'PUT',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"url\": \"https://example.com/mursilat\",\n    \"events\": null\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.put(\n    \"https://mursilat.com/api/v2/webhook\",\n    headers=headers,\n    json={\n        \"url\": \"https://example.com/mursilat\",\n        \"events\": None\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhook');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PUT',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'url' => 'https://example.com/mursilat',\n        'events' => null\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "delete": {
        "description": "Scope: `webhooks:write`.",
        "operationId": "webhook.delete",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "deleted": true
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Remove the account webhook",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "إزالة ويب هوك الحساب",
        "x-description-ar": "المحاولات المنتظرة بتتلغي.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/webhook\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhook', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/webhook\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhook');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/webhook/test": {
      "post": {
        "description": "Scope: `webhooks:write`.",
        "operationId": "webhook.test",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "numberId": {
                    "type": "string"
                  }
                }
              },
              "examples": {
                "webhook.test": {
                  "summary": "Send a test event",
                  "value": {
                    "numberId": "cm1abcd2345efgh6789ijkl"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "eventId": "evt_…",
                  "deliveryId": "dlv_…",
                  "status": "PENDING"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Send a test event",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "إرسال حدث تجريبي",
        "x-description-ar": "webhook.test لويب هوك الحساب.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/webhook/test\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"numberId\": \"cm1abcd2345efgh6789ijkl\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhook/test', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"numberId\": \"cm1abcd2345efgh6789ijkl\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/webhook/test\",\n    headers=headers,\n    json={\n        \"numberId\": \"cm1abcd2345efgh6789ijkl\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhook/test');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'numberId' => 'cm1abcd2345efgh6789ijkl'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/webhook/rotate-secret": {
      "post": {
        "description": "Scope: `webhooks:write`.",
        "operationId": "webhook.rotate",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "secret": "whsec_…"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Rotate the account webhook secret",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "تغيير مفتاح ويب هوك الحساب",
        "x-description-ar": "بيظهر مرة واحدة.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/webhook/rotate-secret\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhook/rotate-secret', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/webhook/rotate-secret\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhook/rotate-secret');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/webhooks/deliveries": {
      "get": {
        "description": "Every delivery of the last 7 days to your webhooks: status, attempts, HTTP status, timing. Event payloads are never returned (they may contain customer messages).\n\nScope: `webhooks:read`.",
        "operationId": "deliveries.list",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100 (default 25)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {}
          },
          {
            "name": "numberId",
            "required": false,
            "in": "query",
            "description": "Only this number",
            "schema": {}
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "PENDING,RETRYING,SUCCEEDED,FAILED,CANCELLED (comma list)",
            "schema": {}
          },
          {
            "name": "type",
            "required": false,
            "in": "query",
            "description": "Event type",
            "schema": {}
          },
          {
            "name": "eventId",
            "required": false,
            "in": "query",
            "description": "evt_…",
            "schema": {}
          },
          {
            "name": "target",
            "required": false,
            "in": "query",
            "description": "account | number",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "dlv_3c1f0a9b8e7d6c5b4a392817",
                      "eventId": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                      "type": "message.status",
                      "numberId": "cm1abcd2345efgh6789ijkl",
                      "target": "account",
                      "url": "https://example.com/mursilat",
                      "status": "SUCCEEDED",
                      "attempt": 1,
                      "maxAttempts": 6,
                      "httpStatus": 200,
                      "durationMs": 143,
                      "error": null,
                      "nextRetryAt": null,
                      "isTest": false,
                      "redeliveryOf": null,
                      "createdAt": "2026-10-13T08:00:00.000Z",
                      "updatedAt": "2026-10-13T08:00:00.200Z"
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Delivery log",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "سجل التسليم",
        "x-description-ar": "بيانات وصفية بس — محتوى الأحداث مش بيرجع.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/webhooks/deliveries?status=FAILED\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhooks/deliveries?status=FAILED', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/webhooks/deliveries?status=FAILED\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhooks/deliveries?status=FAILED');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/webhooks/deliveries/{deliveryId}": {
      "get": {
        "description": "Scope: `webhooks:read`.",
        "operationId": "deliveries.get",
        "parameters": [
          {
            "name": "deliveryId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "dlv_3c1f0a9b8e7d6c5b4a392817",
                  "eventId": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                  "type": "message.status",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "target": "account",
                  "url": "https://example.com/mursilat",
                  "status": "SUCCEEDED",
                  "attempt": 1,
                  "maxAttempts": 6,
                  "httpStatus": 200,
                  "durationMs": 143,
                  "error": null,
                  "nextRetryAt": null,
                  "isTest": false,
                  "redeliveryOf": null,
                  "createdAt": "2026-10-13T08:00:00.000Z",
                  "updatedAt": "2026-10-13T08:00:00.200Z",
                  "attempts": [
                    {
                      "attempt": 1,
                      "at": "…",
                      "httpStatus": 200,
                      "durationMs": 143,
                      "error": null
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "One delivery",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "تسليم واحد",
        "x-description-ar": "مع كل محاولة (الوقت وكود HTTP والمدة والخطأ).",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/webhooks/deliveries/dlv_3c1f0a9b8e7d6c5b4a392817\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhooks/deliveries/dlv_3c1f0a9b8e7d6c5b4a392817', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/webhooks/deliveries/dlv_3c1f0a9b8e7d6c5b4a392817\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhooks/deliveries/dlv_3c1f0a9b8e7d6c5b4a392817');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/webhooks/deliveries/{deliveryId}/redeliver": {
      "post": {
        "description": "Sends the same event (same id) again as a new delivery. Possible only while the payload still exists — about one hour after the event (zero retention).\n\nScope: `webhooks:write`.",
        "operationId": "deliveries.redeliver",
        "parameters": [
          {
            "name": "deliveryId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "dlv_3c1f0a9b8e7d6c5b4a392817",
                  "eventId": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                  "type": "message.status",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "target": "account",
                  "url": "https://example.com/mursilat",
                  "status": "PENDING",
                  "attempt": 1,
                  "maxAttempts": 6,
                  "httpStatus": 200,
                  "durationMs": 143,
                  "error": null,
                  "nextRetryAt": null,
                  "isTest": false,
                  "redeliveryOf": "dlv_3c1f0a9b8e7d6c5b4a392817",
                  "createdAt": "2026-10-13T08:00:00.000Z",
                  "updatedAt": "2026-10-13T08:00:00.200Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: DELIVERY_PAYLOAD_EXPIRED, WEBHOOK_DISABLED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Redeliver (retry window)",
        "tags": [
          "v2 · Webhooks"
        ],
        "x-summary-ar": "إعادة الإرسال (خلال فترة المحاولات)",
        "x-description-ar": "نفس id الحدث؛ متاح لحوالي ساعة بعد الحدث.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/webhooks/deliveries/dlv_3c1f0a9b8e7d6c5b4a392817/redeliver\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/webhooks/deliveries/dlv_3c1f0a9b8e7d6c5b4a392817/redeliver', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/webhooks/deliveries/dlv_3c1f0a9b8e7d6c5b4a392817/redeliver\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/webhooks/deliveries/dlv_3c1f0a9b8e7d6c5b4a392817/redeliver');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/messages": {
      "post": {
        "description": "Same message model as v1 (text, image, video/GIF/video note, audio, voice, document, sticker, location, contact, poll, event, buttons, list, cta_url) plus `numberId` and optional `scheduleAt` (ISO, 1 min – 30 days ahead; scheduled media must use media.url). Scheduling is available on request: it is off by default and answers 422 SCHEDULING_DISABLED until enabled for the platform. Every send goes through the Number Shield, plan quota and the suppression list. Legacy number keys (x-api-key) may send from their own number.\n\nScope: `messages:send`.",
        "operationId": "messages.send",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "numberId",
                  "to",
                  "type"
                ],
                "properties": {
                  "numberId": {
                    "type": "string"
                  },
                  "to": {
                    "type": "string",
                    "example": "201001234567"
                  },
                  "type": {
                    "type": "string",
                    "example": "text"
                  },
                  "text": {
                    "type": "string",
                    "example": "طلبك اتشحن 🚚"
                  },
                  "reference": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "scheduleAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "additionalProperties": true
              },
              "examples": {
                "messages.send": {
                  "summary": "Send a message (any type)",
                  "value": {
                    "numberId": "cm1abcd2345efgh6789ijkl",
                    "to": "201001234567",
                    "type": "text",
                    "text": "طلبك اتشحن 🚚 *شكرًا*",
                    "reference": "order-1042"
                  }
                },
                "messages.schedule": {
                  "summary": "Schedule a message",
                  "value": {
                    "numberId": "cm1abcd2345efgh6789ijkl",
                    "to": "201001234567",
                    "type": "text",
                    "text": "تذكير بموعدك بكرة الساعة 5",
                    "scheduleAt": "2026-10-14T13:00:00+02:00"
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "numberId": {
                    "type": "string"
                  },
                  "to": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string"
                  },
                  "caption": {
                    "type": "string"
                  },
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "3EB0A1B2C3D4E5F60718",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "status": "sent",
                  "type": "text",
                  "reference": "order-1042",
                  "scheduledAt": null,
                  "interactionId": null,
                  "format": null,
                  "fallbackIncluded": null,
                  "estimatedDelayMs": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: NUMBER_ID_REQUIRED, INVALID_RECIPIENT, MESSAGE_TYPE_NOT_SUPPORTED, SAFETY_DAILY_CAP_REACHED, SAFETY_PACING, SAFETY_SUPPRESSED, MESSAGES_QUOTA_EXCEEDED, SCHEDULE_AT_INVALID, IDEMPOTENCY_KEY_REQUIRED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          },
          {
            "x-api-key": []
          }
        ],
        "summary": "Send a message (any type)",
        "tags": [
          "v2 · Messages"
        ],
        "x-summary-ar": "إرسال رسالة (أي نوع)",
        "x-description-ar": "الأنواع: نص، صورة، فيديو (GIF / فيديو دائري)، صوت، رسالة صوتية، ملف، ستيكر، موقع، جهة اتصال، استطلاع، حدث، أزرار، قائمة، زرار رابط. الجدولة (scheduleAt) متاحة عند الطلب — شوف جدولة رسالة.",
        "x-idempotency": "required",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/messages\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n  \"to\": \"201001234567\",\n  \"type\": \"text\",\n  \"text\": \"طلبك اتشحن 🚚 *شكرًا*\",\n  \"reference\": \"order-1042\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/messages', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n    \"to\": \"201001234567\",\n    \"type\": \"text\",\n    \"text\": \"طلبك اتشحن 🚚 *شكرًا*\",\n    \"reference\": \"order-1042\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/messages\",\n    headers=headers,\n    json={\n        \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n        \"to\": \"201001234567\",\n        \"type\": \"text\",\n        \"text\": \"طلبك اتشحن 🚚 *شكرًا*\",\n        \"reference\": \"order-1042\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/messages');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'numberId' => 'cm1abcd2345efgh6789ijkl',\n        'to' => '201001234567',\n        'type' => 'text',\n        'text' => 'طلبك اتشحن 🚚 *شكرًا*',\n        'reference' => 'order-1042'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "get": {
        "description": "Never returns message content. Kept 30 days.\n\nScope: `messages:read`.",
        "operationId": "messages.list",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100 (default 25)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {}
          },
          {
            "name": "numberId",
            "required": false,
            "in": "query",
            "description": "Only this number",
            "schema": {}
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "scheduled|queued|sent|delivered|read|failed|cancelled",
            "schema": {}
          },
          {
            "name": "reference",
            "required": false,
            "in": "query",
            "description": "Your reference",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "3EB0A1B2C3D4E5F60718",
                      "numberId": "cm1abcd2345efgh6789ijkl",
                      "type": "text",
                      "reference": "order-1042",
                      "to": "2010****4567",
                      "status": "read",
                      "scheduledAt": null,
                      "error": null,
                      "interactionId": null,
                      "timeline": [
                        {
                          "status": "queued",
                          "at": "2026-10-13T08:00:00.000Z"
                        },
                        {
                          "status": "sent",
                          "at": "2026-10-13T08:00:01.200Z"
                        },
                        {
                          "status": "delivered",
                          "at": "2026-10-13T08:00:02.900Z"
                        },
                        {
                          "status": "read",
                          "at": "2026-10-13T08:03:10.000Z"
                        }
                      ],
                      "createdAt": "2026-10-13T08:00:00.000Z",
                      "updatedAt": "2026-10-13T08:03:10.000Z"
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          },
          {
            "x-api-key": []
          }
        ],
        "summary": "List sent messages (status only)",
        "tags": [
          "v2 · Messages"
        ],
        "x-summary-ar": "الرسايل المبعوتة (الحالة بس)",
        "x-description-ar": "الرسايل اللي اتبعتت بـ API v2 آخر 30 يوم — من غير محتوى.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/messages?reference=order-1042\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/messages?reference=order-1042', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/messages?reference=order-1042\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/messages?reference=order-1042');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/media": {
      "post": {
        "description": "multipart `file` (≤100 MB) or JSON {\"url\": \"https://…\"} + `numberId`. Returns a media id valid 24 h for `media: {\"id\": …}` on the same number. Bytes are kept only until sent / expired.\n\nScope: `messages:send`.",
        "operationId": "media.upload",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "mediaId": "med_8f2c1d9a7b3e4f56a1b2c3d4",
                  "mimeType": "image/png",
                  "size": 48213,
                  "fileName": "logo.png",
                  "expiresAt": "2026-10-14T08:00:00.000Z",
                  "numberId": "cm1abcd2345efgh6789ijkl"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: MESSAGE_MEDIA_REQUIRED, MESSAGE_MEDIA_TOO_LARGE, MESSAGE_MEDIA_FETCH_FAILED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          },
          {
            "x-api-key": []
          }
        ],
        "summary": "Upload media once, send many times",
        "tags": [
          "v2 · Messages"
        ],
        "x-summary-ar": "ارفع الميديا مرة وابعتها كذا مرة",
        "x-description-ar": "بيرجع media id صالح 24 ساعة على نفس الرقم. بيقبل كمان JSON فيه url.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/media\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -F numberId=\"cm1abcd2345efgh6789ijkl\" \\\n  -F file=@logo.png"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "import fs from 'node:fs';\n\nconst form = new FormData();\nform.append('numberId', \"cm1abcd2345efgh6789ijkl\");\nform.append('file', new Blob([fs.readFileSync('logo.png')]), 'logo.png');\n\nconst res = await fetch('https://mursilat.com/api/v2/media', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n  body: form,\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/media\",\n    headers=headers,\n    data={\n        \"numberId\": \"cm1abcd2345efgh6789ijkl\"\n    },\n    files={\"file\": open(\"logo.png\", \"rb\")},\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/media');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n    CURLOPT_POSTFIELDS => [\n        'numberId' => 'cm1abcd2345efgh6789ijkl',\n        'file' => new CURLFile('logo.png')\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "numberId": {
                    "type": "string"
                  },
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/messages/{messageId}": {
      "get": {
        "description": "queued → sent → delivered → read, or failed (with the error code). Metadata only — never content.\n\nScope: `messages:read`.",
        "operationId": "messages.get",
        "parameters": [
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "description": "The id returned by POST /v2/messages",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "3EB0A1B2C3D4E5F60718",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "type": "text",
                  "reference": "order-1042",
                  "to": "2010****4567",
                  "status": "read",
                  "scheduledAt": null,
                  "error": null,
                  "interactionId": null,
                  "timeline": [
                    {
                      "status": "queued",
                      "at": "2026-10-13T08:00:00.000Z"
                    },
                    {
                      "status": "sent",
                      "at": "2026-10-13T08:00:01.200Z"
                    },
                    {
                      "status": "delivered",
                      "at": "2026-10-13T08:00:02.900Z"
                    },
                    {
                      "status": "read",
                      "at": "2026-10-13T08:03:10.000Z"
                    }
                  ],
                  "createdAt": "2026-10-13T08:00:00.000Z",
                  "updatedAt": "2026-10-13T08:03:10.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: MESSAGE_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          },
          {
            "x-api-key": []
          }
        ],
        "summary": "Message status timeline",
        "tags": [
          "v2 · Messages"
        ],
        "x-summary-ar": "مراحل حالة الرسالة",
        "x-description-ar": "queued → sent → delivered → read أو failed مع كود الخطأ.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "patch": {
        "description": "Scope: `messages:send`.",
        "operationId": "messages.edit",
        "parameters": [
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "numberId": {
                    "type": "string"
                  }
                }
              },
              "examples": {
                "messages.edit": {
                  "summary": "Edit a sent text (≤15 min)",
                  "value": {
                    "text": "الموعد اتغير لـ 5 مساءً"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "messageId": "3EB0A1B2C3D4E5F60718",
                  "action": "edit"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: MESSAGE_NOT_EDITABLE, MESSAGE_EDIT_WINDOW_PASSED, MESSAGE_NOT_SENT_YET (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          },
          {
            "x-api-key": []
          }
        ],
        "summary": "Edit a sent text (≤15 min)",
        "tags": [
          "v2 · Messages"
        ],
        "x-summary-ar": "تعديل رسالة نصية (خلال 15 دقيقة)",
        "x-description-ar": "رسايلك النصية بس؛ النص الجديد بيعدي على قواعد المحتوى.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PATCH \"https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"text\": \"الموعد اتغير لـ 5 مساءً\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718', {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"text\": \"الموعد اتغير لـ 5 مساءً\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.patch(\n    \"https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718\",\n    headers=headers,\n    json={\n        \"text\": \"الموعد اتغير لـ 5 مساءً\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PATCH',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'text' => 'الموعد اتغير لـ 5 مساءً'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "delete": {
        "description": "Scope: `messages:send`.",
        "operationId": "messages.delete",
        "parameters": [
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "forEveryone",
            "required": false,
            "in": "query",
            "description": "true (default) | false = delete for me",
            "schema": {}
          },
          {
            "name": "numberId",
            "required": false,
            "in": "query",
            "description": "For messages not sent through v2",
            "schema": {}
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "messageId": "3EB0A1B2C3D4E5F60718",
                  "action": "delete",
                  "forEveryone": true
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: MESSAGE_NOT_DELETABLE, MESSAGE_DELETE_WINDOW_PASSED, MESSAGE_NOT_CANCELLABLE (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          },
          {
            "x-api-key": []
          }
        ],
        "summary": "Delete — or cancel a scheduled message",
        "tags": [
          "v2 · Messages"
        ],
        "x-summary-ar": "حذف — أو إلغاء رسالة مجدولة",
        "x-description-ar": "الرسالة المجدولة بتتلغي ونسختها بتتمسح.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718?forEveryone=true\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718?forEveryone=true', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718?forEveryone=true\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718?forEveryone=true');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/messages/{messageId}/reactions": {
      "post": {
        "description": "Any message of the number (sent or received). For messages not sent through v2, pass numberId.\n\nScope: `messages:send`.",
        "operationId": "messages.react",
        "parameters": [
          {
            "name": "messageId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "emoji"
                ],
                "properties": {
                  "emoji": {
                    "type": "string",
                    "example": "👍"
                  },
                  "numberId": {
                    "type": "string"
                  }
                }
              },
              "examples": {
                "messages.react": {
                  "summary": "React to a message",
                  "value": {
                    "emoji": "👍"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "messageId": "3EB0A1B2C3D4E5F60718",
                  "action": "react",
                  "emoji": "👍"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: MESSAGE_REACTION_INVALID, MESSAGE_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          },
          {
            "x-api-key": []
          }
        ],
        "summary": "React to a message",
        "tags": [
          "v2 · Messages"
        ],
        "x-summary-ar": "تفاعل على رسالة",
        "x-description-ar": "إيموجي واحد؛ \"\" بيشيل التفاعل. للرسايل الواردة ابعت numberId.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718/reactions\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"emoji\": \"👍\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718/reactions', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"emoji\": \"👍\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718/reactions\",\n    headers=headers,\n    json={\n        \"emoji\": \"👍\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/messages/3EB0A1B2C3D4E5F60718/reactions');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'emoji' => '👍'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/campaigns": {
      "post": {
        "description": "Content: text, image/video/audio/document (media.url), location, contact, cta_url (link button), buttons, list. Recipients: inline (≤10 000, with variables for {name} etc.) or contactListId / audience. Every message goes through the Number Shield (warm-up caps, pacing, quiet hours, opt-outs, content rules). Content and recipients are deleted automatically after the campaign ends (keep window ≤24 h); only totals remain.\n\nScope: `campaigns:write`.",
        "operationId": "campaigns.create",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "numberId",
                  "name",
                  "content",
                  "optInConfirmed"
                ],
                "properties": {
                  "numberId": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "content": {
                    "type": "object",
                    "example": {
                      "type": "text",
                      "text": "أهلاً {name|عميلنا} 👋 عندنا عرض جديد"
                    }
                  },
                  "recipients": {
                    "type": "array",
                    "maxItems": 10000,
                    "items": {
                      "type": "object",
                      "properties": {
                        "phone": {
                          "type": "string"
                        },
                        "variables": {
                          "type": "object"
                        }
                      }
                    }
                  },
                  "contactListId": {
                    "type": "string"
                  },
                  "audience": {
                    "type": "object",
                    "properties": {
                      "listIds": {
                        "type": "array"
                      },
                      "tags": {
                        "type": "array"
                      },
                      "excludeTags": {
                        "type": "array"
                      }
                    }
                  },
                  "optInConfirmed": {
                    "type": "boolean",
                    "const": true
                  },
                  "speed": {
                    "type": "string",
                    "enum": [
                      "SAFE",
                      "NORMAL",
                      "FAST"
                    ]
                  },
                  "scheduleAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "start": {
                    "type": "boolean",
                    "default": true
                  }
                }
              },
              "examples": {
                "campaigns.create": {
                  "summary": "Create and start a campaign",
                  "value": {
                    "numberId": "cm1abcd2345efgh6789ijkl",
                    "name": "عرض الجمعة",
                    "content": {
                      "type": "cta_url",
                      "body": {
                        "text": "أهلاً {name|عميلنا} 👋 خصم 20% لحد الجمعة"
                      },
                      "cta": {
                        "title": "شوف العرض",
                        "url": "https://example.com/offer?ref={name}"
                      }
                    },
                    "recipients": [
                      {
                        "phone": "201001234567",
                        "variables": {
                          "name": "منى"
                        }
                      },
                      {
                        "phone": "966501234567"
                      }
                    ],
                    "optInConfirmed": true,
                    "speed": "SAFE"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm2camp0001xyz",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "name": "عرض الجمعة",
                  "status": "scheduled",
                  "contentType": "cta_url",
                  "createdVia": "api",
                  "speed": "SAFE",
                  "scheduledAt": null,
                  "startedAt": "2026-10-13T09:00:00.000Z",
                  "pausedAt": null,
                  "completedAt": null,
                  "pause": null,
                  "progress": {
                    "total": 500,
                    "queued": 380,
                    "sent": 120,
                    "delivered": 115,
                    "read": 70,
                    "replied": 9,
                    "failed": 0,
                    "skipped": 3,
                    "optOuts": 1,
                    "percent": 24
                  },
                  "replies": null,
                  "eta": {
                    "remaining": 380,
                    "perDayCap": 200,
                    "remainingToday": 80,
                    "estimatedMinutesToday": 34,
                    "extraDays": 2,
                    "note": "Estimate from the number warm-up caps and pacing."
                  },
                  "purged": false,
                  "purgedAt": null,
                  "createdAt": "2026-10-13T08:55:00.000Z",
                  "updatedAt": "2026-10-13T09:30:00.000Z",
                  "recipientsUpload": {
                    "total": 2,
                    "invalid": 0,
                    "notOnWhatsApp": 0,
                    "unchecked": 0
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CAMPAIGN_OPT_IN_REQUIRED, CAMPAIGN_CONTENT_INVALID, CAMPAIGN_RECIPIENTS_REQUIRED, CAMPAIGN_TOO_MANY_RECIPIENTS, CAMPAIGN_NO_RECIPIENTS, URL_SHORTENER, FEATURE_NOT_IN_PLAN (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Create and start a campaign",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "إنشاء وتشغيل حملة",
        "x-description-ar": "المحتوى: نص، صورة/فيديو/صوت/ملف (media.url)، موقع، جهة اتصال، زرار رابط، أزرار، قائمة. المستلمين في الطلب (لحد 10,000 بمتغيرات) أو contactListId أو audience.",
        "x-idempotency": "required",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/campaigns\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n  \"name\": \"عرض الجمعة\",\n  \"content\": {\n    \"type\": \"cta_url\",\n    \"body\": {\n      \"text\": \"أهلاً {name|عميلنا} 👋 خصم 20% لحد الجمعة\"\n    },\n    \"cta\": {\n      \"title\": \"شوف العرض\",\n      \"url\": \"https://example.com/offer?ref={name}\"\n    }\n  },\n  \"recipients\": [\n    {\n      \"phone\": \"201001234567\",\n      \"variables\": {\n        \"name\": \"منى\"\n      }\n    },\n    {\n      \"phone\": \"966501234567\"\n    }\n  ],\n  \"optInConfirmed\": true,\n  \"speed\": \"SAFE\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n    \"name\": \"عرض الجمعة\",\n    \"content\": {\n      \"type\": \"cta_url\",\n      \"body\": {\n        \"text\": \"أهلاً {name|عميلنا} 👋 خصم 20% لحد الجمعة\"\n      },\n      \"cta\": {\n        \"title\": \"شوف العرض\",\n        \"url\": \"https://example.com/offer?ref={name}\"\n      }\n    },\n    \"recipients\": [\n      {\n        \"phone\": \"201001234567\",\n        \"variables\": {\n          \"name\": \"منى\"\n        }\n      },\n      {\n        \"phone\": \"966501234567\"\n      }\n    ],\n    \"optInConfirmed\": true,\n    \"speed\": \"SAFE\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/campaigns\",\n    headers=headers,\n    json={\n        \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n        \"name\": \"عرض الجمعة\",\n        \"content\": {\n            \"type\": \"cta_url\",\n            \"body\": {\n                \"text\": \"أهلاً {name|عميلنا} 👋 خصم 20% لحد الجمعة\"\n            },\n            \"cta\": {\n                \"title\": \"شوف العرض\",\n                \"url\": \"https://example.com/offer?ref={name}\"\n            }\n        },\n        \"recipients\": [\n            {\n                \"phone\": \"201001234567\",\n                \"variables\": {\n                    \"name\": \"منى\"\n                }\n            },\n            {\n                \"phone\": \"966501234567\"\n            }\n        ],\n        \"optInConfirmed\": True,\n        \"speed\": \"SAFE\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'numberId' => 'cm1abcd2345efgh6789ijkl',\n        'name' => 'عرض الجمعة',\n        'content' => [\n            'type' => 'cta_url',\n            'body' => [\n                'text' => 'أهلاً {name|عميلنا} 👋 خصم 20% لحد الجمعة'\n            ],\n            'cta' => [\n                'title' => 'شوف العرض',\n                'url' => 'https://example.com/offer?ref={name}'\n            ]\n        ],\n        'recipients' => [\n            [\n                'phone' => '201001234567',\n                'variables' => [\n                    'name' => 'منى'\n                ]\n            ],\n            [\n                'phone' => '966501234567'\n            ]\n        ],\n        'optInConfirmed' => true,\n        'speed' => 'SAFE'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "get": {
        "description": "Scope: `campaigns:read`.",
        "operationId": "campaigns.list",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100 (default 25)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {}
          },
          {
            "name": "numberId",
            "required": false,
            "in": "query",
            "description": "Only this number",
            "schema": {}
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "running, paused, …",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "cm2camp0001xyz",
                      "numberId": "cm1abcd2345efgh6789ijkl",
                      "name": "عرض الجمعة",
                      "status": "running",
                      "contentType": "cta_url",
                      "createdVia": "api",
                      "speed": "SAFE",
                      "scheduledAt": null,
                      "startedAt": "2026-10-13T09:00:00.000Z",
                      "pausedAt": null,
                      "completedAt": null,
                      "pause": null,
                      "progress": {
                        "total": 500,
                        "queued": 380,
                        "sent": 120,
                        "delivered": 115,
                        "read": 70,
                        "replied": 9,
                        "failed": 0,
                        "skipped": 3,
                        "optOuts": 1,
                        "percent": 24
                      },
                      "replies": null,
                      "eta": {
                        "remaining": 380,
                        "perDayCap": 200,
                        "remainingToday": 80,
                        "estimatedMinutesToday": 34,
                        "extraDays": 2,
                        "note": "Estimate from the number warm-up caps and pacing."
                      },
                      "purged": false,
                      "purgedAt": null,
                      "createdAt": "2026-10-13T08:55:00.000Z",
                      "updatedAt": "2026-10-13T09:30:00.000Z"
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "List campaigns",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "عرض الحملات",
        "x-description-ar": "الأحدث الأول؛ الأرقام بس.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/campaigns\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/campaigns\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/campaigns/{campaignId}": {
      "get": {
        "description": "Scope: `campaigns:read`.",
        "operationId": "campaigns.get",
        "parameters": [
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm2camp0001xyz",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "name": "عرض الجمعة",
                  "status": "running",
                  "contentType": "cta_url",
                  "createdVia": "api",
                  "speed": "SAFE",
                  "scheduledAt": null,
                  "startedAt": "2026-10-13T09:00:00.000Z",
                  "pausedAt": null,
                  "completedAt": null,
                  "pause": null,
                  "progress": {
                    "total": 500,
                    "queued": 380,
                    "sent": 120,
                    "delivered": 115,
                    "read": 70,
                    "replied": 9,
                    "failed": 0,
                    "skipped": 3,
                    "optOuts": 1,
                    "percent": 24
                  },
                  "replies": null,
                  "eta": {
                    "remaining": 380,
                    "perDayCap": 200,
                    "remainingToday": 80,
                    "estimatedMinutesToday": 34,
                    "extraDays": 2,
                    "note": "Estimate from the number warm-up caps and pacing."
                  },
                  "purged": false,
                  "purgedAt": null,
                  "createdAt": "2026-10-13T08:55:00.000Z",
                  "updatedAt": "2026-10-13T09:30:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CAMPAIGN_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Progress, pause reason and ETA",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "التقدم وسبب الإيقاف والوقت المتوقع",
        "x-description-ar": "الوقت المتوقع محسوب من حدود تسخين الرقم وسرعته.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "delete": {
        "description": "Scope: `campaigns:write`.",
        "operationId": "campaigns.delete",
        "parameters": [
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm2camp0001xyz",
                  "deleted": true
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CAMPAIGN_ACTIVE (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Delete a draft / finished campaign",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "حذف مسودة أو حملة خلصت",
        "x-description-ar": "الحملة الشغالة لازم تتلغي الأول.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/campaigns/{campaignId}/recipients": {
      "get": {
        "description": "Available while the campaign runs and during the keep window; afterwards 410 CAMPAIGN_PURGED.\n\nScope: `campaigns:read`.",
        "operationId": "campaigns.recipients",
        "parameters": [
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–500 (default 50)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor",
            "schema": {}
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "QUEUED | SENDING | SENT | FAILED | SKIPPED",
            "schema": {}
          },
          {
            "name": "reply",
            "required": false,
            "in": "query",
            "description": "option id | ANY | NONE",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "phone": "201001234567",
                      "status": "sent",
                      "errorCode": null,
                      "sentAt": "…",
                      "deliveredAt": "…",
                      "readAt": null,
                      "repliedAt": null,
                      "optedOut": false,
                      "buttonReply": {
                        "id": "yes",
                        "title": "مهتم",
                        "index": 1,
                        "at": "…"
                      }
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CAMPAIGN_PURGED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Recipients and button replies",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "المستلمين وردود الأزرار",
        "x-description-ar": "متاحة وقت التشغيل وخلال فترة الحفظ.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/recipients?status=FAILED\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/recipients?status=FAILED', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/recipients?status=FAILED\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/recipients?status=FAILED');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/campaigns/{campaignId}/start": {
      "post": {
        "description": "Scope: `campaigns:write`.",
        "operationId": "campaigns.start",
        "parameters": [
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm2camp0001xyz",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "name": "عرض الجمعة",
                  "status": "running",
                  "contentType": "cta_url",
                  "createdVia": "api",
                  "speed": "SAFE",
                  "scheduledAt": null,
                  "startedAt": "2026-10-13T09:00:00.000Z",
                  "pausedAt": null,
                  "completedAt": null,
                  "pause": null,
                  "progress": {
                    "total": 500,
                    "queued": 380,
                    "sent": 120,
                    "delivered": 115,
                    "read": 70,
                    "replied": 9,
                    "failed": 0,
                    "skipped": 3,
                    "optOuts": 1,
                    "percent": 24
                  },
                  "replies": null,
                  "eta": {
                    "remaining": 380,
                    "perDayCap": 200,
                    "remainingToday": 80,
                    "estimatedMinutesToday": 34,
                    "extraDays": 2,
                    "note": "Estimate from the number warm-up caps and pacing."
                  },
                  "purged": false,
                  "purgedAt": null,
                  "createdAt": "2026-10-13T08:55:00.000Z",
                  "updatedAt": "2026-10-13T09:30:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CAMPAIGN_NOT_DRAFT (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Start a draft",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "تشغيل مسودة",
        "x-description-ar": "للحملات اللي اتعملت بـ start=false.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/start\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/start', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/start\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/start');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/campaigns/{campaignId}/pause": {
      "post": {
        "description": "Scope: `campaigns:write`.",
        "operationId": "campaigns.pause",
        "parameters": [
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm2camp0001xyz",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "name": "عرض الجمعة",
                  "status": "paused",
                  "contentType": "cta_url",
                  "createdVia": "api",
                  "speed": "SAFE",
                  "scheduledAt": null,
                  "startedAt": "2026-10-13T09:00:00.000Z",
                  "pausedAt": null,
                  "completedAt": null,
                  "pause": {
                    "reason": "USER_PAUSED",
                    "until": null
                  },
                  "progress": {
                    "total": 500,
                    "queued": 380,
                    "sent": 120,
                    "delivered": 115,
                    "read": 70,
                    "replied": 9,
                    "failed": 0,
                    "skipped": 3,
                    "optOuts": 1,
                    "percent": 24
                  },
                  "replies": null,
                  "eta": {
                    "remaining": 380,
                    "perDayCap": 200,
                    "remainingToday": 80,
                    "estimatedMinutesToday": 34,
                    "extraDays": 2,
                    "note": "Estimate from the number warm-up caps and pacing."
                  },
                  "purged": false,
                  "purgedAt": null,
                  "createdAt": "2026-10-13T08:55:00.000Z",
                  "updatedAt": "2026-10-13T09:30:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Pause",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "إيقاف مؤقت",
        "x-description-ar": "الإرسال المنتظر بيقف فورًا.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/pause\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/pause', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/pause\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/pause');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/campaigns/{campaignId}/resume": {
      "post": {
        "description": "Same rules as the dashboard: platform / safety pauses (bans, content blocks, admin) cannot be lifted by you; time-boxed safety pauses only after they end.\n\nScope: `campaigns:write`.",
        "operationId": "campaigns.resume",
        "parameters": [
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm2camp0001xyz",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "name": "عرض الجمعة",
                  "status": "running",
                  "contentType": "cta_url",
                  "createdVia": "api",
                  "speed": "SAFE",
                  "scheduledAt": null,
                  "startedAt": "2026-10-13T09:00:00.000Z",
                  "pausedAt": null,
                  "completedAt": null,
                  "pause": null,
                  "progress": {
                    "total": 500,
                    "queued": 380,
                    "sent": 120,
                    "delivered": 115,
                    "read": 70,
                    "replied": 9,
                    "failed": 0,
                    "skipped": 3,
                    "optOuts": 1,
                    "percent": 24
                  },
                  "replies": null,
                  "eta": {
                    "remaining": 380,
                    "perDayCap": 200,
                    "remainingToday": 80,
                    "estimatedMinutesToday": 34,
                    "extraDays": 2,
                    "note": "Estimate from the number warm-up caps and pacing."
                  },
                  "purged": false,
                  "purgedAt": null,
                  "createdAt": "2026-10-13T08:55:00.000Z",
                  "updatedAt": "2026-10-13T09:30:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CAMPAIGN_RESUME_BLOCKED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Resume",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "استكمال",
        "x-description-ar": "الإيقاف من المنصة أو الحماية مش بإيدك؛ الإيقاف المؤقت بيرجع لما وقته يخلص.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/resume\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/resume', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/resume\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/resume');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/campaigns/{campaignId}/cancel": {
      "post": {
        "description": "Scope: `campaigns:write`.",
        "operationId": "campaigns.cancel",
        "parameters": [
          {
            "name": "campaignId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm2camp0001xyz",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "name": "عرض الجمعة",
                  "status": "cancelled",
                  "contentType": "cta_url",
                  "createdVia": "api",
                  "speed": "SAFE",
                  "scheduledAt": null,
                  "startedAt": "2026-10-13T09:00:00.000Z",
                  "pausedAt": null,
                  "completedAt": null,
                  "pause": null,
                  "progress": {
                    "total": 500,
                    "queued": 380,
                    "sent": 120,
                    "delivered": 115,
                    "read": 70,
                    "replied": 9,
                    "failed": 0,
                    "skipped": 3,
                    "optOuts": 1,
                    "percent": 24
                  },
                  "replies": null,
                  "eta": {
                    "remaining": 380,
                    "perDayCap": 200,
                    "remainingToday": 80,
                    "estimatedMinutesToday": 34,
                    "extraDays": 2,
                    "note": "Estimate from the number warm-up caps and pacing."
                  },
                  "purged": false,
                  "purgedAt": null,
                  "createdAt": "2026-10-13T08:55:00.000Z",
                  "updatedAt": "2026-10-13T09:30:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CAMPAIGN_NOT_CANCELLABLE (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Cancel",
        "tags": [
          "v2 · Campaigns"
        ],
        "x-summary-ar": "إلغاء",
        "x-description-ar": "المستلمين اللي مستنيين بيتلغوا.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/cancel\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/cancel', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/cancel\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/campaigns/cm2camp0001xyz/cancel');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/auto-replies": {
      "get": {
        "description": "Rules of this number plus rules set for all numbers (scope: allNumbers). Plan feature AUTO_REPLIES.\n\nScope: `autoreplies:read`.",
        "operationId": "autoReplies.list",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100 (default 25)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "cm3rule0001xyz",
                      "sessionId": "cm1abcd2345efgh6789ijkl",
                      "scope": "number",
                      "name": "الأسعار",
                      "enabled": true,
                      "trigger": {
                        "type": "KEYWORD",
                        "match": "CONTAINS",
                        "keywords": [
                          "سعر",
                          "بكام",
                          "price"
                        ]
                      },
                      "schedule": null,
                      "reply": {
                        "text": "أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices"
                      },
                      "cooldownMinutes": 60,
                      "priority": 0,
                      "stats": {
                        "triggered": 42,
                        "lastTriggeredAt": "2026-10-13T07:40:00.000Z"
                      },
                      "createdAt": "2026-10-01T09:00:00.000Z",
                      "updatedAt": "2026-10-10T09:00:00.000Z"
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "List rules",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "عرض القواعد",
        "x-description-ar": "قواعد الرقم + قواعد كل الأرقام (scope: allNumbers).",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "post": {
        "description": "Triggers: KEYWORD with match EXACT (whole message), CONTAINS (whole word or phrase), STARTS_WITH (message starts with the word / phrase) — literal keywords after Arabic normalisation — or REGEX (RE2 patterns: linear time, no lookarounds / backreferences; ≤ 10 patterns of ≤ 200 chars per rule, ≤ 50 REGEX rules per account; reply text can insert captures {1}, {2}, {groupName}); FIRST_MESSAGE (first message ever from a contact); AWAY (outside business hours). REGEX rules run after EXACT / CONTAINS / STARTS_WITH rules of the same priority. Replies go through the Number Shield as replies (WARM). Opt-out keywords always win.\n\nScope: `autoreplies:write`.",
        "operationId": "autoReplies.create",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "trigger",
                  "reply"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "enabled": {
                    "type": "boolean",
                    "default": true
                  },
                  "trigger": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "KEYWORD",
                          "FIRST_MESSAGE",
                          "AWAY"
                        ]
                      },
                      "match": {
                        "type": "string",
                        "enum": [
                          "EXACT",
                          "CONTAINS",
                          "STARTS_WITH",
                          "REGEX"
                        ],
                        "description": "Case-insensitive (\"regex\" and \"starts_with\" are accepted); `matchType` is an alias."
                      },
                      "keywords": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 100
                        },
                        "maxItems": 50,
                        "description": "EXACT / CONTAINS / STARTS_WITH: literal keywords"
                      },
                      "patterns": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 200
                        },
                        "minItems": 1,
                        "maxItems": 10,
                        "description": "REGEX: RE2 patterns (linear time; no lookarounds / backreferences). Any match fires the rule."
                      },
                      "regex": {
                        "type": "object",
                        "properties": {
                          "ignoreCase": {
                            "type": "boolean",
                            "default": true
                          },
                          "normalizeArabic": {
                            "type": "boolean",
                            "default": true
                          },
                          "allowLinksInCaptures": {
                            "type": "boolean",
                            "default": false,
                            "description": "Keep link-like captures (URLs, domains, wa.me / t.me) in the reply. Off by default: they are always removed so a customer cannot make your number send a link of their choice."
                          }
                        }
                      }
                    }
                  },
                  "schedule": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "timezone": {
                        "type": "string",
                        "example": "Africa/Cairo"
                      },
                      "days": {
                        "type": "array",
                        "items": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 6
                        }
                      },
                      "start": {
                        "type": "string",
                        "example": "09:00"
                      },
                      "end": {
                        "type": "string",
                        "example": "18:00"
                      }
                    }
                  },
                  "reply": {
                    "type": "object",
                    "properties": {
                      "text": {
                        "type": "string",
                        "maxLength": 4096
                      },
                      "mediaUrl": {
                        "type": "string"
                      },
                      "mediaType": {
                        "type": "string",
                        "enum": [
                          "image",
                          "video",
                          "document",
                          "audio"
                        ]
                      }
                    }
                  },
                  "cooldownMinutes": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "priority": {
                    "type": "integer"
                  }
                }
              },
              "examples": {
                "autoReplies.create": {
                  "summary": "Create a rule",
                  "value": {
                    "name": "الأسعار",
                    "trigger": {
                      "type": "KEYWORD",
                      "match": "CONTAINS",
                      "keywords": [
                        "سعر",
                        "بكام",
                        "price"
                      ]
                    },
                    "reply": {
                      "text": "أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices"
                    },
                    "cooldownMinutes": 60
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm3rule0001xyz",
                  "sessionId": "cm1abcd2345efgh6789ijkl",
                  "scope": "number",
                  "name": "الأسعار",
                  "enabled": true,
                  "trigger": {
                    "type": "KEYWORD",
                    "match": "CONTAINS",
                    "keywords": [
                      "سعر",
                      "بكام",
                      "price"
                    ]
                  },
                  "schedule": null,
                  "reply": {
                    "text": "أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices"
                  },
                  "cooldownMinutes": 60,
                  "priority": 0,
                  "stats": {
                    "triggered": 42,
                    "lastTriggeredAt": "2026-10-13T07:40:00.000Z"
                  },
                  "createdAt": "2026-10-01T09:00:00.000Z",
                  "updatedAt": "2026-10-10T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: AUTO_REPLIES_NOT_IN_PLAN, AUTO_REPLY_KEYWORDS_REQUIRED, AUTO_REPLY_PATTERNS_REQUIRED, AUTO_REPLY_REGEX_INVALID, AUTO_REPLY_REGEX_TOO_MANY_PATTERNS, AUTO_REPLY_REGEX_RULE_LIMIT, AUTO_REPLY_REGEX_ENGINE_UNAVAILABLE, AUTO_REPLY_SCHEDULE_REQUIRED, INVALID_SCHEDULE (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Create a rule",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "إنشاء قاعدة",
        "x-description-ar": "match: ‏EXACT / CONTAINS / STARTS_WITH بتقارن كلمات حرفيًا بعد توحيد الحروف العربي (أ/إ/آ، ى/ي، ة/ه، والتشكيل). REGEX بياخد trigger.patterns: تعبيرات RE2 النمطية (وقت خطّي — مفيش تعليق من التراجع). مقبول \"regex\" و \"starts_with\" بحروف صغيرة و trigger.matchType.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"name\": \"الأسعار\",\n  \"trigger\": {\n    \"type\": \"KEYWORD\",\n    \"match\": \"CONTAINS\",\n    \"keywords\": [\n      \"سعر\",\n      \"بكام\",\n      \"price\"\n    ]\n  },\n  \"reply\": {\n    \"text\": \"أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices\"\n  },\n  \"cooldownMinutes\": 60\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"name\": \"الأسعار\",\n    \"trigger\": {\n      \"type\": \"KEYWORD\",\n      \"match\": \"CONTAINS\",\n      \"keywords\": [\n        \"سعر\",\n        \"بكام\",\n        \"price\"\n      ]\n    },\n    \"reply\": {\n      \"text\": \"أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices\"\n    },\n    \"cooldownMinutes\": 60\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies\",\n    headers=headers,\n    json={\n        \"name\": \"الأسعار\",\n        \"trigger\": {\n            \"type\": \"KEYWORD\",\n            \"match\": \"CONTAINS\",\n            \"keywords\": [\n                \"سعر\",\n                \"بكام\",\n                \"price\"\n            ]\n        },\n        \"reply\": {\n            \"text\": \"أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices\"\n        },\n        \"cooldownMinutes\": 60\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'name' => 'الأسعار',\n        'trigger' => [\n            'type' => 'KEYWORD',\n            'match' => 'CONTAINS',\n            'keywords' => [\n                'سعر',\n                'بكام',\n                'price'\n            ]\n        ],\n        'reply' => [\n            'text' => 'أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices'\n        ],\n        'cooldownMinutes' => 60\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "delete": {
        "description": "Scope: `autoreplies:write`.",
        "operationId": "autoReplies.deleteAll",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confirm",
            "required": true,
            "in": "query",
            "description": "Must be DELETE_ALL",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeAccountWide",
            "required": false,
            "in": "query",
            "description": "true = also rules set for all numbers",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "deleted": 4
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: CONFIRMATION_REQUIRED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Delete all rules",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "حذف كل القواعد",
        "x-description-ar": "محتاج ?confirm=DELETE_ALL.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies?confirm=DELETE_ALL\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies?confirm=DELETE_ALL', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies?confirm=DELETE_ALL\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies?confirm=DELETE_ALL');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/auto-replies/test": {
      "post": {
        "description": "Scope: `autoreplies:read`.",
        "operationId": "autoReplies.test",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "firstMessage": {
                    "type": "boolean"
                  }
                }
              },
              "examples": {
                "autoReplies.test": {
                  "summary": "Which rule would answer? (no send)",
                  "value": {
                    "text": "عايز اعرف السعر"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "matchedRuleId": "cm3rule0001xyz",
                  "reply": {
                    "text": "أهلاً بيك 👋 …"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Which rule would answer? (no send)",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "أي قاعدة هترد؟ (من غير إرسال)",
        "x-description-ar": "جرّب نص قبل ما تشغّل.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/test\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"text\": \"عايز اعرف السعر\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/test', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"text\": \"عايز اعرف السعر\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/test\",\n    headers=headers,\n    json={\n        \"text\": \"عايز اعرف السعر\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/test');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'text' => 'عايز اعرف السعر'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/auto-replies/enable-all": {
      "post": {
        "description": "Scope: `autoreplies:write`.",
        "operationId": "autoReplies.enableAll",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeAccountWide",
            "required": false,
            "in": "query",
            "description": "true = also rules set for all numbers",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "updated": 4,
                  "enabled": true
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Enable all rules",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "تشغيل كل القواعد",
        "x-description-ar": "ضيف ?includeAccountWide=true لقواعد كل الأرقام كمان.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/enable-all\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/enable-all', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/enable-all\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/enable-all');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/auto-replies/disable-all": {
      "post": {
        "description": "Scope: `autoreplies:write`.",
        "operationId": "autoReplies.disableAll",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeAccountWide",
            "required": false,
            "in": "query",
            "description": "true = also rules set for all numbers",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "updated": 4,
                  "enabled": false
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Disable all rules",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "إيقاف كل القواعد",
        "x-description-ar": "نفس فلتر enable-all.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/disable-all\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/disable-all', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/disable-all\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/disable-all');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/auto-replies/{ruleId}": {
      "get": {
        "description": "Scope: `autoreplies:read`.",
        "operationId": "autoReplies.get",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ruleId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm3rule0001xyz",
                  "sessionId": "cm1abcd2345efgh6789ijkl",
                  "scope": "number",
                  "name": "الأسعار",
                  "enabled": true,
                  "trigger": {
                    "type": "KEYWORD",
                    "match": "CONTAINS",
                    "keywords": [
                      "سعر",
                      "بكام",
                      "price"
                    ]
                  },
                  "schedule": null,
                  "reply": {
                    "text": "أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices"
                  },
                  "cooldownMinutes": 60,
                  "priority": 0,
                  "stats": {
                    "triggered": 42,
                    "lastTriggeredAt": "2026-10-13T07:40:00.000Z"
                  },
                  "createdAt": "2026-10-01T09:00:00.000Z",
                  "updatedAt": "2026-10-10T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: AUTO_REPLY_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Get a rule",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "تفاصيل قاعدة",
        "x-description-ar": "مع إحصائيات التشغيل.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "patch": {
        "description": "Scope: `autoreplies:write`.",
        "operationId": "autoReplies.update",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ruleId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "enabled": {
                    "type": "boolean",
                    "default": true
                  },
                  "trigger": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "KEYWORD",
                          "FIRST_MESSAGE",
                          "AWAY"
                        ]
                      },
                      "match": {
                        "type": "string",
                        "enum": [
                          "EXACT",
                          "CONTAINS",
                          "STARTS_WITH",
                          "REGEX"
                        ],
                        "description": "Case-insensitive (\"regex\" and \"starts_with\" are accepted); `matchType` is an alias."
                      },
                      "keywords": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 100
                        },
                        "maxItems": 50,
                        "description": "EXACT / CONTAINS / STARTS_WITH: literal keywords"
                      },
                      "patterns": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 200
                        },
                        "minItems": 1,
                        "maxItems": 10,
                        "description": "REGEX: RE2 patterns (linear time; no lookarounds / backreferences). Any match fires the rule."
                      },
                      "regex": {
                        "type": "object",
                        "properties": {
                          "ignoreCase": {
                            "type": "boolean",
                            "default": true
                          },
                          "normalizeArabic": {
                            "type": "boolean",
                            "default": true
                          },
                          "allowLinksInCaptures": {
                            "type": "boolean",
                            "default": false,
                            "description": "Keep link-like captures (URLs, domains, wa.me / t.me) in the reply. Off by default: they are always removed so a customer cannot make your number send a link of their choice."
                          }
                        }
                      }
                    }
                  },
                  "schedule": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "timezone": {
                        "type": "string",
                        "example": "Africa/Cairo"
                      },
                      "days": {
                        "type": "array",
                        "items": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 6
                        }
                      },
                      "start": {
                        "type": "string",
                        "example": "09:00"
                      },
                      "end": {
                        "type": "string",
                        "example": "18:00"
                      }
                    }
                  },
                  "reply": {
                    "type": "object",
                    "properties": {
                      "text": {
                        "type": "string",
                        "maxLength": 4096
                      },
                      "mediaUrl": {
                        "type": "string"
                      },
                      "mediaType": {
                        "type": "string",
                        "enum": [
                          "image",
                          "video",
                          "document",
                          "audio"
                        ]
                      }
                    }
                  },
                  "cooldownMinutes": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "priority": {
                    "type": "integer"
                  }
                }
              },
              "examples": {
                "autoReplies.update": {
                  "summary": "Update / toggle a rule",
                  "value": {
                    "enabled": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm3rule0001xyz",
                  "sessionId": "cm1abcd2345efgh6789ijkl",
                  "scope": "number",
                  "name": "الأسعار",
                  "enabled": false,
                  "trigger": {
                    "type": "KEYWORD",
                    "match": "CONTAINS",
                    "keywords": [
                      "سعر",
                      "بكام",
                      "price"
                    ]
                  },
                  "schedule": null,
                  "reply": {
                    "text": "أهلاً {name|بيك} 👋 الأسعار: https://example.com/prices"
                  },
                  "cooldownMinutes": 60,
                  "priority": 0,
                  "stats": {
                    "triggered": 42,
                    "lastTriggeredAt": "2026-10-13T07:40:00.000Z"
                  },
                  "createdAt": "2026-10-01T09:00:00.000Z",
                  "updatedAt": "2026-10-10T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Update / toggle a rule",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "تعديل / تشغيل وإيقاف قاعدة",
        "x-description-ar": "تعديل جزئي؛ enabled بيشغل ويوقف.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PATCH \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"enabled\": false\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz', {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"enabled\": false\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.patch(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz\",\n    headers=headers,\n    json={\n        \"enabled\": False\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PATCH',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'enabled' => false\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "delete": {
        "description": "Scope: `autoreplies:write`.",
        "operationId": "autoReplies.delete",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ruleId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "deleted": true,
                  "id": "cm3rule0001xyz"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Delete a rule",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "حذف قاعدة",
        "x-description-ar": "نهائي.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-replies/cm3rule0001xyz');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/auto-reply-settings": {
      "get": {
        "description": "Scope: `autoreplies:read`.",
        "operationId": "autoReplies.settings.get",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "delaySeconds": {
                    "min": 3,
                    "max": 8
                  },
                  "maxDelaySeconds": 120
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Reply delay",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "وقت التأخير قبل الرد",
        "x-description-ar": "تأخير عشوائي بين min و max ثانية.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-reply-settings\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-reply-settings', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-reply-settings\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-reply-settings');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "patch": {
        "description": "A random delay between min and max seconds (0–120) before each auto-reply of this number.\n\nScope: `autoreplies:write`.",
        "operationId": "autoReplies.settings.update",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "delaySeconds"
                ],
                "properties": {
                  "delaySeconds": {
                    "type": "object",
                    "properties": {
                      "min": {
                        "type": "integer"
                      },
                      "max": {
                        "type": "integer"
                      }
                    }
                  }
                }
              },
              "examples": {
                "autoReplies.settings.update": {
                  "summary": "Set the reply delay",
                  "value": {
                    "delaySeconds": {
                      "min": 3,
                      "max": 8
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "delaySeconds": {
                    "min": 3,
                    "max": 8
                  },
                  "maxDelaySeconds": 120
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: AUTO_REPLY_DELAY_INVALID (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Set the reply delay",
        "tags": [
          "v2 · Auto-replies"
        ],
        "x-summary-ar": "ضبط التأخير قبل الرد",
        "x-description-ar": "0–120 ثانية؛ بيبان طبيعي وبيوزع الضغط.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PATCH \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-reply-settings\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"delaySeconds\": {\n    \"min\": 3,\n    \"max\": 8\n  }\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-reply-settings', {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"delaySeconds\": {\n      \"min\": 3,\n      \"max\": 8\n    }\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.patch(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-reply-settings\",\n    headers=headers,\n    json={\n        \"delaySeconds\": {\n            \"min\": 3,\n            \"max\": 8\n        }\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/auto-reply-settings');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PATCH',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'delaySeconds' => [\n            'min' => 3,\n            'max' => 8\n        ]\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/health": {
      "get": {
        "description": "Scope: `stats:read`.",
        "operationId": "shield.health",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "score": 86,
                  "level": "good",
                  "reasons": [],
                  "warmup": {
                    "stage": "WEEK_2",
                    "source": "AGE",
                    "nextStageAt": "2026-10-20T09:00:00.000Z",
                    "ageDays": 9
                  },
                  "caps": {
                    "coldPerDay": 100,
                    "coldPerHour": 25,
                    "warmPerDay": 1000
                  },
                  "customLimits": {
                    "maxPerDay": null,
                    "maxPerHour": null,
                    "minGapSeconds": null
                  },
                  "usageToday": {
                    "coldToday": 12,
                    "warmToday": 40,
                    "coldLastHour": 3,
                    "resetsAt": "…"
                  },
                  "pause": null,
                  "restrictions": {
                    "reachoutLocked": false,
                    "linksTrusted": false,
                    "linksAllowedToNewContacts": true
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Health",
        "tags": [
          "v2 · Number Shield & stats"
        ],
        "x-summary-ar": "صحة الرقم",
        "x-description-ar": "الدرجة والمستوى والأسباب ومرحلة التسخين والحدود والاستخدام النهارده والإيقاف والقيود.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/health\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/health', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/health\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/health');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/pause": {
      "post": {
        "description": "Your own pause: campaigns and sends to new contacts wait; replies to people who wrote in the last 24 h still go. Your pause applies to this number in your account only; a Number Shield pause stays in force on its own and cannot be lifted from the API.\n\nScope: `numbers:write`.",
        "operationId": "shield.pause",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "minutes"
                ],
                "properties": {
                  "minutes": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 10080
                  }
                }
              },
              "examples": {
                "shield.pause": {
                  "summary": "Pause a number",
                  "value": {
                    "minutes": 120
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "paused": true,
                  "until": "2026-10-13T10:00:00.000Z",
                  "reason": "CUSTOMER_PAUSED"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: NUMBER_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Pause a number",
        "tags": [
          "v2 · Number Shield & stats"
        ],
        "x-summary-ar": "إيقاف الرقم مؤقتًا",
        "x-description-ar": "من 5 دقايق لـ 7 أيام. الحملات والرسايل للأرقام الجديدة بتستنى؛ الردود على المحادثات الحديثة شغالة.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/pause\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"minutes\": 120\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/pause', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"minutes\": 120\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/pause\",\n    headers=headers,\n    json={\n        \"minutes\": 120\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/pause');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'minutes' => 120\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/resume": {
      "post": {
        "description": "Scope: `numbers:write`.",
        "operationId": "shield.resume",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "paused": false
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: NUMBER_PAUSE_NOT_YOURS (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Lift your pause",
        "tags": [
          "v2 · Number Shield & stats"
        ],
        "x-summary-ar": "إلغاء الإيقاف بتاعك",
        "x-description-ar": "الإيقاف من حماية الرقم بيخلص لوحده.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/resume\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/resume', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/resume\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/resume');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/limits": {
      "get": {
        "description": "Scope: `stats:read`.",
        "operationId": "shield.limits.get",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "maxPerDay": 150,
                  "maxPerHour": 20,
                  "minGapSeconds": 30,
                  "updatedAt": "…"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Your limits",
        "tags": [
          "v2 · Number Shield & stats"
        ],
        "x-summary-ar": "حدودك",
        "x-description-ar": "الحدود اللي انت حطيتها للرقم.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "put": {
        "description": "Applied by the Number Shield on every send of the number on top of its own caps — the stricter value always wins, so you can only slow a number down, never speed it up.\n\nScope: `numbers:write`.",
        "operationId": "shield.limits.put",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "maxPerDay": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1
                  },
                  "maxPerHour": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1
                  },
                  "minGapSeconds": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 3600
                  }
                }
              },
              "examples": {
                "shield.limits.put": {
                  "summary": "Set stricter limits",
                  "value": {
                    "maxPerDay": 150,
                    "maxPerHour": 20,
                    "minGapSeconds": 30
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "maxPerDay": 150,
                  "maxPerHour": 20,
                  "minGapSeconds": 30,
                  "updatedAt": "…"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: LIMITS_INVALID (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Set stricter limits",
        "tags": [
          "v2 · Number Shield & stats"
        ],
        "x-summary-ar": "ضبط حدود أشد",
        "x-description-ar": "بتتطبق على كل رسايل الرقم فوق حماية الرقم؛ الأشد هو اللي بيكسب.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PUT \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"maxPerDay\": 150,\n  \"maxPerHour\": 20,\n  \"minGapSeconds\": 30\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits', {\n  method: 'PUT',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"maxPerDay\": 150,\n    \"maxPerHour\": 20,\n    \"minGapSeconds\": 30\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.put(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits\",\n    headers=headers,\n    json={\n        \"maxPerDay\": 150,\n        \"maxPerHour\": 20,\n        \"minGapSeconds\": 30\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PUT',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'maxPerDay' => 150,\n        'maxPerHour' => 20,\n        'minGapSeconds' => 30\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "delete": {
        "description": "Scope: `numbers:write`.",
        "operationId": "shield.limits.delete",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "maxPerDay": null,
                  "maxPerHour": null,
                  "minGapSeconds": null,
                  "updatedAt": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Remove your limits",
        "tags": [
          "v2 · Number Shield & stats"
        ],
        "x-summary-ar": "إزالة حدودك",
        "x-description-ar": "حدود الحماية بتفضل.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/limits');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/stats": {
      "get": {
        "description": "Scope: `stats:read`.",
        "operationId": "stats.number",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "YYYY-MM-DD (default: 6 days before `to`)",
            "schema": {}
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "YYYY-MM-DD (default: today)",
            "schema": {}
          },
          {
            "name": "granularity",
            "required": false,
            "in": "query",
            "description": "day",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "timezone": "Africa/Cairo",
                  "granularity": "day",
                  "from": "2026-10-07",
                  "to": "2026-10-13",
                  "data": [
                    {
                      "date": "2026-10-13",
                      "sent": 52,
                      "delivered": 50,
                      "read": 31,
                      "failed": 0,
                      "replied": 12,
                      "optOuts": 0,
                      "newContacts": 20,
                      "replies": 32
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: STATS_RANGE_INVALID (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Daily statistics",
        "tags": [
          "v2 · Number Shield & stats"
        ],
        "x-summary-ar": "إحصائيات يومية",
        "x-description-ar": "المبعوت والمستلم والمقروء والفاشل والردود والإلغاءات لكل يوم (لحد 92 يوم).",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/stats?from=2026-10-07&to=2026-10-13\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/stats?from=2026-10-07&to=2026-10-13', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/stats?from=2026-10-07&to=2026-10-13\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/stats?from=2026-10-07&to=2026-10-13');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/stats/today": {
      "get": {
        "description": "Scope: `stats:read`.",
        "operationId": "stats.today",
        "parameters": [
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "date": "2026-10-13",
                  "timezone": "Africa/Cairo",
                  "totals": {
                    "sent": 120,
                    "delivered": 115,
                    "read": 70,
                    "failed": 1,
                    "replied": 20,
                    "optOuts": 0
                  },
                  "numbers": [
                    {
                      "numberId": "cm1abcd2345efgh6789ijkl",
                      "name": "فرع المعادي",
                      "sent": 120,
                      "delivered": 115,
                      "read": 70,
                      "failed": 1,
                      "replied": 20,
                      "optOuts": 0
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Today across numbers",
        "tags": [
          "v2 · Number Shield & stats"
        ],
        "x-summary-ar": "النهارده لكل الأرقام",
        "x-description-ar": "الإجمالي ولكل رقم.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/stats/today\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/stats/today', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/stats/today\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/stats/today');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/groups": {
      "get": {
        "description": "Read only. Sending to groups is blocked by the Number Shield on purpose (see docs).\n\nScope: `groups:read`.",
        "operationId": "groups.list",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100 (default 25)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "120363025246125486@g.us",
                      "subject": "عملاء VIP",
                      "size": 48,
                      "isAdmin": true
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: GROUPS_NOT_IN_PLAN, NUMBER_NOT_CONNECTED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "List groups",
        "tags": [
          "v2 · Groups"
        ],
        "x-summary-ar": "عرض الجروبات",
        "x-description-ar": "الاسم والحجم وهل الرقم أدمن.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/groups\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/groups', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/groups\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/groups');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/numbers/{numberId}/groups/{groupId}": {
      "get": {
        "description": "Scope: `groups:read`.",
        "operationId": "groups.get",
        "parameters": [
          {
            "name": "numberId",
            "required": true,
            "in": "path",
            "description": "Number id (from GET /v2/numbers)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "groupId",
            "required": true,
            "in": "path",
            "description": "1203…@g.us",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "120363025246125486@g.us",
                  "subject": "عملاء VIP",
                  "description": null,
                  "size": 48,
                  "isAdmin": true,
                  "participants": [
                    {
                      "phone": "201001234567",
                      "lid": null,
                      "role": "member"
                    }
                  ],
                  "inviteLink": "https://chat.whatsapp.com/AbCdEf…",
                  "sending": {
                    "allowed": false,
                    "reason": "GROUP_SENDS_BLOCKED"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: GROUP_ID_INVALID, GROUP_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Group info",
        "tags": [
          "v2 · Groups"
        ],
        "x-summary-ar": "تفاصيل الجروب",
        "x-description-ar": "الأعضاء ولينك الدعوة لو الرقم أدمن بس.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/groups/120363025246125486%40g.us\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/groups/120363025246125486%40g.us', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/groups/120363025246125486%40g.us\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/numbers/cm1abcd2345efgh6789ijkl/groups/120363025246125486%40g.us');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/otp": {
      "post": {
        "description": "Mursilat generates the code (4–8 digits), sends it from your number and keeps only a hash: the code is never returned, stored or logged. Optional \"copy code\" button. The text is fixed and localized (ar/en) with your app name (letters, digits and spaces, no links). At most 5 codes per recipient per hour and 200 different recipients per account per hour; opted-out recipients are refused; the Number Shield OTP class applies its own caps and short pacing.\n\nScope: `otp`.",
        "operationId": "otp.send",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "numberId",
                  "to"
                ],
                "properties": {
                  "numberId": {
                    "type": "string"
                  },
                  "to": {
                    "type": "string",
                    "example": "201001234567"
                  },
                  "length": {
                    "type": "integer",
                    "minimum": 4,
                    "maximum": 8,
                    "default": 6
                  },
                  "ttlSeconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 900,
                    "default": 300
                  },
                  "maxAttempts": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10,
                    "default": 5
                  },
                  "app": {
                    "type": "string",
                    "maxLength": 30,
                    "example": "متجر النور",
                    "description": "Letters, digits and spaces only"
                  },
                  "locale": {
                    "type": "string",
                    "enum": [
                      "ar",
                      "en"
                    ],
                    "default": "ar"
                  },
                  "copyButton": {
                    "type": "boolean",
                    "default": false
                  }
                }
              },
              "examples": {
                "otp.send": {
                  "summary": "Send a code",
                  "value": {
                    "numberId": "cm1abcd2345efgh6789ijkl",
                    "to": "201001234567",
                    "length": 6,
                    "ttlSeconds": 300,
                    "maxAttempts": 5,
                    "app": "متجر النور",
                    "copyButton": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "otpId": "otp_8f2c1d9a7b3e4f56a1b2c3d4",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "to": "2010****4567",
                  "status": "pending",
                  "length": 6,
                  "maxAttempts": 5,
                  "expiresAt": "2026-10-13T08:05:00.000Z",
                  "messageId": "3EB0A1B2C3D4E5F60718"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: OTP_INPUT_INVALID, OTP_RECIPIENT_RATE_LIMITED, SAFETY_HOURLY_CAP_REACHED, MESSAGES_QUOTA_EXCEEDED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Send a code",
        "tags": [
          "v2 · OTP"
        ],
        "x-summary-ar": "إرسال كود",
        "x-description-ar": "الطول 4–8، الصلاحية 60–900 ثانية، المحاولات 1–10، واسم التطبيق (حروف وأرقام ومسافات، من غير روابط). النص ثابت ومترجم. لحد 5 أكواد للرقم و200 رقم مختلف للحساب في الساعة؛ الأرقام اللي لغت اشتراكها بترفض.",
        "x-idempotency": "required",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/otp\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n  \"to\": \"201001234567\",\n  \"length\": 6,\n  \"ttlSeconds\": 300,\n  \"maxAttempts\": 5,\n  \"app\": \"متجر النور\",\n  \"copyButton\": true\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/otp', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n    \"to\": \"201001234567\",\n    \"length\": 6,\n    \"ttlSeconds\": 300,\n    \"maxAttempts\": 5,\n    \"app\": \"متجر النور\",\n    \"copyButton\": true\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/otp\",\n    headers=headers,\n    json={\n        \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n        \"to\": \"201001234567\",\n        \"length\": 6,\n        \"ttlSeconds\": 300,\n        \"maxAttempts\": 5,\n        \"app\": \"متجر النور\",\n        \"copyButton\": True\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/otp');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'numberId' => 'cm1abcd2345efgh6789ijkl',\n        'to' => '201001234567',\n        'length' => 6,\n        'ttlSeconds' => 300,\n        'maxAttempts' => 5,\n        'app' => 'متجر النور',\n        'copyButton' => true\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/otp/{otpId}/verify": {
      "post": {
        "description": "Constant-time comparison. Every call spends one attempt; after maxAttempts the OTP is locked. Send the code as a string (leading zeros matter).\n\nScope: `otp`.",
        "operationId": "otp.verify",
        "parameters": [
          {
            "name": "otpId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "code"
                ],
                "properties": {
                  "code": {
                    "type": "string",
                    "example": "048213"
                  }
                }
              },
              "examples": {
                "otp.verify": {
                  "summary": "Verify a code",
                  "value": {
                    "code": "048213"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "otpId": "otp_8f2c1d9a7b3e4f56a1b2c3d4",
                  "valid": true,
                  "reason": null,
                  "attemptsLeft": 4
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: OTP_NOT_FOUND, OTP_VERIFY_RATE_LIMITED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Verify a code",
        "tags": [
          "v2 · OTP"
        ],
        "x-summary-ar": "التحقق من الكود",
        "x-description-ar": "كل محاولة بتتحسب؛ ابعت الكود كنص. reason: INVALID_CODE | EXPIRED | TOO_MANY_ATTEMPTS | ALREADY_VERIFIED.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/otp/otp_8f2c1d9a7b3e4f56a1b2c3d4/verify\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"code\": \"048213\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/otp/otp_8f2c1d9a7b3e4f56a1b2c3d4/verify', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"code\": \"048213\"\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/otp/otp_8f2c1d9a7b3e4f56a1b2c3d4/verify\",\n    headers=headers,\n    json={\n        \"code\": \"048213\"\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/otp/otp_8f2c1d9a7b3e4f56a1b2c3d4/verify');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'code' => '048213'\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/otp/{otpId}": {
      "get": {
        "description": "Scope: `otp`.",
        "operationId": "otp.get",
        "parameters": [
          {
            "name": "otpId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "otpId": "otp_8f2c1d9a7b3e4f56a1b2c3d4",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "to": "2010****4567",
                  "status": "verified",
                  "attempts": 1,
                  "maxAttempts": 5,
                  "attemptsLeft": 0,
                  "expiresAt": "…",
                  "verifiedAt": "…",
                  "createdAt": "…",
                  "messageId": "3EB0…"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "OTP status",
        "tags": [
          "v2 · OTP"
        ],
        "x-summary-ar": "حالة الـ OTP",
        "x-description-ar": "pending | verified | expired | locked | failed.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/otp/otp_8f2c1d9a7b3e4f56a1b2c3d4\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/otp/otp_8f2c1d9a7b3e4f56a1b2c3d4', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/otp/otp_8f2c1d9a7b3e4f56a1b2c3d4\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/otp/otp_8f2c1d9a7b3e4f56a1b2c3d4');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/widgets": {
      "get": {
        "description": "Scope: `widgets:read`.",
        "operationId": "widgets.list",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100 (default 25)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "wgt_k2m7q4x9a3b5c8d2",
                      "name": "Main website",
                      "enabled": true,
                      "numberId": "cm1abcd2345efgh6789ijkl",
                      "number": {
                        "name": "فرع المعادي",
                        "phone": "201001234567"
                      },
                      "allowedDomains": [
                        "example.com",
                        "*.example.com"
                      ],
                      "settings": {
                        "position": "end",
                        "color": "#25D366",
                        "buttonText": {
                          "ar": "كلمنا واتساب",
                          "en": "Chat with us"
                        },
                        "icon": "whatsapp",
                        "greeting": {
                          "enabled": true,
                          "title": {
                            "ar": "أهلاً 👋",
                            "en": "Hi 👋"
                          },
                          "text": {
                            "ar": "محتاج مساعدة؟",
                            "en": "Need help?"
                          },
                          "avatar": {
                            "type": "initial",
                            "initial": ""
                          }
                        },
                        "agents": [],
                        "message": {
                          "ar": "عندي سؤال عن {page_title}",
                          "en": "Question about {page_title}"
                        },
                        "attribution": {
                          "enabled": true,
                          "label": "ref",
                          "position": "end"
                        },
                        "branding": {
                          "show": true
                        },
                        "impressions": {
                          "enabled": false
                        }
                      },
                      "snippet": "<script async src=\"https://mursilat.com/w/v1.js\" data-widget=\"wgt_k2m7q4x9a3b5c8d2\"></script>",
                      "stats7d": {
                        "clicks": 120,
                        "conversations": 31
                      },
                      "createdAt": "2026-10-14T09:00:00.000Z",
                      "updatedAt": "2026-10-14T09:00:00.000Z"
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "List website buttons",
        "tags": [
          "v2 · Website button"
        ],
        "x-summary-ar": "قائمة زراير الموقع",
        "x-description-ar": "زراير الأرقام اللي المفتاح شايفها، الأحدث الأول، ومعاها ضغطات ومحادثات آخر 7 أيام.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/widgets?limit=25\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/widgets?limit=25', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/widgets?limit=25\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/widgets?limit=25');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "post": {
        "description": "numberId + allowedDomains (required) + optional settings. Plan limits: starter 1, growth 5, business unlimited.\n\nScope: `widgets:write`.",
        "operationId": "widgets.create",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "numberId",
                  "allowedDomains"
                ]
              },
              "examples": {
                "widgets.create": {
                  "summary": "Create a website button",
                  "value": {
                    "name": "Main website",
                    "numberId": "cm1abcd2345efgh6789ijkl",
                    "allowedDomains": [
                      "example.com"
                    ],
                    "settings": {
                      "buttonText": {
                        "ar": "كلمنا واتساب",
                        "en": "Chat with us"
                      },
                      "attribution": {
                        "enabled": true,
                        "label": "ref",
                        "position": "end"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "wgt_k2m7q4x9a3b5c8d2",
                  "name": "Main website",
                  "enabled": true,
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "number": {
                    "name": "فرع المعادي",
                    "phone": "201001234567"
                  },
                  "allowedDomains": [
                    "example.com",
                    "*.example.com"
                  ],
                  "settings": {
                    "position": "end",
                    "color": "#25D366",
                    "buttonText": {
                      "ar": "كلمنا واتساب",
                      "en": "Chat with us"
                    },
                    "icon": "whatsapp",
                    "greeting": {
                      "enabled": true,
                      "title": {
                        "ar": "أهلاً 👋",
                        "en": "Hi 👋"
                      },
                      "text": {
                        "ar": "محتاج مساعدة؟",
                        "en": "Need help?"
                      },
                      "avatar": {
                        "type": "initial",
                        "initial": ""
                      }
                    },
                    "agents": [],
                    "message": {
                      "ar": "عندي سؤال عن {page_title}",
                      "en": "Question about {page_title}"
                    },
                    "attribution": {
                      "enabled": true,
                      "label": "ref",
                      "position": "end"
                    },
                    "branding": {
                      "show": true
                    },
                    "impressions": {
                      "enabled": false
                    }
                  },
                  "snippet": "<script async src=\"https://mursilat.com/w/v1.js\" data-widget=\"wgt_k2m7q4x9a3b5c8d2\"></script>",
                  "stats7d": {
                    "clicks": 120,
                    "conversations": 31
                  },
                  "createdAt": "2026-10-14T09:00:00.000Z",
                  "updatedAt": "2026-10-14T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: WIDGET_LIMIT_REACHED, WIDGET_DOMAINS_REQUIRED, WIDGET_DOMAIN_INVALID, WIDGET_DOMAINS_TOO_MANY, WIDGET_NUMBER_INVALID, WIDGET_NUMBER_NO_PHONE, WIDGET_SETTINGS_INVALID, WIDGET_BRANDING_LOCKED, WIDGET_NAME_INVALID, NUMBER_NOT_ALLOWED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Create a website button",
        "tags": [
          "v2 · Website button"
        ],
        "x-summary-ar": "إنشاء زرار موقع",
        "x-description-ar": "numberId و allowedDomains مطلوبين؛ الإعدادات اختيارية (نفس افتراضيات لوحة التحكم). الرد فيه كود التضمين. حدود الباقات: البداية 1، النمو 5، الأعمال بلا حدود؛ وإخفاء «مدعوم من مرسلات» محتاج النمو أو أعلى.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/widgets\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"name\": \"Main website\",\n  \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n  \"allowedDomains\": [\n    \"example.com\"\n  ],\n  \"settings\": {\n    \"buttonText\": {\n      \"ar\": \"كلمنا واتساب\",\n      \"en\": \"Chat with us\"\n    },\n    \"attribution\": {\n      \"enabled\": true,\n      \"label\": \"ref\",\n      \"position\": \"end\"\n    }\n  }\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/widgets', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"name\": \"Main website\",\n    \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n    \"allowedDomains\": [\n      \"example.com\"\n    ],\n    \"settings\": {\n      \"buttonText\": {\n        \"ar\": \"كلمنا واتساب\",\n        \"en\": \"Chat with us\"\n      },\n      \"attribution\": {\n        \"enabled\": true,\n        \"label\": \"ref\",\n        \"position\": \"end\"\n      }\n    }\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/widgets\",\n    headers=headers,\n    json={\n        \"name\": \"Main website\",\n        \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n        \"allowedDomains\": [\n            \"example.com\"\n        ],\n        \"settings\": {\n            \"buttonText\": {\n                \"ar\": \"كلمنا واتساب\",\n                \"en\": \"Chat with us\"\n            },\n            \"attribution\": {\n                \"enabled\": True,\n                \"label\": \"ref\",\n                \"position\": \"end\"\n            }\n        }\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/widgets');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'name' => 'Main website',\n        'numberId' => 'cm1abcd2345efgh6789ijkl',\n        'allowedDomains' => [\n            'example.com'\n        ],\n        'settings' => [\n            'buttonText' => [\n                'ar' => 'كلمنا واتساب',\n                'en' => 'Chat with us'\n            ],\n            'attribution' => [\n                'enabled' => true,\n                'label' => 'ref',\n                'position' => 'end'\n            ]\n        ]\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/widgets/{widgetId}": {
      "get": {
        "description": "Scope: `widgets:read`.",
        "operationId": "widgets.get",
        "parameters": [
          {
            "name": "widgetId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "wgt_k2m7q4x9a3b5c8d2",
                  "name": "Main website",
                  "enabled": true,
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "number": {
                    "name": "فرع المعادي",
                    "phone": "201001234567"
                  },
                  "allowedDomains": [
                    "example.com",
                    "*.example.com"
                  ],
                  "settings": {
                    "position": "end",
                    "color": "#25D366",
                    "buttonText": {
                      "ar": "كلمنا واتساب",
                      "en": "Chat with us"
                    },
                    "icon": "whatsapp",
                    "greeting": {
                      "enabled": true,
                      "title": {
                        "ar": "أهلاً 👋",
                        "en": "Hi 👋"
                      },
                      "text": {
                        "ar": "محتاج مساعدة؟",
                        "en": "Need help?"
                      },
                      "avatar": {
                        "type": "initial",
                        "initial": ""
                      }
                    },
                    "agents": [],
                    "message": {
                      "ar": "عندي سؤال عن {page_title}",
                      "en": "Question about {page_title}"
                    },
                    "attribution": {
                      "enabled": true,
                      "label": "ref",
                      "position": "end"
                    },
                    "branding": {
                      "show": true
                    },
                    "impressions": {
                      "enabled": false
                    }
                  },
                  "snippet": "<script async src=\"https://mursilat.com/w/v1.js\" data-widget=\"wgt_k2m7q4x9a3b5c8d2\"></script>",
                  "stats7d": {
                    "clicks": 120,
                    "conversations": 31
                  },
                  "createdAt": "2026-10-14T09:00:00.000Z",
                  "updatedAt": "2026-10-14T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: WIDGET_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Get a website button",
        "tags": [
          "v2 · Website button"
        ],
        "x-summary-ar": "تفاصيل زرار موقع",
        "x-description-ar": "الإعدادات والدومينات وكود التضمين وأرقام آخر 7 أيام.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/widgets/widgetId\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/widgets/widgetId', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/widgets/widgetId\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/widgets/widgetId');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "patch": {
        "description": "Scope: `widgets:write`.",
        "operationId": "widgets.update",
        "parameters": [
          {
            "name": "widgetId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "wgt_k2m7q4x9a3b5c8d2",
                  "name": "Main website",
                  "enabled": false,
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "number": {
                    "name": "فرع المعادي",
                    "phone": "201001234567"
                  },
                  "allowedDomains": [
                    "example.com",
                    "*.example.com"
                  ],
                  "settings": {
                    "position": "end",
                    "color": "#25D366",
                    "buttonText": {
                      "ar": "كلمنا واتساب",
                      "en": "Chat with us"
                    },
                    "icon": "whatsapp",
                    "greeting": {
                      "enabled": true,
                      "title": {
                        "ar": "أهلاً 👋",
                        "en": "Hi 👋"
                      },
                      "text": {
                        "ar": "محتاج مساعدة؟",
                        "en": "Need help?"
                      },
                      "avatar": {
                        "type": "initial",
                        "initial": ""
                      }
                    },
                    "agents": [],
                    "message": {
                      "ar": "عندي سؤال عن {page_title}",
                      "en": "Question about {page_title}"
                    },
                    "attribution": {
                      "enabled": true,
                      "label": "ref",
                      "position": "end"
                    },
                    "branding": {
                      "show": true
                    },
                    "impressions": {
                      "enabled": false
                    }
                  },
                  "snippet": "<script async src=\"https://mursilat.com/w/v1.js\" data-widget=\"wgt_k2m7q4x9a3b5c8d2\"></script>",
                  "stats7d": {
                    "clicks": 120,
                    "conversations": 31
                  },
                  "createdAt": "2026-10-14T09:00:00.000Z",
                  "updatedAt": "2026-10-14T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: WIDGET_NOT_FOUND, WIDGET_LIMIT_REACHED, WIDGET_DOMAINS_REQUIRED, WIDGET_DOMAIN_INVALID, WIDGET_DOMAINS_TOO_MANY, WIDGET_NUMBER_INVALID, WIDGET_NUMBER_NO_PHONE, WIDGET_SETTINGS_INVALID, WIDGET_BRANDING_LOCKED, WIDGET_NAME_INVALID, NUMBER_NOT_ALLOWED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Update a website button",
        "tags": [
          "v2 · Website button"
        ],
        "x-summary-ar": "تعديل زرار موقع",
        "x-description-ar": "أي من name و enabled و numberId و allowedDomains و settings (الإعدادات بتتبعت كاملة وبتحل محل القديمة؛ الزرار بيتحدّث على المواقع خلال 5 دقايق).",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PATCH \"https://mursilat.com/api/v2/widgets/widgetId\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"enabled\": false\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/widgets/widgetId', {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"enabled\": false\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.patch(\n    \"https://mursilat.com/api/v2/widgets/widgetId\",\n    headers=headers,\n    json={\n        \"enabled\": False\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/widgets/widgetId');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PATCH',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'enabled' => false\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "examples": {
                "widgets.update": {
                  "summary": "Update a website button",
                  "value": {
                    "enabled": false
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "description": "Scope: `widgets:write`.",
        "operationId": "widgets.delete",
        "parameters": [
          {
            "name": "widgetId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "wgt_k2m7q4x9a3b5c8d2",
                  "deleted": true
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: WIDGET_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Delete a website button",
        "tags": [
          "v2 · Website button"
        ],
        "x-summary-ar": "مسح زرار موقع",
        "x-description-ar": "الكود بيبطّل يظهر، وضغطاته وإحصائياته بتتمسح.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/widgets/widgetId\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/widgets/widgetId', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/widgets/widgetId\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/widgets/widgetId');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/widgets/{widgetId}/stats": {
      "get": {
        "description": "Scope: `widgets:read`.",
        "operationId": "widgets.stats",
        "parameters": [
          {
            "name": "widgetId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "YYYY-MM-DD (default: 30 days before `to`)",
            "schema": {}
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "YYYY-MM-DD (default: today), at most 92 days",
            "schema": {}
          },
          {
            "name": "tz",
            "required": false,
            "in": "query",
            "description": "IANA time zone of the days (default Africa/Cairo)",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "range": {
                    "from": "2026-10-01",
                    "to": "2026-10-14",
                    "tz": "Africa/Cairo"
                  },
                  "totals": {
                    "impressions": null,
                    "clicks": 40,
                    "conversations": 12,
                    "conversionRate": 0.3
                  },
                  "byDay": [
                    {
                      "day": "2026-10-14",
                      "impressions": 0,
                      "clicks": 3,
                      "conversations": 1
                    }
                  ],
                  "byPage": [
                    {
                      "key": "/products/bag",
                      "clicks": 10,
                      "conversations": 3
                    }
                  ],
                  "bySource": [
                    {
                      "key": "facebook / cpc",
                      "source": "facebook",
                      "medium": "cpc",
                      "clicks": 5,
                      "conversations": 2
                    }
                  ],
                  "byCampaign": [
                    {
                      "key": "summer",
                      "clicks": 4,
                      "conversations": 1
                    }
                  ],
                  "byAgent": [
                    {
                      "key": "sales",
                      "clicks": 4,
                      "conversations": 1
                    }
                  ],
                  "byDevice": [
                    {
                      "key": "mobile",
                      "clicks": 30,
                      "conversations": 9
                    }
                  ],
                  "byReferrer": [
                    {
                      "key": "facebook.com",
                      "clicks": 4,
                      "conversations": 1
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: WIDGET_NOT_FOUND, STATS_RANGE_INVALID (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Website button statistics",
        "tags": [
          "v2 · Website button"
        ],
        "x-summary-ar": "إحصائيات زرار الموقع",
        "x-description-ar": "مرات الظهور (لو مفعّلة، بالعينة)، الضغطات، المحادثات المنسوبة ونسبة التحويل — باليوم والصفحة ومصدر/وسيلة utm والحملة والموظف والجهاز ودومين المصدر. أرقام بس.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/widgets/widgetId/stats?from=2026-10-01&to=2026-10-14\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/widgets/widgetId/stats?from=2026-10-01&to=2026-10-14', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/widgets/widgetId/stats?from=2026-10-01&to=2026-10-14\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/widgets/widgetId/stats?from=2026-10-01&to=2026-10-14');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/links": {
      "get": {
        "description": "Scope: `links:read`.",
        "operationId": "links.list",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "1–100 (default 25)",
            "schema": {}
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "nextCursor of the previous page",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "cm9link0001",
                      "name": "Instagram bio",
                      "slug": "k7m2xq9prw",
                      "customSlug": false,
                      "url": "https://mursilat.com/l/k7m2xq9prw",
                      "numberId": "cm1abcd2345efgh6789ijkl",
                      "number": {
                        "name": "فرع المعادي",
                        "phone": "201001234567"
                      },
                      "message": "عايز أعرف الأسعار",
                      "utm": {
                        "source": "instagram",
                        "medium": "bio",
                        "campaign": "",
                        "content": "",
                        "term": ""
                      },
                      "attribution": {
                        "enabled": true,
                        "label": "ref",
                        "position": "end"
                      },
                      "enabled": true,
                      "stats7d": {
                        "clicks": 64,
                        "conversations": 18
                      },
                      "createdAt": "2026-10-14T09:00:00.000Z",
                      "updatedAt": "2026-10-14T09:00:00.000Z"
                    }
                  ],
                  "nextCursor": null
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: see the error catalog (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "List tracked WhatsApp links",
        "tags": [
          "v2 · WhatsApp links"
        ],
        "x-summary-ar": "قائمة روابط واتساب",
        "x-description-ar": "روابط الأرقام اللي المفتاح شايفها، الأحدث الأول.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/links?limit=25\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/links?limit=25', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/links?limit=25\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/links?limit=25');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "post": {
        "description": "numberId + optional message, utm defaults, custom slug and attribution. Plan limits: starter 3, growth 50, business unlimited.\n\nScope: `links:write`.",
        "operationId": "links.create",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "numberId"
                ]
              },
              "examples": {
                "links.create": {
                  "summary": "Create a tracked WhatsApp link",
                  "value": {
                    "name": "Instagram bio",
                    "numberId": "cm1abcd2345efgh6789ijkl",
                    "message": "عايز أعرف الأسعار",
                    "utm": {
                      "source": "instagram",
                      "medium": "bio"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm9link0001",
                  "name": "Instagram bio",
                  "slug": "k7m2xq9prw",
                  "customSlug": false,
                  "url": "https://mursilat.com/l/k7m2xq9prw",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "number": {
                    "name": "فرع المعادي",
                    "phone": "201001234567"
                  },
                  "message": "عايز أعرف الأسعار",
                  "utm": {
                    "source": "instagram",
                    "medium": "bio",
                    "campaign": "",
                    "content": "",
                    "term": ""
                  },
                  "attribution": {
                    "enabled": true,
                    "label": "ref",
                    "position": "end"
                  },
                  "enabled": true,
                  "stats7d": {
                    "clicks": 64,
                    "conversations": 18
                  },
                  "createdAt": "2026-10-14T09:00:00.000Z",
                  "updatedAt": "2026-10-14T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: LINK_LIMIT_REACHED, LINK_CUSTOM_SLUG_PLAN, LINK_SLUG_INVALID, LINK_SLUG_RESERVED, LINK_SLUG_TAKEN, LINK_NUMBER_INVALID, LINK_NUMBER_NO_PHONE, LINK_FIELD_INVALID, NUMBER_NOT_ALLOWED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Create a tracked WhatsApp link",
        "tags": [
          "v2 · WhatsApp links"
        ],
        "x-summary-ar": "إنشاء رابط واتساب متتبَّع",
        "x-description-ar": "https://mursilat.com/l/<slug> بيسجل ضغطة مجهولة ويحوّل (302) لـ wa.me بالرسالة الجاهزة + الكود — ومش لأي مكان تاني أبدًا. الاسم: 10 حروف عشوائية (صعب تخمينها) أو كلمة تختارها. قيم utm_* على الرابط بتغطي على الافتراضي. أكواد QR (SVG / PNG) في لوحة التحكم.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://mursilat.com/api/v2/links\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"name\": \"Instagram bio\",\n  \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n  \"message\": \"عايز أعرف الأسعار\",\n  \"utm\": {\n    \"source\": \"instagram\",\n    \"medium\": \"bio\"\n  }\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/links', {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"name\": \"Instagram bio\",\n    \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n    \"message\": \"عايز أعرف الأسعار\",\n    \"utm\": {\n      \"source\": \"instagram\",\n      \"medium\": \"bio\"\n    }\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.post(\n    \"https://mursilat.com/api/v2/links\",\n    headers=headers,\n    json={\n        \"name\": \"Instagram bio\",\n        \"numberId\": \"cm1abcd2345efgh6789ijkl\",\n        \"message\": \"عايز أعرف الأسعار\",\n        \"utm\": {\n            \"source\": \"instagram\",\n            \"medium\": \"bio\"\n        }\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/links');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'POST',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'name' => 'Instagram bio',\n        'numberId' => 'cm1abcd2345efgh6789ijkl',\n        'message' => 'عايز أعرف الأسعار',\n        'utm' => [\n            'source' => 'instagram',\n            'medium' => 'bio'\n        ]\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/links/{linkId}": {
      "get": {
        "description": "Scope: `links:read`.",
        "operationId": "links.get",
        "parameters": [
          {
            "name": "linkId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm9link0001",
                  "name": "Instagram bio",
                  "slug": "k7m2xq9prw",
                  "customSlug": false,
                  "url": "https://mursilat.com/l/k7m2xq9prw",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "number": {
                    "name": "فرع المعادي",
                    "phone": "201001234567"
                  },
                  "message": "عايز أعرف الأسعار",
                  "utm": {
                    "source": "instagram",
                    "medium": "bio",
                    "campaign": "",
                    "content": "",
                    "term": ""
                  },
                  "attribution": {
                    "enabled": true,
                    "label": "ref",
                    "position": "end"
                  },
                  "enabled": true,
                  "stats7d": {
                    "clicks": 64,
                    "conversations": 18
                  },
                  "createdAt": "2026-10-14T09:00:00.000Z",
                  "updatedAt": "2026-10-14T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: LINK_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Get a tracked link",
        "tags": [
          "v2 · WhatsApp links"
        ],
        "x-summary-ar": "تفاصيل رابط",
        "x-description-ar": "الرابط والرسالة الجاهزة وقيم utm وأرقام آخر 7 أيام.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/links/linkId\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/links/linkId', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/links/linkId\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/links/linkId');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      },
      "patch": {
        "description": "Scope: `links:write`.",
        "operationId": "links.update",
        "parameters": [
          {
            "name": "linkId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm9link0001",
                  "name": "Instagram bio",
                  "slug": "k7m2xq9prw",
                  "customSlug": false,
                  "url": "https://mursilat.com/l/k7m2xq9prw",
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "number": {
                    "name": "فرع المعادي",
                    "phone": "201001234567"
                  },
                  "message": "عايز أعرف الأسعار",
                  "utm": {
                    "source": "instagram",
                    "medium": "bio",
                    "campaign": "",
                    "content": "",
                    "term": ""
                  },
                  "attribution": {
                    "enabled": true,
                    "label": "ref",
                    "position": "end"
                  },
                  "enabled": false,
                  "stats7d": {
                    "clicks": 64,
                    "conversations": 18
                  },
                  "createdAt": "2026-10-14T09:00:00.000Z",
                  "updatedAt": "2026-10-14T09:00:00.000Z"
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: LINK_NOT_FOUND, LINK_LIMIT_REACHED, LINK_CUSTOM_SLUG_PLAN, LINK_SLUG_INVALID, LINK_SLUG_RESERVED, LINK_SLUG_TAKEN, LINK_NUMBER_INVALID, LINK_NUMBER_NO_PHONE, LINK_FIELD_INVALID, NUMBER_NOT_ALLOWED (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Update a tracked link",
        "tags": [
          "v2 · WhatsApp links"
        ],
        "x-summary-ar": "تعديل رابط",
        "x-description-ar": "أي من name و numberId و message و utm و slug (null = اسم عشوائي جديد) و attribution و enabled (الرابط المتوقف بيرد 410).",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PATCH \"https://mursilat.com/api/v2/links/linkId\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"enabled\": false\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/links/linkId', {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"enabled\": false\n  }),\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.patch(\n    \"https://mursilat.com/api/v2/links/linkId\",\n    headers=headers,\n    json={\n        \"enabled\": False\n    },\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/links/linkId');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'PATCH',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n        'Content-Type: application/json',\n    ],\n    CURLOPT_POSTFIELDS => json_encode([\n        'enabled' => false\n    ], JSON_UNESCAPED_UNICODE),\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "examples": {
                "links.update": {
                  "summary": "Update a tracked link",
                  "value": {
                    "enabled": false
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "description": "Scope: `links:write`.",
        "operationId": "links.delete",
        "parameters": [
          {
            "name": "linkId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "id": "cm9link0001",
                  "deleted": true
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: LINK_NOT_FOUND (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Delete a tracked link",
        "tags": [
          "v2 · WhatsApp links"
        ],
        "x-summary-ar": "مسح رابط",
        "x-description-ar": "الرابط بيبطّل يشتغل (404)، والضغطات والإحصائيات بتتمسح.",
        "x-idempotency": "optional",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X DELETE \"https://mursilat.com/api/v2/links/linkId\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\" \\\n  -H \"Idempotency-Key: order-1042-confirm\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/links/linkId', {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n    'Idempotency-Key': 'order-1042-confirm',\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\", \"Idempotency-Key\": \"order-1042-confirm\"}\nres = requests.delete(\n    \"https://mursilat.com/api/v2/links/linkId\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/links/linkId');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'DELETE',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n        'Idempotency-Key: order-1042-confirm',\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    },
    "/api/v2/links/{linkId}/stats": {
      "get": {
        "description": "Scope: `links:read`.",
        "operationId": "links.stats",
        "parameters": [
          {
            "name": "linkId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "YYYY-MM-DD (default: 30 days before `to`)",
            "schema": {}
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "YYYY-MM-DD (default: today), at most 92 days",
            "schema": {}
          },
          {
            "name": "tz",
            "required": false,
            "in": "query",
            "description": "IANA time zone of the days (default Africa/Cairo)",
            "schema": {}
          },
          {
            "in": "header",
            "name": "X-Request-Id",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional; echoed back"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "range": {
                    "from": "2026-10-01",
                    "to": "2026-10-14",
                    "tz": "Africa/Cairo"
                  },
                  "totals": {
                    "impressions": null,
                    "clicks": 40,
                    "conversations": 12,
                    "conversionRate": 0.3
                  },
                  "byDay": [
                    {
                      "day": "2026-10-14",
                      "impressions": 0,
                      "clicks": 3,
                      "conversations": 1
                    }
                  ],
                  "byPage": [
                    {
                      "key": "/products/bag",
                      "clicks": 10,
                      "conversations": 3
                    }
                  ],
                  "bySource": [
                    {
                      "key": "facebook / cpc",
                      "source": "facebook",
                      "medium": "cpc",
                      "clicks": 5,
                      "conversations": 2
                    }
                  ],
                  "byCampaign": [
                    {
                      "key": "summer",
                      "clicks": 4,
                      "conversations": 1
                    }
                  ],
                  "byAgent": [
                    {
                      "key": "sales",
                      "clicks": 4,
                      "conversations": 1
                    }
                  ],
                  "byDevice": [
                    {
                      "key": "mobile",
                      "clicks": 30,
                      "conversations": 9
                    }
                  ],
                  "byReferrer": [
                    {
                      "key": "facebook.com",
                      "clicks": 4,
                      "conversations": 1
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Client error. Codes: LINK_NOT_FOUND, STATS_RANGE_INVALID (and the auth / rate-limit codes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "default": {
            "description": "Server error (INTERNAL_ERROR) or temporary unavailability.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {
            "wasla-api-key": []
          }
        ],
        "summary": "Tracked link statistics",
        "tags": [
          "v2 · WhatsApp links"
        ],
        "x-summary-ar": "إحصائيات الرابط",
        "x-description-ar": "الضغطات والمحادثات المنسوبة ونسبة التحويل باليوم ومصدر/وسيلة utm والحملة والجهاز ودومين المصدر.",
        "x-idempotency": "none",
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X GET \"https://mursilat.com/api/v2/links/linkId/stats?from=2026-10-01&to=2026-10-14\" \\\n  -H \"Authorization: Bearer $WASLA_API_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "Node",
            "source": "const res = await fetch('https://mursilat.com/api/v2/links/linkId/stats?from=2026-10-01&to=2026-10-14', {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.WASLA_API_KEY}`,\n  },\n});\nconst data = await res.json();\nif (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);\nconsole.log(data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nheaders = {\"Authorization\": f\"Bearer {os.environ['WASLA_API_KEY']}\"}\nres = requests.get(\n    \"https://mursilat.com/api/v2/links/linkId/stats?from=2026-10-01&to=2026-10-14\",\n    headers=headers,\n    timeout=30,\n)\ndata = res.json()\nif not res.ok:\n    raise RuntimeError(f\"{data['error']['code']}: {data['error']['message']}\")\nprint(data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init('https://mursilat.com/api/v2/links/linkId/stats?from=2026-10-01&to=2026-10-14');\ncurl_setopt_array($ch, [\n    CURLOPT_CUSTOMREQUEST => 'GET',\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_HTTPHEADER => [\n        'Authorization: Bearer ' . getenv('WASLA_API_KEY'),\n    ],\n]);\n$data = json_decode(curl_exec($ch), true);\n$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\nif ($status >= 400) { throw new Exception($data['error']['code'] . ': ' . $data['error']['message']); }\nprint_r($data);"
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "wasla-api-key": {
        "scheme": "bearer",
        "bearerFormat": "wsl_live_…",
        "type": "http",
        "description": "Account API key (Settings → API keys)"
      },
      "x-api-key": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Legacy number key — message endpoints of its own number only"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "docsUrl"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "OTP_ACCOUNT_RATE_LIMITED",
                  "SCHEDULE_LIMIT_REACHED",
                  "AUTO_REPLY_ACCOUNT_WIDE_READ_ONLY",
                  "ENCRYPTION_NOT_CONFIGURED",
                  "API_KEY_REQUIRED",
                  "API_KEY_INVALID",
                  "API_KEY_REVOKED",
                  "API_KEY_EXPIRED",
                  "ACCOUNT_KEY_REQUIRED",
                  "AUTH_TOO_MANY_FAILURES",
                  "IP_NOT_ALLOWED",
                  "SCOPE_REQUIRED",
                  "NUMBER_NOT_ALLOWED",
                  "KEY_NUMBER_RESTRICTED",
                  "RATE_LIMITED",
                  "API_TEMPORARY_BAN",
                  "IMPERSONATION_ACTION_FORBIDDEN",
                  "API_V2_NOT_CONFIGURED",
                  "API_KEY_NAME_INVALID",
                  "API_KEY_SCOPES_INVALID",
                  "API_KEY_NUMBERS_INVALID",
                  "API_KEY_IP_ALLOWLIST_INVALID",
                  "API_KEY_EXPIRY_INVALID",
                  "API_KEY_GRACE_INVALID",
                  "API_KEY_LIMIT_REACHED",
                  "API_KEY_NOT_FOUND",
                  "VALIDATION_FAILED",
                  "IDEMPOTENCY_KEY_REQUIRED",
                  "IDEMPOTENCY_KEY_INVALID",
                  "IDEMPOTENCY_KEY_REUSED",
                  "IDEMPOTENCY_IN_PROGRESS",
                  "PAGINATION_LIMIT_INVALID",
                  "PAGINATION_CURSOR_INVALID",
                  "ROUTE_NOT_FOUND",
                  "UNSUPPORTED_CONTENT_TYPE",
                  "CONFIRMATION_REQUIRED",
                  "NUMBER_NOT_FOUND",
                  "NUMBER_ID_REQUIRED",
                  "NUMBER_ALREADY_CONNECTED",
                  "NUMBER_NOT_PAIRING",
                  "PAIRING_CODE_UNAVAILABLE",
                  "PAIRING_CODE_FAILED",
                  "NUMBER_BANNED",
                  "NUMBER_NOT_CONNECTED",
                  "SESSION_NOT_CONNECTED",
                  "SESSION_OWNED_BY_OTHER_INSTANCE",
                  "PLAN_NUMBERS_LIMIT_REACHED",
                  "CONTACT_CHECK_TOO_MANY",
                  "INVALID_RECIPIENT",
                  "MESSAGE_NOT_FOUND",
                  "MESSAGE_NOT_SENT_YET",
                  "MESSAGE_NOT_CANCELLABLE",
                  "SCHEDULING_DISABLED",
                  "SCHEDULE_AT_INVALID",
                  "SCHEDULE_MEDIA_URL_ONLY",
                  "SCHEDULING_UNAVAILABLE",
                  "MESSAGE_TYPE_REQUIRED",
                  "MESSAGE_TYPE_NOT_SUPPORTED",
                  "MESSAGE_FIELD_REQUIRED",
                  "MESSAGE_FIELD_INVALID",
                  "MESSAGE_TEXT_TOO_LONG",
                  "MESSAGE_UNEXPECTED_FIELD",
                  "MESSAGE_MEDIA_REQUIRED",
                  "MESSAGE_MEDIA_NOT_FOUND",
                  "MESSAGE_MEDIA_EXPIRED",
                  "MESSAGE_MEDIA_TOO_LARGE",
                  "MESSAGE_MEDIA_TYPE_NOT_ALLOWED",
                  "MESSAGE_MEDIA_FETCH_FAILED",
                  "MESSAGE_STICKER_INVALID",
                  "MESSAGE_VIDEO_NOTE_TOO_LONG",
                  "MESSAGE_POLL_INVALID",
                  "MESSAGE_CONTACT_INVALID",
                  "MESSAGE_LOCATION_INVALID",
                  "MESSAGE_EVENT_INVALID",
                  "MESSAGE_MENTIONS_GROUP_ONLY",
                  "MESSAGE_REPLY_TARGET_NOT_FOUND",
                  "MESSAGE_REACTION_INVALID",
                  "MESSAGE_NOT_EDITABLE",
                  "MESSAGE_EDIT_WINDOW_PASSED",
                  "MESSAGE_NOT_DELETABLE",
                  "MESSAGE_DELETE_WINDOW_PASSED",
                  "INTERACTIVE_INVALID",
                  "INTERACTIVE_RESERVED_TITLE",
                  "MESSAGES_QUOTA_EXCEEDED",
                  "CAMPAIGN_NOT_FOUND",
                  "CAMPAIGN_OPT_IN_REQUIRED",
                  "CAMPAIGN_CONTENT_INVALID",
                  "CAMPAIGN_RECIPIENTS_REQUIRED",
                  "CAMPAIGN_TOO_MANY_RECIPIENTS",
                  "CAMPAIGN_NO_RECIPIENTS",
                  "CAMPAIGN_NOT_DRAFT",
                  "CAMPAIGN_ACTIVE",
                  "CAMPAIGN_NOT_CANCELLABLE",
                  "CAMPAIGN_RESUME_BLOCKED",
                  "CAMPAIGN_STATE_CHANGED",
                  "CAMPAIGN_PURGED",
                  "URL_SHORTENER",
                  "FEATURE_NOT_IN_PLAN",
                  "AUTO_REPLIES_NOT_IN_PLAN",
                  "AUTO_REPLY_NOT_FOUND",
                  "AUTO_REPLY_KEYWORDS_REQUIRED",
                  "AUTO_REPLY_PATTERNS_REQUIRED",
                  "AUTO_REPLY_REGEX_INVALID",
                  "AUTO_REPLY_REGEX_TOO_MANY_PATTERNS",
                  "AUTO_REPLY_REGEX_RULE_LIMIT",
                  "AUTO_REPLY_REGEX_ENGINE_UNAVAILABLE",
                  "AUTO_REPLY_SCHEDULE_REQUIRED",
                  "INVALID_SCHEDULE",
                  "AUTO_REPLY_DELAY_INVALID",
                  "OTP_INPUT_INVALID",
                  "OTP_RECIPIENT_RATE_LIMITED",
                  "OTP_VERIFY_RATE_LIMITED",
                  "OTP_NOT_FOUND",
                  "SAFETY_DAILY_CAP_REACHED",
                  "SAFETY_HOURLY_CAP_REACHED",
                  "SAFETY_PACING",
                  "SAFETY_NUMBER_BUSY",
                  "SAFETY_QUIET_HOURS",
                  "SAFETY_NUMBER_PAUSED",
                  "SAFETY_NUMBER_BANNED",
                  "SAFETY_SUPPRESSED",
                  "SAFETY_CONTENT_BLOCKED",
                  "ACCOUNT_DAILY_CAP_REACHED",
                  "ACCOUNT_COD_CAP_REACHED",
                  "ACCOUNT_RESTRICTED",
                  "ACCOUNT_NUMBER_ROTATION",
                  "CONTENT_PROHIBITED",
                  "LIST_QUALITY_LOW",
                  "AUP_NOT_ACCEPTED",
                  "SESSION_PHONE_UNKNOWN",
                  "NUMBER_NOT_CONNECTED_YET",
                  "NUMBER_PAUSE_NOT_YOURS",
                  "LIMITS_INVALID",
                  "STATS_RANGE_INVALID",
                  "GROUPS_NOT_IN_PLAN",
                  "GROUPS_UNAVAILABLE",
                  "GROUP_ID_INVALID",
                  "GROUP_NOT_FOUND",
                  "WEBHOOKS_NOT_IN_PLAN",
                  "WEBHOOK_URL_NOT_SET",
                  "WEBHOOK_DISABLED",
                  "WEBHOOK_EVENTS_INVALID",
                  "WEBHOOK_VERSION_INVALID",
                  "WEBHOOK_DELIVERY_NOT_FOUND",
                  "DELIVERY_PAYLOAD_EXPIRED",
                  "NO_NUMBER",
                  "URL_PRIVATE_ADDRESS",
                  "URL_PORT_NOT_ALLOWED",
                  "WIDGET_LIMIT_REACHED",
                  "LINK_LIMIT_REACHED",
                  "WIDGET_NOT_FOUND",
                  "LINK_NOT_FOUND",
                  "WIDGET_DOMAINS_REQUIRED",
                  "WIDGET_DOMAIN_INVALID",
                  "WIDGET_DOMAINS_TOO_MANY",
                  "WIDGET_NUMBER_INVALID",
                  "WIDGET_NUMBER_NO_PHONE",
                  "WIDGET_SETTINGS_INVALID",
                  "WIDGET_BRANDING_LOCKED",
                  "WIDGET_NAME_INVALID",
                  "LINK_SLUG_INVALID",
                  "LINK_SLUG_RESERVED",
                  "LINK_SLUG_TAKEN",
                  "LINK_NUMBER_INVALID",
                  "LINK_NUMBER_NO_PHONE",
                  "LINK_FIELD_INVALID",
                  "WIDGET_ORIGIN_NOT_ALLOWED",
                  "WIDGET_CLICK_RATE_LIMITED",
                  "LINK_CUSTOM_SLUG_PLAN",
                  "WIDGET_RATE_LIMITED",
                  "API_ACCESS_NOT_IN_PLAN",
                  "NO_ACTIVE_PLAN",
                  "USER_SUSPENDED",
                  "INTERNAL_ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "additionalProperties": true
              },
              "docsUrl": {
                "type": "string",
                "format": "uri"
              },
              "requestId": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "message.received": {
      "post": {
        "operationId": "webhook_message_received",
        "security": [],
        "summary": "message.received event",
        "description": "A customer sent a message to the number (content goes only to your webhook, live). Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "message.received",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "messageId": "3EB0C1D2E3F4A5B6C7D8",
                  "from": {
                    "phone": "201099887766",
                    "lid": null,
                    "name": "منى"
                  },
                  "chat": {
                    "type": "direct"
                  },
                  "type": "text",
                  "text": "عايز أعرف السعر",
                  "caption": null,
                  "media": null,
                  "location": null,
                  "replyTo": null,
                  "timestamp": "2026-10-13T08:00:02.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "message.status": {
      "post": {
        "operationId": "webhook_message_status",
        "security": [],
        "summary": "message.status event",
        "description": "A message sent by the API / dashboard was sent, delivered, read or failed. Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "message.status",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "messageId": "3EB0A1B2C3D4E5F60718",
                  "reference": "order-1042",
                  "to": "201099887766",
                  "status": "delivered",
                  "error": null,
                  "timestamp": "2026-10-13T08:00:05.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "interactive.reply": {
      "post": {
        "operationId": "webhook_interactive_reply",
        "security": [],
        "summary": "interactive.reply event",
        "description": "A customer answered buttons / a list (tap or typed number/title). Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "interactive.reply",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "interactionId": "int_8f2c1d9a7b3e4f56a1b2c3d4",
                  "messageId": "3EB0A1B2C3D4E5F60718",
                  "reference": "order-1042",
                  "from": {
                    "phone": "201099887766",
                    "lid": null,
                    "name": "منى"
                  },
                  "reply": {
                    "id": "confirm",
                    "title": "تأكيد",
                    "index": 1,
                    "source": "button"
                  },
                  "replyMessageId": "3EB0FFEE0011223344",
                  "timestamp": "2026-10-13T08:03:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "poll.vote": {
      "post": {
        "operationId": "webhook_poll_vote",
        "security": [],
        "summary": "poll.vote event",
        "description": "A customer voted on a poll sent by the number. Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "poll.vote",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "messageId": "3EB0A1B2C3D4E5F60718",
                  "reference": "survey-7",
                  "from": {
                    "phone": "201099887766",
                    "lid": null,
                    "name": "منى"
                  },
                  "selectedOptions": [
                    "الأحد"
                  ],
                  "timestamp": "2026-10-13T08:04:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "contact.opted_out": {
      "post": {
        "operationId": "webhook_contact_opted_out",
        "security": [],
        "summary": "contact.opted_out event",
        "description": "A customer sent an opt-out keyword (now suppressed). Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "contact.opted_out",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "phone": "201099887766",
                  "lid": null,
                  "keyword": "إلغاء",
                  "timestamp": "2026-10-13T08:05:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "contact.opted_in": {
      "post": {
        "operationId": "webhook_contact_opted_in",
        "security": [],
        "summary": "contact.opted_in event",
        "description": "You removed a customer from the suppression list. Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "contact.opted_in",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "phone": "201099887766",
                  "lid": null,
                  "keyword": null,
                  "timestamp": "2026-10-13T09:00:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "session.status": {
      "post": {
        "operationId": "webhook_session_status",
        "security": [],
        "summary": "session.status event",
        "description": "Legacy connection event (connected / disconnected / banned / logged_out). Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "session.status",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "status": "disconnected",
                  "reason": null,
                  "timestamp": "2026-10-13T10:00:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "number.status": {
      "post": {
        "operationId": "webhook_number_status",
        "security": [],
        "summary": "number.status event",
        "description": "Connection of a number changed: connected, disconnected, pairing (QR), banned, logged_out, conflict. Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "number.status",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "status": "connected",
                  "reason": null,
                  "timestamp": "2026-10-13T08:00:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "number.restricted": {
      "post": {
        "operationId": "webhook_number_restricted",
        "security": [],
        "summary": "number.restricted event",
        "description": "WhatsApp restricted (or lifted the restriction on) messaging new contacts for the number. Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "number.restricted",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "numberId": "cm1abcd2345efgh6789ijkl",
                  "restricted": true,
                  "until": "2026-10-14T08:00:00.000Z",
                  "type": "reachout_timelock",
                  "timestamp": "2026-10-13T08:00:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "campaign.status": {
      "post": {
        "operationId": "webhook_campaign_status",
        "security": [],
        "summary": "campaign.status event",
        "description": "A campaign started, paused, resumed, completed, failed or was cancelled (with reason). Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "campaign.status",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "campaignId": "cm2camp0001xyz",
                  "name": "عرض الجمعة",
                  "status": "paused",
                  "reason": "AUTO_LOW_DELIVERY",
                  "pausedUntil": "2026-10-13T10:00:00.000Z",
                  "timestamp": "2026-10-13T09:00:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "otp.verified": {
      "post": {
        "operationId": "webhook_otp_verified",
        "security": [],
        "summary": "otp.verified event",
        "description": "An OTP sent through POST /v2/otp was verified. Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "otp.verified",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "otpId": "otp_8f2c1d9a7b3e4f56a1b2c3d4",
                  "to": "2010****4567",
                  "verifiedAt": "2026-10-13T08:01:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "conversation.attributed": {
      "post": {
        "operationId": "webhook_conversation_attributed",
        "security": [],
        "summary": "conversation.attributed event",
        "description": "A chat started from your website button or a tracked WhatsApp link (page, utm_*, widget / link). Metadata only. Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "conversation.attributed",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "conversationId": "cm5conv0001",
                  "contact": {
                    "phone": "201099887766",
                    "lid": null,
                    "name": "منى"
                  },
                  "messageId": "3EB0C1D2E3F4A5B6C7D8",
                  "source": {
                    "type": "widget",
                    "widgetId": "wgt_k2m7q4x9a3b5c8d2",
                    "linkId": null,
                    "name": "Main website",
                    "agent": "sales",
                    "pagePath": "/products/bag",
                    "referrerDomain": "facebook.com",
                    "utm": {
                      "source": "facebook",
                      "medium": "cpc",
                      "campaign": "summer",
                      "content": null,
                      "term": null
                    }
                  },
                  "clickedAt": "2026-10-13T07:58:10.000Z",
                  "timestamp": "2026-10-13T08:00:02.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    },
    "webhook.test": {
      "post": {
        "operationId": "webhook_webhook_test",
        "security": [],
        "summary": "webhook.test event",
        "description": "Test event (always delivered). Signed: X-Wasla-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>. Answer 2xx within 10 s; retried after 10s, 1m, 5m, 15m, 30m; 410 disables the webhook.",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "id": "evt_5f0c2b7d9e1a4c3b8a6f2d10",
                "type": "webhook.test",
                "apiVersion": "2026-10",
                "createdAt": "2026-10-13T08:00:03.000Z",
                "sessionId": "cm1abcd2345efgh6789ijkl",
                "number": "201001234567",
                "data": {
                  "message": "This is a test event from Mursilat",
                  "timestamp": "2026-10-13T08:00:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          },
          "410": {
            "description": "Stop sending (webhook disabled)"
          }
        }
      }
    }
  }
}
