واجهة REST API

اقرأ مراقباتك واكتبها، واقرأ الحوادث وحدّثها، وارفع ملفات source map. كل ما هنا يستخدم فحوص الصلاحيات نفسها ومرشّح العزل بين العملاء نفسه اللذين تستخدمهما لوحة التحكم — ولا يوجد تنفيذ منفصل على جانب الـ API يمكن أن ينحرف عنهما.

متاحة في كل خطة، بما فيها المجانية. لا توجد إضافة تشتريها ولا مستوى يفتحها.

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

https://vitrinaengine.com/api/v1

وصف قابل للقراءة آليًا

/openapi.json مستند OpenAPI 3.1 يغطي كل مسار في هذه الصفحة. وجّه إليه مولّد عملاء، أو سلّمه إلى وكيل عليه أن يستدعي هذه الـ API دون أن يشرحها له أحد.

يُولَّد من الخدمة نفسها بدلًا من أن يُكتب إلى جانبها: المسارات تأتي من السطح الذي تنشره الـ API عند GET /، والأشكال ونصوصها من ملفات .proto نفسها في /api/proto، وحدود الاستخدام من الشيفرة التي تطبّقها. تفشل عملية البناء حين يختلف المستند المودع عن الـ API، فهو يصف ما يُقدَّم فعلًا لا ما كان صحيحًا آخر مرة عدّله أحد.

هو يصف الأشكال. أما الأسباب فهي في هذه الصفحة — أن معرّفًا يخص مؤسسة أخرى يُجاب بـ 404، وأن config لا يُعاد أبدًا — وهذا ما لا يكتبه أي مولّد.

للوكلاء: MCP

https://vitrinaengine.com/mcp خادم Model Context Protocol. أضفه إلى عميل MCP مع مفتاح API بوصفه رمز bearer، فيستطيع وكيل أن يقرأ مراقباتك وحوادثك وأخطاءك وتحليلاتك — وأن ينشئ المراقبات ويعدّلها ويحذفها — دون أن يشرح له أحد كيف تعمل هذه الـ API.

{
  "mcpServers": {
    "vitrina-engine": {
      "type": "http",
      "url": "https://vitrinaengine.com/mcp",
      "headers": { "Authorization": "Bearer vte_your_key_here" }
    }
  }
}

يقرأ كل شيء ويكتب ثلاثة أشياء. كل عملية GET في هذه الصفحة أداة، وكذلك POST /monitors و PATCH /monitors/{id} و DELETE /monitors/{id}. ولا شيء آخر يكتب في متناوله — لا مساحة عمل ولا عضو ولا مفتاح API ولا صفحة حالة ولا حسابك — لأنه لا توجد أداة لأيٍّ منها، ولأن قائمة عمليات الكتابة المسموح بها ثلاثة أسطر يضيفها أحدهم عن قصد.

المفتاح الذي لا يملك الكتابة يظل مرفوضًا. استدعاء الأداة هو الطلب نفسه الذي كان المفتاح ليرسله مباشرة، بالفحص نفسه للصلاحيات وبمرشّح العزل نفسه: فوكيل يحمل مفتاح قراءة فقط يقرأ. امنحه مفتاحًا كهذا ما لم تقصد أن يغيّر مراقبتك، وتوقّع أن يسألك العميل قبل الحذف: حذف مراقبة يأخذ معه تاريخها ولا تراجع عنه. ولإسكات مراقبة دون فقدانها، أوقفها مؤقتًا عبر PATCH.

ولأنه الطلب نفسه، فهو يرى بالضبط ما يراه المفتاح، ويكتب في سجل التدقيق ما تكتبه لوحة التحكم، ويُحتسب على حد الاستخدام نفسه مرتين: مرة للاستدعاء ومرة للطلب الذي بداخله. والكتابة تُحتسب على حد الكتابة.

ثمة أمر يجدر معرفته قبل أن يعدّل وكيل مراقبةً: config يُستبدل كاملًا ولا يُدمج. اقرأ المراقبة أولًا، غيّر الحقل المقصود، ثم أعد إرسال الكائن كاملًا. فالتهيئة الجزئية تُسقِط بصمت الترويسات وبيانات الاعتماد التي يعتمد عليها الفحص، وتتركه يعمل.

المصادقة

أنشئ مفتاحًا من الإعدادات ← مفاتيح API، ثم أرسله بوصفه رمز bearer. يُعرض المفتاح مرة واحدة، عند إنشائه، ولا يُخزَّن إلا كتجزئة — فإن فقدته، أنشئ غيره.

curl https://vitrinaengine.com/api/v1/summary \
  -H "Authorization: Bearer vte_your_key_here"

لا يمنح المفتاح أبدًا أكثر مما كان يملكه من أنشأه. فهو مرتبط بعضويته ويحمل دوره: المفتاح الذي ينشئه شخص دوره للقراءة فقط لا يستطيع الكتابة مهما أرسلت إليه. ويمكن أيضًا حصر المفتاح في مساحة عمل واحدة، فتُرشَّح عندئذ كل استجابة إلى تلك المساحة، وما خرج عنها غير موجود بالنسبة إلى ذلك المفتاح.

وإزالة شخص من مؤسستك تبطل المفاتيح التي أنشأها، في العملية نفسها. فسحب الوصول يجب أن يسحب بيانات الاعتماد معه، وإلا بقي في يد الشخص مفتاح يعمل.

الأعراف المتبعة

كل استجابة ناجحة كائن JSON فيه خاصية data. وكل إخفاق كائن JSON فيه خاصية error تحمل جملة موجهة إلى إنسان.

{ "data": { "id": "8f14e45f-…", "name": "Marketing site" } }

{ "error": "This key cannot create monitors." }

تُرسَل الاستجابات مع Cache-Control: private, no-store. فهي بيانات خاصة بمفتاح بعينه على أصل مشترك، ولا يجوز أن يحتفظ بها أي وسيط.

Protobuf وgzip

كل نقطة نهاية تحت /api/v1 تتحدث Protocol Buffers أيضًا. أرسل Accept: application/x-protobuf فتأتي الاستجابة بصيغة protobuf؛ وأرسل جسمًا بصيغة protobuf مع Content-Type: application/x-protobuf فتعود الاستجابة بالصيغة نفسها. وإن لم ترسل أيًّا منهما فهي JSON، تمامًا كما كانت.

curl https://vitrinaengine.com/api/v1/monitors \
  -H "Authorization: Bearer vte_your_key_here" \
  -H "Accept: application/x-protobuf" \
  --compressed -o monitors.pb

الرسائل منشورة: /api/proto يسرد كل ملف. نزّلها مع الحفاظ على مساراتها ووجّه protoc -I إلى ذلك المجلد. وثلاثة أمور تختلف عما يتوقعه مستخدم protobuf: الحقل الذي قد يكون فارغًا هو null في JSON وغائب في protobuf؛ وبعض الحقول التي يتغير شكلها — مثل config الخاص بمراقب أو بقناة — مستندات JSON محمولة داخل نص؛ وStringList يغلّف قائمة يمكن أن تكون هي نفسها null.

ويعمل gzip في الاتجاهين: Accept-Encoding: gzip للاستجابات، و Content-Encoding: gzip للطلبات. ولأن عميلين قد يتلقيان الآن بايتات مختلفة من العنوان نفسه، تحمل كل استجابة Vary: Accept, Content-Type.

رموز الحالة

الرمزالمعنى
200كل شيء على ما يرام. و201 حين يُنشأ شيء.
400الجسم ليس JSON، أو ينقصه حقل، أو لم يُطلب فيه أي تغيير.
401لا مفتاح، أو مفتاح غير صالح. ولا يقال أبدًا أيهما، عن قصد — فرسالة تفرّق بينهما تصير وسيلة لتخمين المفاتيح.
403مفتاح صالح لا يملك صلاحية هذا الإجراء. والرسالة تسمّيها.
404لا وجود لهذا السجل بالنسبة إليك. انظر أدناه.
413ملف source map يتجاوز حد الحجم.
429تجاوزت أحد حدود الطلبات. ويحمل Retry-After. انظر أدناه.

رموز الرفض

كل استجابة خارج نطاق 2xx تحمل code إلى جانب الجملة — not_found وlimit_reached وrate_limited — وهو الحقل الذي ينبغي أن تتفرّع عليه. نصّ error مكتوب لإنسان يقرأ سجلًّا وقد تُعاد صياغته في أي وقت؛ أما الرمز فثابت. وحين تسمّي الجملة قيمة، يحمل vars تلك القيم كنصوص، فتضعها حيث تريده قواعد لغتك بدل استخراجها من الإنجليزية.

{
  "error": "The Pro plan includes 50 monitors, and you have 50.",
  "code": "limit_reached",
  "vars": { "plan": "pro", "limit": "50", "current": "50", "resource": "monitors" }
}

هذا ما تعرض تطبيقاتنا الرفض منه بلغة القارئ. تعامل مع رمز لا تعرفه كما تفعل هي — ارجع إلى error — لأن الرموز تُضاف دون تغيير رقم الإصدار.

حدود الطلبات

لكل مؤسسة، لا لكل مفتاح — فإنشاء مفتاح آخر لا يرفعها.

الفئةالحد
القراءات (GET)120 في الدقيقة
الكتابات (POST وPATCH وDELETE)30 في الدقيقة
رفع ملفات source map300 في الساعة

تجاوزها يُجاب بـ 429 مع ترويسة Retry-After تذكر عدد الثواني الكاملة الباقية حتى تُصفَّر النافذة. التزم بها بدلًا من إعادة المحاولة فورًا.

وهي موضوعة حيث لا يبلغها أي تكامل عادي: لوحة معلقة على الجدار تستعلم كل عشر ثوانٍ تنفق ستًا من القراءات الـ 120. وهي واحدة في كل الخطط، لأن نقاط النهاية الجامعة تعيد كل شيء في استجابة واحدة — فالحساب الذي فيه خمسمئة مراقب لا يحتاج إلى طلبات أكثر من حساب فيه عشرون. أما ملفات source map فلها نافذة بالساعة لأنها تصل دفعة واحدة عند النشر، حيث قد تكون واجهة أمامية واحدة مئة جزء.

404 بدلًا من 403، عن قصد

المعرّف الذي يخص عميلًا آخر يُجاب بـ “Not found.”، لا “Forbidden.”. فالرد بـ 403 يؤكد أن السجل موجود، وهو ما يحوّل نقطة النهاية إلى وسيلة لمعرفة ما إذا كان معرّف ما حقيقيًا. فلا تقرأ الـ 404 دليلًا على أن شيئًا ما غير موجود في أي مكان — بل على أنه لا يوجد شيء يستطيع هذا المفتاح رؤيته.

نقاط النهاية

كل ما يطابق ?q= في الحساب: المراقبات والحوادث وتحليلات ما بعدها والخوادم وصفحات الحالة ومساحات العمل وقنوات التنبيه وفترات الصيانة ومشاريع الأخطاء والمشكلات ومواقع التحليلات والأعضاء والدعوات ومفاتيح API والوكلاء والمسابير الخاصة. طلب واحد بدل طلب لكل نوع.

?type= يحصر النتائج في أنواع محددة مفصولة بفواصل، و?limit= يحدّ عدد نتائج كل نوع بين 1 و20 (الافتراضي 5). كل نوع محكوم بالصلاحية نفسها التي تحكم نقطته الخاصة، والنوع الذي لا يسمح به مفتاحك يغيب كما لو لم يطابق شيئًا. لا يُطابَق أو يُعاد أي سر أو رمز أو قيمة مختومة.

المعاملات والاستجابات
الاسمالموضعالنوع
limitqueryinteger
qquerystring
typequerystring
الاستجابةSearchResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /summary

أعداد، للوحة جدارية أو لملخص يومي. تتطلب monitor:read.

{
  "data": {
    "total": 42, "up": 39, "degraded": 1, "down": 1,
    "paused": 1, "pending": 0,
    "openIncidents": 2, "suppressedIncidents": 1
  }
}

suppressedIncidents يعدّ الحوادث المحتجزة لكونها ضمن نطاق تأثير حادث آخر. وهي حقيقية، لكنها ليست أعطالًا منفصلة.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةGetSummaryResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /setup

ما تبقّى على حساب جديد أن يفعله: الأسئلة الأربعة نفسها التي تطرحها قائمة البدء في لوحة التحكم، مشتقة عند كل قراءة. تتطلب monitor:read.

{
  "data": {
    "hasMonitor": true,
    "hasConfirmedChannel": false,
    "hasStatusPage": false,
    "hasColleague": false,
    "dismissedAt": null
  }
}

hasConfirmedChannel يسأل عمّا إذا كان التنبيه سيصل فعلًا، لا عمّا إذا كانت القناة موجودة. فقد افترق الأمران مرة على نحو سيئ، وقائمة تعدّ التنبيه جاهزًا بقناة يرفضها المُنبِّه تكرر ذلك الخلل في صورة طمأنينة.

hasColleague يعدّ العضويات لا الدعوات أبدًا: دعوة أُرسلت ولم تُقبل لم تضف أحدًا.

وهو غير مطوي داخل /summary، لأن تلك النقطة أعداد بحسب الحالة ولا شيء غير ذلك: فلوحة جدارية تستعلم عنها كل بضع ثوانٍ لا تريد خمسة استعلامات زائدة لرسم تنبيه موجه إلى من أنشأ الحساب قبل شهور.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةGetSetupResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

DELETE /setup

يتخطى القائمة. يتطلب org:update، لأن صرف النظر عنها صف واحد يخص المؤسسة كلها لا تفضيلًا لكل شخص — فالزميل الذي يأتي بعد تخطّيها لا تُعرض عليه مرة أخرى.

ولا يتغير شيء آخر في الحساب، ولا يُكتب أي قيد تدقيق: إخفاء تنبيه لا يغيّر شيئًا في سلوك المنتج، ولا في تنبيهه، ولا في فوترته.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةDismissedResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /monitors

كل المراقبات التي يستطيع المفتاح رؤيتها. تتطلب monitor:read. ويحمل كل منها id وname وkind وstatus، statusSince وenabled وintervalSeconds، tags وworkspace وlastCheckedAt، lastResponseTimeMs وlastMessage وuptime24h، uptime30d وopenIncidentId.

?tag=prod,eu يضيّق القائمة إلى المراقبات التي تحمل كل وسم مذكور — «و» لا «أو»، فذكر وسم ثانٍ يعيد دائمًا عددًا أقل لا أكثر. وفلتر لوحة التحكم نفسه يقرأ بالطريقة ذاتها. تُخزَّن الوسوم بحروف صغيرة، وتُحوَّل القيمة هنا بالطريقة نفسها قبل المقارنة، لذا يجدها ?tag=Prod. وأي مدخل لا يصلح أن يكون وسمًا — فارغ، أو أطول مما يسمح به الوسم — يُسقَط ويبقى باقي الفلتر ساريًا بدل رفض الطلب: فالرابط يجب ألّا يتوقف عن العمل لأن أحد وسومه أُعيدت تسميته.

config لا يُعاد أبدًا. ففي بعض الأنواع يحتوي على ترويسات طلب وبيانات اعتماد، ولا ينبغي أن يكون مفتاح للقراءة فقط وسيلة لاسترجاع أسرار كتبها أحدهم في نموذج.

المعاملات والاستجابات
الاسمالموضعالنوع
tagquerystring
الاستجابةListMonitorsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /monitors

تتطلب monitor:create. وتحتاج إلى name وkind، workspaceId وconfig. والاختيارية: intervalSeconds (الافتراضي 300)، وconfirmations، و dependsOn.

curl -X POST https://vitrinaengine.com/api/v1/monitors \
  -H "Authorization: Bearer vte_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Marketing site",
    "kind": "http",
    "workspaceId": "…",
    "intervalSeconds": 60,
    "config": {
      "url": "https://example.com",
      "assertions": [{ "type": "status_code", "operator": "lt", "value": "400" }]
    }
  }'

تُجيب بـ 201 ومعها المعرّف الجديد. ويُقصَر الفاصل الزمني على أدنى ما تسمح به خطتك بدلًا من أن يُرفض، فطلب 10 ثوانٍ في خطة حدها الأدنى 60 يعطيك 60 — وإن كان ذلك يهمّك، فأعد قراءته.

المعاملات والاستجابات
الاسمالموضعالنوع
namebodystring
kindbodystring
workspaceIdbodystring
configbodystring
intervalSecondsbodyinteger
confirmationsbodyinteger
dependsOnbodystring[]
probeIdbodystring
tagsbodystring[]
الاستجابةCreatedResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /monitors/{id}

مراقب واحد، بكل ما تعطيه القائمة إضافة إلى paused. تتطلب monitor:read.

ولأنواع mail_posture وtls_audit وsnmp يحمل أيضًا lastCheckDetail، أي نتيجة آخر فحص نفسها: النتائج التي وراء الحالة، لكل منها code ثابت وseverity، مع تقدير TLS أو قراءات SNMP. وهو null حتى يجري أول فحص، وغائب في كل نوع آخر.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةGetMonitorResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

PATCH /monitors/{id}

أرسل ما تريد تغييره فقط: name أو intervalSeconds أو confirmations أو enabled أو config أو paused.

يُفحص paused في مقابل monitor:pause وكل ما عداه في مقابل monitor:update، كل على حدة — فالمفتاح الذي يستطيع الإيقاف المؤقت دون التحرير يظل قادرًا على الإيقاف المؤقت. وإرسال تغيير فارغ يُجاب بـ 400.

ويُعاد قراءة المراقب وإرجاعه، بدلًا من تكرار ما أرسلته إليك، فما تراه هو ما حُفظ فعلًا.

# Silence a monitor for the length of a deploy.
curl -X PATCH https://vitrinaengine.com/api/v1/monitors/$ID \
  -H "Authorization: Bearer vte_…" \
  -H "Content-Type: application/json" \
  -d '{"paused": true}'
المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
namebodystring
intervalSecondsbodyinteger
confirmationsbodyinteger
enabledbodyboolean
pausedbodyboolean
configbodystring
tagsbodyStringList
الاستجابةUpdatedMonitorResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /monitors/{id}

تتطلب monitor:delete. وتُجيب بـ { "data": { "id": "…", "deleted": true } }.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /hosts · POST /hosts

الخوادم هي الطريقة الثانية لتجميع المراقبات: مساحة العمل تقول لمن المراقب، والخادم يقول على أي جهاز يعمل. اختياري تمامًا — الحساب الذي لا ينشئ خادمًا قط لا يفقد شيئًا، ومعظم المراقبات لا تسمي خادمًا أصلًا.

كل خادم يحمل status وpinned وspanning. تُشتق status فقط من المراقبات التي تعمل على هذا الخادم وحده. أما المراقب الممتد على عدة آلات فيُحتسب في spanning ولا يلوّن أيًا منها، لأن تعطّل نقطة موزَّعة الحمل يقول إن الخدمة معطلة لا أي آلة عطّلتها. والخادم الذي لا مراقب خاص به يجيب "status": null بدل up.

يحتاج POST إلى monitor:create وإلى name. أما provider وaddress وnotes فاختيارية وهي ملاحظاتك وحدك، لا يقرؤها المنتج. والاسم الذي يطابق اسمًا لديك — مع تجاهل حالة الأحرف والنقطة الأخيرة — يجيب 409.

المعاملات والاستجابات

GET /hosts

لا معاملات ولا حقول متن معلنة.

الاستجابةListHostsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /hosts

الاسمالموضعالنوع
namebodystring
providerbodystring
addressbodystring
notesbodystring
الاستجابةCreatedResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /hosts/{id} · PATCH /hosts/{id} · DELETE /hosts/{id}

التفاصيل تحمل الخادم والمراقبات التي عليه، كل واحدة بعلامة pinned، وحين لا تكون كذلك تحمل alsoOn: الآلات الأخرى التي تستجيب منها، وهو ما تقرؤه قبل إعادة تشغيل إحداها. وDELETE يتقاعد بالخادم بينما تستمر كل مراقباته في العمل، فالخادم لا يملك جدولًا ولا سجلًا خاصًا به.

المعاملات والاستجابات

GET /hosts/{id}

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةGetHostResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

PATCH /hosts/{id}

الاسمالموضعالنوع
id إلزاميpathstring
namebodystring
providerbodystring
addressbodystring
notesbodystring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /hosts/{id}

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

POST /hosts/{id}/monitors · DELETE /hosts/{id}/monitors

مراقب واحد على خادم أو خارجه، عبر monitorId في الجسم أو ?monitorId=. وليست قائمة كاملة عن قصد: في حساب وكالة يحمل الخادم مراقبات من عدة مساحات عمل، ومن يستبدل «القائمة» يستبدل صفوفًا لم تُعرض عليه أصلًا. والاتجاهان كلاهما لا يتأثران بالتكرار.

المعاملات والاستجابات

POST /hosts/{id}/monitors

الاسمالموضعالنوع
id إلزاميpathstring
monitorIdbodystring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /hosts/{id}/monitors

الاسمالموضعالنوع
id إلزاميpathstring
monitorIdquerystring
monitorIdbodystring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /monitors/{id}/hosts · PUT /monitors/{id}/hosts

الوجه الآخر للعلاقة نفسها، وهذا قائمة كاملة فعلًا: هذه الروابط تخص مراقبًا واحدًا، فلا شيء في الطرف الآخر تراه مساحة عمل أخرى. أرسل hostIds؛ والمصفوفة الفارغة طلب حقيقي ومعناه أن المراقب لا يعمل على خادم بعينه. أما المعرفات التي ليست لك فتُهمَل بدل أن تُرفض. وكل استجابة مراقب تحمل كذلك hosts، فارغة حين لا يوجد أي خادم.

المعاملات والاستجابات

GET /monitors/{id}/hosts

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةListMonitorHostsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

PUT /monitors/{id}/hosts

الاسمالموضعالنوع
id إلزاميpathstring
hostIdsbodystring[]
الاستجابةListMonitorHostsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /incidents

تتطلب incident:read. وتقبل ?status= بإحدى القيم open أو acknowledged أو resolved أو suppressed — و?open=true للحالات الثلاث غير المحلولة. والحالة غير المعروفة تُتجاهل بدلًا من أن تُرفض، تمامًا كما يُقصَر ?limit= (الافتراضي 50) على 200 بدلًا من أن يُرفض.

ويحمل كل منها id وmonitorId وmonitorName، title وcause وstatus وseverity، startedAt وresolvedAt وdurationSeconds، acknowledgedAt وrootIncidentId.

rootIncidentId هو الحقل الذي تنظر إليه إن كنت تبني تدفق تنبيهات. فحين يكون موجودًا، يكون هذا الحادث جزءًا من نطاق تأثير حادث آخر — سقط خادم قاعدة البيانات وهذا واحد من اثنتي عشرة خدمة خلفه. تخطَّها فتصلك رسالة واحدة بدل ثلاث عشرة.

المعاملات والاستجابات
الاسمالموضعالنوع
limitqueryinteger
openqueryboolean
statusquerystring
الاستجابةListIncidentsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /incidents/{id}

حادث واحد. تتطلب incident:read. الحقول نفسها التي في القائمة، إضافة إلى workspaceId.

ولا تعيد الخط الزمني للحادث — فالتعليقات وتغيّرات الحالة التي تراها في لوحة التحكم ليست في هذه النقطة. وإن كنت تحتاج إليها فاطلبها ويمكن إضافتها؛ أما توثيقها هنا وهي غير موجودة فأسوأ من غيابها.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةGetIncidentResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

PATCH /incidents/{id}

أرسل status بقيمة "acknowledged" أو "resolved"، أو comment، أو كليهما. ويُفحص كل منهما في مقابل صلاحيته: incident:acknowledge و incident:resolve وincident:comment. وإضافة "publish": true إلى تعليق تنشره على صفحة الحالة وتتطلب معها status_page:manage.

# A runbook that fixed the thing itself can close its own incident.
curl -X PATCH https://vitrinaengine.com/api/v1/incidents/$ID \
  -H "Authorization: Bearer vte_…" \
  -H "Content-Type: application/json" \
  -d '{"status": "resolved", "comment": "Restarted by runbook.", "publish": true}'
المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
statusbodystring
commentbodystring
publishbodyboolean
الاستجابةGetIncidentResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

PUT /incidents/{id}/postmortem

يكتب مراجعة ما بعد الحادث أو يستبدلها. يتطلب incident:resolve، ويجب أن يكون الحادث قد حُلّ بالفعل — وإلا فالرد 409 مع الرمز incident_not_resolved. أرسل body بصيغة Markdown، من 1 إلى 50,000 حرف بعد إزالة المسافات الطرفية (postmortem_required، postmortem_too_long). لكل حادث مراجعة واحدة، لذا يستبدل كل استدعاء السابقة. الرد هو الحادث كما يعيده GET /incidents/{id}.

يحملها GET /incidents/{id} على شكل postmortem: { body, authorName, updatedAt } أو null، وتحمل القائمة hasPostmortem. اعرض body بصيغة Markdown وليس أبدًا كـ HTML: إنه نص كتبه شخص. المراجعة داخلية ولا تظهر أبدًا على صفحة الحالة.

curl -X PUT https://vitrinaengine.com/api/v1/incidents/$ID/postmortem \
  -H "Authorization: Bearer vte_…" \
  -H "Content-Type: application/json" \
  -d '{"body": "## What happened\n\nThe connection pool ran dry after a deploy."}'
المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
bodybodystring
الاستجابةGetIncidentResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /probes

المسابير الخاصة بمؤسستك: id, name, lastSeenAt, version, hostname, monitorCount, revoked وcreatedAt. يتطلب agent:read. هذا ما يعرضه منتقي المسبار في المراقِب.

لا يوجد حقل للمنطقة، ولن يوجد. تختار المسبار باسمه؛ أما مكان تشغيل الفحص خلفه فأمر نقرره نحن ونغيّره. تظهر المسابير الملغاة مع revoked: true ولا تتلقى عملًا، فلا تعرضها.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةListProbesResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /monitors/{id}/push-url

عنوان ping لمراقِب heartbeat، معروضًا مرة أخرى. يتطلب monitor:read. تكون url هي null لنوع لا يُرسل إليه ping، ولرمز لم يعد من الممكن فك تشفيره — يواصل المراقِب العمل، وتجديد الرمز في لوحة التحكم يُصدر عنوانًا يمكن عرضه.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةGetPushUrlResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /organizations · PUT /organizations/active

المؤسسات التي ينتمي إليها الشخص المسجّل دخوله، ولكل منها role الخاص به هناك وactive على المؤسسة المستخدمة حاليًا، والتبديل بينها. أرسل organizationId؛ والرد هو العضوية المستخدمة الآن.

لجلسة مسجّلة الدخول فقط. المفتاح ينتمي إلى عضوية واحدة ويتلقى 403 مع session_required. ينقل التبديل كل جلسات هذا الشخص، بما فيها لوحة التحكم، والمؤسسة التي ليس عضوًا فيها ترد بـ 404.

المعاملات والاستجابات

GET /organizations

لا معاملات ولا حقول متن معلنة.

الاستجابةListOrganizationsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

PUT /organizations/active

الاسمالموضعالنوع
organizationIdbodystring
الاستجابةActiveOrganizationResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

POST /sms/enrolment · POST /sms/enrolment/confirm

سجّل رقم هاتفك المحمول لتنبيهات SMS: أرسل phone (واختياريًا name)، وسنرسل إليه رمزًا من ستة أرقام؛ ثم أرسل ذلك code إلى المسار الثاني للتأكيد. يتطلب notification_channel:manage وجلسة مسجّلة الدخول — يضيف الرقمَ الشخصُ الذي يحمل الهاتف، وليس مفتاحًا أبدًا.

يُحفظ الرقم غير مؤكَّد ولا يتلقى شيئًا حتى يعود الرمز. التسجيل مجددًا يستبدل رقمك السابق. حالات الرفض: sms_not_included (402، الخطة لا تتضمن SMS)، not_a_phone_number, sms_country_unsupported, sms_route_not_open، verification_code_not_sent (502؛ استدعِ مجددًا لرمز جديد)، verification_code_malformed وverification_code_incorrect. تحمل البداية الناجحة country وcaveatsender-replaced, registration-pending, unverified أو null — ويستحق عرضه قبل أن يعتمد أحد على الرقم.

المعاملات والاستجابات

POST /sms/enrolment

الاسمالموضعالنوع
phonebodystring
namebodystring
الاستجابةSmsEnrolmentResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

POST /sms/enrolment/confirm

الاسمالموضعالنوع
codebodystring
الاستجابةSmsConfirmedResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

POST /channels/{id}/confirmation

يعيد إرسال رسالة تأكيد قناة البريد الإلكتروني. يتطلب notification_channel:manage. كل استدعاء يُصدر رابطًا جديدًا ويتوقف الرابط السابق عن العمل. تعني sent: false أنه لم يكن هناك ما يُرسل — فالعنوان أكّد بالفعل — ولا يُراسَل عنوان مؤكَّد مجددًا بهذه الطريقة أبدًا. الإرسال الذي يرفضه مزوّد البريد يرد بـ 502 مع confirmation_not_sent.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةChannelConfirmationResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

PATCH /workspaces/{id}

يعيد تسمية مساحة عمل. يتطلب workspace:update. الحقل name مطلوب (من 1 إلى 80 حرفًا) وclientReference اختياري — وnull يمسحه. لا يتغير الـ slug أبدًا لأنه جزء من عناوين صفحات الحالة. الرد هو مساحة العمل كما أصبحت.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
namebodystring
clientReferencebodyrequests.NullableString
الاستجابةUpdatedWorkspaceResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

POST /sourcemaps

ارفع ملف source map كي تُحلّ آثار التتبع المصغّرة. تتطلب monitor:create. وتحتاج إلى projectRef (رقم) و filename، إضافة إلى الملف نفسه في map (بصيغة JSON) أو mapGzipBase64. والاختيارية: debugId وrelease.

أرسل معرّف تصحيح أو إصدارًا. فالملف الذي لا يحمل أيًّا منهما لا يمكن ربطه بأثر تتبع وسيبقى دون فائدة. ويُبحث عن المطابقة أولًا عبر debugId ثم عبر الإصدار مع اسم الملف.

وتُحلّ الملفات عند قراءة المشكلة لا عند رفعها، فالملف المرفوع بعد وصول الأخطاء يظل مفيدًا — وهو الترتيب المعتاد.

المعاملات والاستجابات
الاسمالموضعالنوع
projectRefbodyinteger
filenamebodystring
debugIdbodystring
releasebodystring
mapbodystring
mapGzipBase64bodystring
الاستجابةUploadedSourceMapResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات300 في الساعة

POST /symbols

الفكرة نفسها لتطبيق أصلي: ارفع ملف .dSYM من iOS أو ملف mapping.txt من R8 في أندرويد كي تُحلّ آثار الانهيارات. تتطلب monitor:create. عشرون عملية رفع في الساعة، ويُحتفظ بما يعادل عشرين إصدارًا لكل مشروع.

وخلافًا لـ /sourcemaps، يكون الجسم هو الملف المضغوط بـ gzip نفسه وتكون البيانات الوصفية في الترويسات: X-Vitrina-Project-Ref و X-Vitrina-Platform (ios أو android)، و X-Vitrina-Symbol-Name، وX-Vitrina-Release. فملف dSYM حجمه عشرات الميغابايتات، وترميز base64 داخل حقل JSON يكلّف ثلثًا إضافيًا في النقل.

والمنصتان تُطابَقان على نحوين مختلفين. فإطار iOS يسمّي معرّف Mach-O UUID للصورة التي ينتمي إليها، لذا يجب أن يحمل الرفع من iOS ترويسة X-Vitrina-Debug-Ids ويُطابَق عليها تمامًا. أما R8 فلا يصدر معرّفًا كهذا، فتُطابَق خرائط أندرويد على الإصدار وحده — ويجب أن يكون بالضبط ما يبلّغ عنه التطبيق، <applicationId>@<versionName>+<versionCode>. وخطأ رقم واحد يجعل الأطر تُحلّ إلى أسطر تبدو معقولة وهي خاطئة.

وإعادة رفع الإصدار نفسه تستبدل رموزه بدلًا من أن تفشل، فإعادة تشغيل مهمة إصدار ليست خطأ. وكما هي الحال مع ملفات source map، يحدث الحل عند قراءة المشكلة.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةUploadedSymbolsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات20 في الساعة

GET /errors/projects

مشاريع تتبّع الأخطاء التي يملكها هذا الحساب. تتطلب monitor:read. ويحمل كل منها ref — الرقم الموجود في الـ DSN — إضافة إلى publicKey و unresolved وeventsLast24h. للقراءة فقط: فالمشروع يُنشأ بمفتاح لا يزال عليك لصقه في إعدادات تطبيق ما، فليس هنا شيء تكمله نقطة نهاية.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةListErrorProjectsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /errors/issues

الأخطاء مجمّعة، الأحدث نشاطًا أولًا. تتطلب monitor:read. والمشكلة بصمة لا حدث، فألف وقوع لرمية واحدة صف واحد قيمة timesSeen فيه ألف. و ?status= افتراضها unresolved وتقبل أيضًا resolved أو ignored أو all؛ و ?project= ترشّح بحسب معرّف المشروع، و?q= تبحث في النوع والقيمة والموضع المسؤول، و?limit= محدودة بـ 200. وspark أربع وعشرون قيمة بالساعة، الأقدم أولًا.

المعاملات والاستجابات
الاسمالموضعالنوع
limitqueryinteger
projectquerystring
qquerystring
statusquerystring
الاستجابةListIssuesResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /errors/issues/{id}

مشكلة واحدة مع أثر تتبعها. تتطلب monitor:read. وexceptions هي سلسلة الـ SDK نفسها، الخطأ المرمي أخيرًا وأسبابه قبله، وأطرها محلولة في مقابل أي ملف source map رفعته — وهو الحل نفسه الذي تجريه لوحة التحكم، فلا ينظر نصك والشخص الذي تحدثه إلى أثرين مختلفين أبدًا. والملف الذي يتعذّر تطبيقه يعود إلى الأطر الأصلية بدلًا من أن يُفشل الطلب.

ويحمل lastEvent طابعين زمنيين عن قصد. occurredAt ما أبلغ به الـ SDK، وreceivedAt وقت كتابته عند الاستقبال؛ والجهاز الذي كان خارج الشبكة، أو الطابور الذي تراكم، هو بالضبط الفارق بينهما.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةGetIssueResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

PATCH /errors/issues/{id}

الحل أو التجاهل أو إعادة الفتح: { "status": "resolved" }. تتطلب monitor:update. ويمكن أن ترافق ignoreHours القيمة ignored لإلغاء التجاهل لاحقًا، وهي محدودة بـ 90 يومًا.

والحل يسجّل الإصدار الذي حُلّت فيه المشكلة، فلا يعيد فتحها حدث متأخر من نشر أقدم. وحين لا يرسل الـ SDK إصدارًا فلا شيء يُقارن به، وأي حدث لاحق يعيد فتحها — فما دام لا سبيل إلى تمييز المتأخر من الانتكاسة، فالافتراض الآمن أن العلة عادت.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
statusbodystring
ignoreHoursbodyinteger
الاستجابةIssueStatusResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /analytics

المواقع التي يقيسها هذا الحساب. تتطلب monitor:read. وتحمل publicId — القيمة التي توضع في وسم النص البرمجي، وهي علنية بحكم التصميم — إضافة إلى viewsLast24h وtrafficAlerting، التي تكون صحيحة ما دامت حركة الموقع أقل مما تشهده تلك الساعة عادة.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةListAnalyticsSitesResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /analytics/{id}

أرقام موقع واحد، لجدول بيانات أو لتقرير. تتطلب monitor:read. و ?days= افتراضها 7 وحدها الأقصى 365. و?dimensions= تأخذ قائمة مفصولة بفواصل من path وreferrer وcountry و browser وos وdevice وutm_source و utm_medium وutm_campaign وevent؛ وأي قيمة غير معروفة تُجاب بـ 400 لا بنتيجة فارغة، لأن خطأً مطبعيًا لا يعيد شيئًا يُقرأ على أنه “لا حركة”.

رقم الزوار اسمه dailyUniqueVisitors، وهذا هو ما يعنيه بالضبط. فهو مجموع الزوار الفريدين يوميًا ولا يمكن أن يكون غير ذلك: السر الذي وراء تجزئة الزائر يُتلف في نهاية يومه بتوقيت UTC، فمن زار في يومين يُحتسب مرتين ولا يوجد مفتاح يجمعهما. وهذا هو تصميم الخصوصية وهو يعمل لا تقريبًا — لكن حقلًا اسمه visitors إلى جوار مدى من 30 يومًا كان سيغريك بأن تبلّغ رقمًا يعني شيئًا آخر.

curl "https://vitrinaengine.com/api/v1/analytics/$ID?days=30&dimensions=path,referrer" \
  -H "Authorization: Bearer vte_…"
المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
daysqueryinteger
الاستجابةGetAnalyticsSiteResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /billing

الخطة، ومن أين تُفوتر. تتطلب billing:read. وتحمل plan و status وcadence وcurrentPeriodEnd و cancelAt وaddOnPacks وآخر اثنتي عشرة فاتورة.

وsource إما paddle أو apple أو manual أو none. وهذا مهم: فالاشتراك المشترى داخل تطبيق iOS تملك Apple تغييره، وتوجد الخطة والبطاقة والإلغاء كلها في إعدادات App Store لدى العميل لا هنا. وcanCheckoutOnWeb وcanPurchaseInApp تقولان أي العروض آمن عرضه، فلا يضطر العميل إلى إعادة اشتقاق تلك القاعدة ويخطئ فيها في الاتجاه الذي يفوتر أحدهم مرتين.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةGetBillingResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /monitors/{id}/history

جاهزية يومية لمراقب واحد. تتطلب monitor:read. وتقبل days، حتى مدة حفظ السجل في خطتك.

وتُحسب من التجميعات اليومية لا من نتائج الفحوص المفردة، ولهذا تظل تجيب عن مدد حذفت سياسة الحفظ نتائجها الخام بالفعل.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
daysqueryinteger
الاستجابةGetMonitorHistoryResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /monitors/{id}/graph · GET /monitors/graphs

الساعات الأخيرة لمراقب واحد، ساعةً بساعة، أو لكل المراقبات التي يراها هذا المفتاح في ردٍّ واحد — ما ترسمه لوحة التحكم في صف المراقب وصفحته. تتطلب monitor:read. وتقبل hours، ‏24 افتراضيًا و168 كحد أقصى.

يحمل رسم uptime نسبة الفحوص الناجحة في كل ساعة، مع null لساعة بلا فحوص؛ ويحمل رسم value، للأنواع الكمية، قراءاته في سلاسل مع وحدتها. كل ساعة في النافذة حاضرة سواء سُجّل فيها شيء أم لا، فتظهر الفجوة فجوةً. تُرسل القراءات كما قيست: سلسلة raw بلا مقياس معروف، فارسمها مقابل أعلى قراءة لها ولا تعرض تلك النسبة على أنها القراءة.

المعاملات والاستجابات

GET /monitors/{id}/graph

الاسمالموضعالنوع
id إلزاميpathstring
hoursqueryinteger
الاستجابةGetMonitorGraphResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /monitors/graphs

الاسمالموضعالنوع
hoursqueryinteger
الاستجابةListMonitorGraphsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /monitors/{id}/channels · PUT /monitors/{id}/channels

القنوات التي ينبّهها هذا المراقب، وتعيينها. القراءة تتطلب notification_channel:read؛ والكتابة تتطلب monitor:update.

وPUT يستبدل المجموعة كلها — فأرسل كل معرّفات القنوات التي تريدها، لا التي تضيفها. والمصفوفة الفارغة تعني أن المراقب لا ينبّه أحدًا، وهو أمر يصح أن تريده ويسوء أن يقع منك سهوًا.

المعاملات والاستجابات

GET /monitors/{id}/channels

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةGetMonitorChannelsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

PUT /monitors/{id}/channels

الاسمالموضعالنوع
id إلزاميpathstring
channelIdsbodyStringList
الاستجابةGetMonitorChannelsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /incidents/{id}/events

الخط الزمني لحادث واحد: تغيّرات الحالة والإقرارات والتعليقات وخطوات التصعيد. تتطلب incident:read. وهو الخط الزمني الذي لا يتضمنه GET /incidents/{id}.

المعاملات والاستجابات
الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةListIncidentEventsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /channels · POST /channels

القراءة تتطلب notification_channel:read؛ والإنشاء يتطلب notification_channel:manage. ويحمل كل منها id و kind وname وtarget وworkspaceId.

وsecret لا يُعاد إلا عند إنشاء القناة، ولا يُعاد بعدها أبدًا. فهو مفتاح توقيع الـ webhook، وحفظه في موضع تستطيع قراءته منه يجعل مفتاحًا للقراءة فقط وسيلة لتزوير طلبات موقّعة.

ويمكنك إنشاء الأنواع التي يستطيع الشخص إنشاؤها في لوحة التحكم: email و webhook وtelegram وslack وteams و discord وpagerduty وjsm. أما الرسائل القصيرة وWhatsApp والأقمار الاصطناعية والإشعارات الفورية فيسجّلها من يتلقاها ولا يمكن إنشاؤها عبر الـ API — وهذا ما يجعلها موافقة لا حقلًا كتبه أحدهم.

وتُنشأ قناة البريد الإلكتروني غير مؤكَّدة وتتلقى رسالة واحدة تسألها إن كانت تريد التنبيهات. ولا يُرسل شيء آخر قبل أن توافق، فإنشاء واحدة عبر الـ API لا يضع عنوانًا في مناوبتك وحده.

المعاملات والاستجابات

GET /channels

لا معاملات ولا حقول متن معلنة.

الاستجابةListChannelsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /channels

الاسمالموضعالنوع
kindbodystring
namebodystring
targetbodystring
workspaceIdbodyrequests.NullableString
الاستجابةCreatedChannelResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

PATCH /channels/{id} · DELETE /channels/{id} · POST /channels/{id}/test

كلها تتطلب notification_channel:manage. والإرسال التجريبي مرفوض لعنوان لم يؤكّد — وإلا لكان وسيلة غير محدودة لمراسلة عنوان لم يوافق، تحت عنوان يبدو نافعًا.

المعاملات والاستجابات

PATCH /channels/{id}

الاسمالموضعالنوع
id إلزاميpathstring
enabledbodyboolean
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /channels/{id}

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

POST /channels/{id}/test

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةTestDeliveryResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /status-pages · POST /status-pages

القراءة تتطلب status_page:read؛ والكتابة تتطلب status_page:manage. ويحمل كل منها id وname و slug وvisibility وcustomDomain و domainVerifiedAt وsubscribersEnabled و componentCount وworkspace وcreatedAt.

المعاملات والاستجابات

GET /status-pages

لا معاملات ولا حقول متن معلنة.

الاستجابةListStatusPagesResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /status-pages

الاسمالموضعالنوع
namebodystring
workspaceIdbodystring
الاستجابةCreatedResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /status-pages/{id} · PATCH /status-pages/{id} · DELETE /status-pages/{id}

القراءة تتطلب status_page:read؛ والتعديل أو الحذف يتطلب status_page:manage.

المعاملات والاستجابات

GET /status-pages/{id}

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةGetStatusPageResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

PATCH /status-pages/{id}

الاسمالموضعالنوع
id إلزاميpathstring
namebodystring
headlinebodyrequests.NullableString
descriptionbodyrequests.NullableString
logoUrlbodyrequests.NullableString
themeAccentbodystring
languagebodystring
historyDaysbodyinteger
showResponseTimesbodyboolean
showIncidentHistorybodyboolean
subscribersEnabledbodyboolean
visibilitybodystring
passwordbodyrequests.NullableString
customCssbodyrequests.NullableString
hideVitrinaBrandingbodyboolean
groupByHostbodyboolean
الاستجابةUpdatedStatusPageResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /status-pages/{id}

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

POST /status-pages/{id}/components · DELETE /status-pages/{id}/components

إضافة مراقب إلى صفحة أو إزالته منها. تتطلب status_page:manage.

ويجب أن يكون المراقب في مساحة عمل الصفحة نفسها، لا في المؤسسة نفسها فحسب. وفي حساب وكالة، هذا ما يمنع نشر مراقب أحد العملاء على صفحة عميل آخر.

المعاملات والاستجابات

POST /status-pages/{id}/components

الاسمالموضعالنوع
id إلزاميpathstring
monitorIdbodystring
displayNamebodystring
الاستجابةComponentAckResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /status-pages/{id}/components

الاسمالموضعالنوع
id إلزاميpathstring
componentquerystring
componentIdbodystring
الاستجابةComponentAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /workspaces · POST /workspaces · DELETE /workspaces/{id}

القراءة تتطلب workspace:read، ولكل ما عداها صلاحيته. ويحمل كل منها id وname وslug وclientReference و isDefault.

والمفتاح الذي يخص عضوًا محصورًا لا يرى إلا مساحات العمل التي حُصر فيها ذلك العضو. ولا يمكن حذف مساحة العمل الافتراضية.

المعاملات والاستجابات

GET /workspaces

لا معاملات ولا حقول متن معلنة.

الاستجابةListWorkspacesResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /workspaces

الاسمالموضعالنوع
namebodystring
clientReferencebodystring
الاستجابةCreatedResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /workspaces/{id}

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /members · POST /members

القراءة تتطلب member:read؛ والدعوة تتطلب member:invite. وتحمل الاستجابة members وinvitations منفصلين — فالدعوة التي لم يقبلها أحد لم تضف أحدًا، ودمج الاثنين يعطي عدد مقاعد يخالف ما تُفوتر عليه.

وPOST يرسل دعوة لا ينشئ حسابًا. ويأخذ بريدًا إلكترونيًا ودورًا، واختياريًا workspaceIds لحصر العضو فيها.

المعاملات والاستجابات

GET /members

لا معاملات ولا حقول متن معلنة.

الاستجابةListMembersResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /members

الاسمالموضعالنوع
emailbodystring
rolebodystring
workspaceIdsbodystring[]
الاستجابةAckResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

PATCH /members/{id} · DELETE /members/{id} · DELETE /invitations/{id}

تغيير الدور يتطلب member:update_role؛ والإزالة تتطلب member:remove؛ وإبطال الدعوة يتطلب member:invite.

وإزالة عضو تحذف قنوات تنبيهه الشخصية — جهازه، ودردشته الخاصة، ورقم هاتفه — مع مفاتيح الـ API التي يملكها. أما القنوات المشتركة فلا تُمس. ولا يمكن إزالة آخر مالك ولا خفض دوره.

المعاملات والاستجابات

PATCH /members/{id}

الاسمالموضعالنوع
id إلزاميpathstring
rolebodystring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /members/{id}

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /invitations/{id}

الاسمالموضعالنوع
id إلزاميpathstring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /maintenance · POST /maintenance · DELETE /maintenance

نوافذ لا يُنبَّه فيها أحد. والفحوص افتراضيًا تظل تعمل وتُسجَّل، فتُحتسب تلك الدقائق في الجاهزية كغيرها؛ وبقيمة keepChecking الخاطئة لا يجري أي فحص ما دامت النافذة مفتوحة، فيبقى في السجل فراغ لا هبوط. القراءة تتطلب incident:read؛ والكتابة تتطلب maintenance:manage.

وتحمل title وstartsAt وendsAt و timezone وmonitorIds وrecurrenceRule و keepChecking وshowOnStatusPage و notifySubscribers. والنافذة المتكررة صف واحد لا صفوف كثيرة.

تكرّر القاعدة الفترة في التوقيت المحلي نفسه ضمن timezone الخاصة بها، فالفترة التي تعبر تغيير التوقيت تبقى عند الساعة المقرّرة. تُوسَّع FREQ=DAILY وFREQ=WEEKLY وFREQ=MONTHLY، ويمكن معها INTERVAL وCOUNT وUNTIL وBYDAY أو BYMONTHDAY يسمّي اليوم الذي تبدأ فيه الفترة نفسها. وأي قاعدة أخرى تُخزَّن وتُعاد إليك كما هي ولا تحجب التنبيهات إلا في أول مرة — ولا يجري تخمينها أبدًا.

المعاملات والاستجابات

GET /maintenance

الاسمالموضعالنوع
pastqueryboolean
الاستجابةListMaintenanceResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /maintenance

الاسمالموضعالنوع
titlebodystring
descriptionbodystring
workspaceIdbodystring
monitorIdsbodystring[]
startsAtbodystring
endsAtbodystring
recurrenceRulebodystring
timezonebodystring
keepCheckingbodyboolean
showOnStatusPagebodyboolean
notifySubscribersbodyboolean
الاستجابةCreatedResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /maintenance

الاسمالموضعالنوع
idquerystring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /on-call

التناوبات وسياسات التصعيد والاستثناءات، ومن في المناوبة الآن. تتطلب oncall:read.

وonCallNow يُحسب في اللحظة التي تسأل فيها، ويقول viaOverride إن كان قد جاء من التناوب أو ممن يغطّي عنه. وunreachable يسمّي المشاركين الذين لا قناة لديهم تصل إليهم فعلًا، وهو العطل الذي يستحق أن يُكتشف قبل الحادث لا أثناءه.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةGetOnCallResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /agents · POST /agents · DELETE /agents · GET /agents/{id}/metrics

وكلاء الخوادم يبلّغون عن المعالج والذاكرة والقرص من أجهزتك أنت. التسجيل يتطلب agent:enroll، والقراءة تتطلب agent:read، والإزالة تتطلب agent:delete.

ويعيد التسجيل رمزًا، مرة واحدة. فهو ما يصادق به الوكيل، ولذلك لا يمكن قراءته بعد ذلك أبدًا.

المعاملات والاستجابات

GET /agents

لا معاملات ولا حقول متن معلنة.

الاستجابةListAgentsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /agents

الاسمالموضعالنوع
namebodystring
workspaceIdbodyrequests.NullableString
الاستجابةEnrolledAgentResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /agents

الاسمالموضعالنوع
idquerystring
idbodystring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /agents/{id}/metrics

الاسمالموضعالنوع
id إلزاميpathstring
hoursqueryinteger
limitqueryinteger
الاستجابةGetAgentMetricsResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /api-keys · POST /api-keys · DELETE /api-keys

القراءة تتطلب api_key:read؛ والإنشاء والإبطال يتطلبان api_key:manage. ويحمل كل منها id وname و prefix وscopes وworkspaceIds و owner وcreatedAt وlastUsedAt و expiresAt وrevokedAt.

وtoken لا يُعاد إلا عند الإنشاء. وprefix هو الجزء القابل للعرض، وهو ما يتيح لك التمييز بين مفتاحين في قائمة دون أن يكون أي منهما قابلًا للقراءة.

ويرث المفتاح دور العضوية التي أنشأته وحصرها في مساحات العمل، فلا يمكن أن يكون المفتاح طريقًا للالتفاف على حدٍّ يخضع له صاحبه.

المعاملات والاستجابات

GET /api-keys

لا معاملات ولا حقول متن معلنة.

الاستجابةListApiKeysResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

POST /api-keys

الاسمالموضعالنوع
namebodystring
scopesbodystring[]
workspaceIdsbodystring[]
expiresInDaysbodyrequests.NullableInt64
الاستجابةCreatedApiKeyResponse
رموز الحالة201 400 401 403 404 429
حد الطلبات30 في الدقيقة

DELETE /api-keys

الاسمالموضعالنوع
idquerystring
idbodystring
الاستجابةAckResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /audit

تغييرات الإعدادات، ومن أجراها وما الذي تغيّر. تتطلب audit_log:read، وهي لخطة Business وما فوقها.

والتصفّح بـ nextBefore لا برقم الصفحة، فلا تتزحزح حدود الصفحة وأنت تقرؤها. وتُسجَّل القيود في كل خطة — فالخطة تحكم القراءة، والترقية تفتح السجل كله بدلًا من أن تبدأ سجلًا جديدًا.

ولا تُكتب بيانات الاعتماد ولا التجزئات ولا الأسرار في changes أبدًا.

المعاملات والاستجابات
الاسمالموضعالنوع
limitqueryinteger
الاستجابةListAuditResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

GET /me

من هو هذا المفتاح، وما الذي يبلغه، وما الذي تسمح به الخطة. لا تحتاج إلى أي صلاحية — فكل مفتاح يستطيع وصف نفسه.

وتحمل user وorganization وmembership (الدور والحصر في مساحات العمل) وentitlements (حدود الخطة بعد حلّها، مع طيّ أي حزم إضافية فيها) وusage. استخدمها للتحقق من حدٍّ قبل محاولة الإنشاء بدلًا من التحقق بعد الرفض.

والجلسة تحصل أيضًا على organizations، التي تسرد كل مؤسسة ينتمي إليها الشخص. أما مفتاح الـ API فلا: فهو يُصدر في مقابل عضوية واحدة ومحصور فيها، وسرد البقية إعلان عن مؤسسات لا تبلغها بيانات الاعتماد تلك.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةGetMeResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات120 في الدقيقة

DELETE /account

يحذف المؤسسة وكل ما فيها. ولا يحرس هذه النقطة ثابت صلاحيات، لأن الملكية هي الفحص: فهي مرفوضة لكل من ليس مالكًا.

وهذا لا رجعة فيه وليس إيقافًا مؤقتًا. استخدمه عن قصد.

المعاملات والاستجابات

لا معاملات ولا حقول متن معلنة.

الاستجابةAccountDeletedResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

POST /billing/apple/verify

يؤكد عملية شراء داخل التطبيق تمت في تطبيقنا المحمول. تتطلب billing:manage.

وهي موثّقة للاكتمال لا للاستعمال: فلا يمكن استدعاؤها إلا بإيصال أصدرته Apple لتطبيقنا، فليس فيها ما يفعله تكامل خارجي. وذُكرت هنا لأن مسارًا موجودًا وغير موصوف في أي مكان لا يُفرَّق عن مسار نسيه أحدهم.

المعاملات والاستجابات
الاسمالموضعالنوع
transactionIdbodystring
الاستجابةAppleVerifyResponse
رموز الحالة200 400 401 403 404 429
حد الطلبات30 في الدقيقة

GET /

الفهرس. يسرد المسارات التي يقدّمها هذا النشر، وهو النسخة القابلة للقراءة آليًا من هذه الصفحة وهو محدَّث دائمًا — إذ يُولَّد مما هو مركّب فعلًا.

تغذية الحوادث (RSS وAtom)

كل حادث في حسابك على هيئة تغذية، لقارئ تغذيات لا لمكتبة برمجية. أنشئ الرابط من لوحة التحكم في الإعدادات ← التنبيهات:

https://vitrinaengine.com/feeds/incidents/vtf_…/feed.xml
https://vitrinaengine.com/feeds/incidents/vtf_…/atom.xml

الرابط نفسه هو بيانات الاعتماد. لا ترويسة تُرسل: من يملك الرابط يقرأ كل حادث في الحساب، عبر كل مساحات العمل. ويظل معروضًا في لوحة التحكم كلما احتجته مرة أخرى، لأنه يعيش في قارئ تغذيات سيعيد أحدهم تثبيته يومًا ما — ويمكن استبداله أو إلغاؤه، ويسري ذلك من الطلب التالي لا عند انتهاء ذاكرة مؤقتة.

وهو يحمل وقائع الحادث فقط: اسم المراقب، والسبب، والخطورة، والحالة، ووقت الفتح والإغلاق، والمستجدّات الموسومة عامة. لا تقرير لاحق أبدًا، ولا إعدادات المراقب، ولا المكان الذي جرى منه الفحص. ومعظم القارئات تزامن عبر خوادم طرف ثالث، ولذلك كُتب المستند كأنه يغادر مبناك، لأنه يغادره.

الاستعلام مرة كل دقيقة أمر متوقع. وبعد ستين طلبًا في الدقيقة للرابط الواحد يردّ بـ 429، والرابط الذي لم يكن صالحًا قط أو استُبدل أو أُلغي يردّ بـ 404 — الجواب نفسه في الحالات الثلاث، حتى لا يُستدلّ به على الرموز التي كانت حقيقية يومًا.

ما لا تعيده هذه الـ API عن قصد

  • config الخاص بمراقب. فقد يحتوي على بيانات اعتماد.
  • المنطقة التي جرى منها الفحص. فأين نفحص قرارنا نحن ويمكننا تغييره ما دمنا نضع المسابير وننقلها. وذكره وعد عن بنيتنا التحتية لا تستطيع التصرف بناءً عليه، كما أنه لا يُعرض في أي موضع آخر من المنتج.

Exporting your data

Two routes hand back a file rather than a message, so that taking your data out does not mean paging through a collection endpoint a thousand times. Both are on every plan, the free one included — what a plan changes is how much history there is to export, not whether you may.

GET /export/{entity}

نوع واحد من الصفوف، بصيغة CSV أو JSON. entity هو أحد monitors أو hosts أو status-pages أو notification-channels أو members أو incidents أو incident-events أو postmortems أو audit-log أو error-issues أو uptime-daily أو uptime-hourly أو analytics-hourly. وأي قيمة أخرى تُجيب بـ 404.

format هو csv (الافتراضي) أو json، و from وto طوابع زمنية بصيغة RFC 3339. أما bom فيضيف علامة ترتيب البايتات UTF-8 إلى ملف CSV: يحتاجها Excel للأسماء غير اللاتينية، بينما تقرأها معظم لغات البرمجة النصية كجزء من عنوان العمود الأول — لذلك فهي معطَّلة ما لم تطلبها.

المعاملات والاستجابات
الاسمالموضعالنوع
entity إلزاميpathstring
bomqueryboolean
formatquerystring
fromquerystring
toquerystring
رموز الحالة200 400 401 403 404 429
حد الطلبات6 في الساعة

GET /export

كل ما يستطيع المفتاح قراءته، في ملف zip: ملف لكل كيان، إضافةً إلى manifest.json الذي يبيّن محتوى الأرشيف وعدد صفوف كل ملف والكيانات الغائبة. وما لا يستطيع دور المفتاح قراءته يُحذف بدل رفض الطلب بأكمله، والبيان هو ما يمنع حدوث ذلك بصمت.

المعاملات والاستجابات
الاسمالموضعالنوع
bomqueryboolean
formatquerystring
fromquerystring
toquerystring
رموز الحالة200 400 401 403 404 429
حد الطلبات6 في الساعة

What an export does not contain

التصدير لا يحتوي على أي شيء يُستخدم للمصادقة: لا إعدادات القنوات، ولا رموز heartbeat، ولا بصمات كلمات المرور. أما إعدادات المراقب فمُضمَّنة، بعد إزالة كل ما يشبه بيانات الاعتماد — جسم الطلب والترويسات وسلسلة مجتمع SNMP وبيانات صندوق البريد. ولا تتضمَّن نتائج الفحص الخام: تحذفها مدة الاحتفاظ، لذا تأتي نسبة التوافر من التجميعات.

Size, and the one refusal you may meet

السلاسل الساعية محدودة بـ 92 يومًا لكل طلب؛ وتُرفض أي نافذة أوسع برمز export_window_too_wide بدلًا من تقليصها بصمت. ولها حد خاص: 6 عمليات تصدير في الساعة لكل مؤسسة.

الإصدارات

رقم الإصدار في المسار. وستُضاف حقول إلى الاستجابات — عامل ما لا تعرفه على أنه شيء يُتجاهل لا خطأ — لكن لن يُحذف شيء من v1 ولن يتغير معناه داخلها.

هل ينقصك شيء؟

السطح صغير عن قصد: يغطي لوحة جدارية، وملخصًا في محادثة، ونص نشر يُسكت مراقبًا طوال الإصدار. فإن كنت تبني شيئًا لا يبلغه، فاكتب إلى support@vitrinaengine.com — فمعرفة ما يريده الناس فعلًا هو ما تُختار به نقطة النهاية التالية.

الأسعار · الشروط