واجهة REST API

العنوان، وكيف يسجّل سكربت الدخول، وكيف تُختار المؤسّسة، وكيف تبدو الأخطاء، مع أمثلة كاملة بـ curl.

كل ما تفعله وحدة التحكّم والـ CLI، تفعلانه عبر واجهة HTTP API واحدة. الـ CLI مبنيّة عليها وليس لها باب خاص: كل ما يستطيعه isogrid، يستطيعه سكربت يحمل بيانات الاعتماد نفسها بـ curl.

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

العنوان

كل طلب يُرسل إلى https://api.isogrid.skyvault.pro/api/v1.

تصف الأمثلة أدناه ما تقبله الواجهة اليوم. تحقّق منها مجدّدًا بعد ترقية المنصّة بدل أن تفترض أن حقلًا ما زال موجودًا.

تسجيل الدخول من سكربت

يحمل كل طلب رمزًا:

Authorization: Bearer <token>

وهذا الرمز، في حالة السكربت، هو بيانات اعتماد CLI: رمز طويل العمر يبدأ بـ skv_، تنشئه أنت، باسمك، لمؤسّسة واحدة. تنشئه بالـ CLI وتوافق عليه في المتصفّح. ولا يوجد في وحدة التحكّم نموذج يسلّم رمزًا دون هذه الموافقة.

export ISOGRID_CONFIG_HOME="$(mktemp -d)"
isogrid --api https://api.isogrid.skyvault.pro login --name my-script
jq -r '.contexts[].token' "$ISOGRID_CONFIG_HOME/config.json"
rm -rf "$ISOGRID_CONFIG_HOME"

استخدام ISOGRID_CONFIG_HOME مؤقّت يُبقي تسجيل الدخول على جهازك كما هو. وتشرح صفحة تثبيت واجهة سطر الأوامر كيف تحصل على isogrid.

ما ينبغي معرفته عن بيانات الاعتماد:

  • هي مثبّتة على المؤسّسة الظاهرة في صفحة الموافقة. تحقّق منها قبل أن توافق.
  • لا تتجاوز أبدًا ما تملكه. تُقاطَع صلاحياتها مع دورك ومجموعاتك في كل طلب، فتضييق صلاحياتك يضيّق صلاحيات السكربت أيضًا.
  • ضيّقها. أضف --scope بما يحتاج إليه السكربت فقط، مثل --scope application:create,application:write-any. ودون --scope، تقترح صفحة الموافقة ما يناسب دورك وتزيل أنت العلامة عن الباقي. انظر النشر من CI/CD لمعرفة النطاقات التي يحتاج إليها النشر.
  • تدوم 90 يومًا ما لم تختر مدّة أقصر في صفحة الموافقة.
  • هناك أشياء لا تستطيعها أبدًا، مهما طلبت: الفوترة، وتعيين المسؤولين، وإنشاء بيانات الاعتماد أو إبطالها. هذه تحتاج إليك أنت، مسجّلًا دخولك في وحدة التحكّم.
  • أبطِلها من صفحة CLI في وحدة التحكّم حين يُستغنى عن السكربت أو حين يُحتمل أن الرمز تسرّب.

تفترض الأمثلة أدناه:

export ISOGRID_API=https://api.isogrid.skyvault.pro/api/v1
export ISOGRID_TOKEN=skv_...

أبقِ الرمز خارج سجلّ أوامر الصدفة وخارج مستودعك، كما تفعل مع كلمة مرور.

اختيار المؤسّسة

قد ينتمي الشخص إلى عدّة مؤسّسات، فكل ما يخصّ إحداها يحتاج إلى معرفة أيّها. تقول ذلك بترويسة، تعطي فيها slug المؤسّسة أو id الخاص بها:

X-Organization: acme

وتُقبل القيمة نفسها معاملًا في العنوان، ?organization=acme، للحالات التي تكون فيها الترويسة غير مريحة.

مع بيانات اعتماد CLI يمكنك إغفالها: فبيانات الاعتماد تخصّ مؤسّسة واحدة أصلًا وكل طلب يعمل فيها. وتسمية مؤسّسة أخرى تُرفض بـ 403، ويذكر الخطأ المؤسّسة التي ثُبّتت عليها بيانات الاعتماد.

كيف يبدو الخطأ

لكل رفض الشكل نفسه، أيًّا كان الخلل:

{
  "error": {
    "code": "permission_denied",
    "message": "Your role in Acme (developer) does not allow this",
    "details": {
      "required_permission": "application:create",
      "role": "developer",
      "organization": "acme"
    }
  }
}

message مكتوب ليُعرض على إنسان. وcode هو ما ينبغي أن يتفرّع عليه السكربت. وdetails يختلف باختلاف الخطأ وقد يكون فارغًا.

الحالة code المعنى
401 unauthenticated لا رمز، أو رمز مجهول أو منتهي الصلاحية أو مُبطَل.
402 insufficient_credits لا تستطيع المؤسّسة دفع ثمن ما طُلب. يذكر details المبلغ المطلوب.
403 permission_denied لا يحقّ لك، أو لبيانات الاعتماد هذه، فعل ذلك.
404 not_found غير موجود، أو ليس لك أن تراه.
409 conflict يتعارض مع ما هو موجود: اسم مأخوذ، أو منتَج لا سعر له بعد في تلك المنطقة.
422 validation_error الطلب غير سليم الصياغة. يسمّي details.fields كل حقل وما الخطأ فيه.
503 no_capacity لا تستطيع المنصّة استضافة هذا الآن. الطلب لم يكن خاطئًا؛ أعد المحاولة لاحقًا.

مع curl، استخدم -f (أو --fail-with-body للاحتفاظ بالرسالة) حتى يُفشل الرفضُ سكربتك بدل أن يُمرَّر إلى الأمر التالي.

القوائم والصفحات

القوائم الرئيسية (التطبيقات، قواعد البيانات، خوادم قواعد البيانات، الشبكات، المناطق، الصور) تعيد صفحة واحدة في كل مرّة:

{ "items": [ ... ], "total": 37, "limit": 50, "offset": 0 }

limit قيمته الافتراضية 50 وأقصاه 200. وoffset هو موضع بداية الصفحة. لقراءة كل شيء، أضف limit إلى offset حتى يبلغ total.

ليست كل القوائم مقسّمة هكذا. بعض القوائم القصيرة (عمليات بناء تطبيق، أنواع النسخ في منطقة) تعيد مصفوفة بسيطة. وتبيّن الأمثلة أدناه شكل كل واحدة.

ما يستغرق وقتًا

إنشاء شيء يعود قبل أن يعمل ذلك الشيء. يخبرك الجواب بأن الشيء موجود ويعطيك id الخاص به؛ ثم تقرأ حالته حتى تستقرّ.

ما طلبته جواب الطلب ثم اقرأ إلى أن
تطبيق 201، مع التطبيق GET /applications/{id}/status يصير deployment_status هو running أو failed
عملية بناء 202، مع build_id GET /applications/{id}/builds/{build_id} يصير status هو succeeded، أو أحد failed وno_dockerfile وrestricted وcancelled
إعادة نشر 202 GET /applications/{id}/status كما في التطبيق
قاعدة بيانات 202، مع قاعدة البيانات GET /databases/{id} يصير status هو ready أو failed

قيمة deployment_status لتطبيق هي إحدى none أو queued أو deploying أو starting أو running أو degraded أو stopped أو failed. وتعني degraded أنه يعمل لكن ليس كاملًا: نسخ عاملة أقلّ من المطلوب، أو نسخ لا تكفّ عن إعادة التشغيل. ويقول message المرافق السبب بالكلمات.

استعلم كل بضع ثوانٍ، لا في حلقة متلاحقة. ومخرجات البناء تُقرأ بالطريقة نفسها: يعيد GET /applications/{id}/builds/{build_id}/logs?after=0 الأسطر المكتوبة حتى الآن مع last_id؛ مرّره في after لتحصل على الجديد فقط.

أمثلة كاملة

من أنا، وأين أستطيع النشر

curl -fsS "$ISOGRID_API/me" -H "Authorization: Bearer $ISOGRID_TOKEN"

يعيد حسابك والمؤسّسات التي تنتمي إليها. وهذه المناطق المفتوحة لك، وأنواع النسخ التي تعرضها منطقة مع أسعارها:

curl -fsS "$ISOGRID_API/clusters" -H "Authorization: Bearer $ISOGRID_TOKEN" \
  | jq '.items[] | {id, slug, name}'

curl -fsS "$ISOGRID_API/pricing/applications/$CLUSTER_ID" \
  -H "Authorization: Bearer $ISOGRID_TOKEN" \
  | jq '.[] | {id, name, vcpu, memory_mb, prices}'

في الواجهة تُسمّى المنطقة cluster، ويُسمّى نوع النسخة resource_tier.

سرد تطبيقاتك

curl -fsS "$ISOGRID_API/applications?limit=20" \
  -H "Authorization: Bearer $ISOGRID_TOKEN" \
  | jq '.items[] | {id, slug, deployment_status, public_url}'

إنشاء تطبيق من صورة

curl -fsS -X POST "$ISOGRID_API/applications" \
  -H "Authorization: Bearer $ISOGRID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "hello",
    "source": "registry",
    "external_image": "nginx:1.27",
    "port": 80,
    "is_public": true
  }'

الجواب هو التطبيق، مع id وslug الخاصّين به، والعنوان الذي سيجيب عليه في public_url. وأول نشر له موضوع في الطابور أصلًا.

معاني الحقول، وما يحدث حين تغفل أحدها:

الحقل المعنى إن أُغفل
name إلزامي.
source registry لصورة؛ وgithub أو gitlab للبناء من مستودع. github
external_image صورة في أي سجلّ، باسمها الكامل: nginx:1.27، ghcr.io/acme/web:main.
external_registry_id السجلّ المحفوظ الذي تُسحب الصورة ببيانات اعتماده. يجب أن تكون الصورة عامّة.
cluster_id المنطقة. منطقة الشبكة التي سمّيتها، وإلّا فالمنطقة الافتراضية للمنصّة.
resource_tier_id نوع النسخة. أصغر ما تعرضه المنطقة.
network_id الشبكة الخاصة التي يعمل عليها. شبكة مؤسّستك في تلك المنطقة.
port المنفذ الذي تستمع عليه الحاوية. 8080 لصورة.
replicas عدد النسخ، من 1 إلى 10. 1
environment إعدادات غير سرّية، في صورة كائن من السلاسل النصّية. لا شيء.
is_public هل يمكن الوصول إليه من الإنترنت. false

الصورة الموجودة في سجلّ مؤسّستك تُسمّى بـ image_id بدل ذلك (يسردها GET /images). وللبناء من مستودع، أرسل repository_full_name (acme/api)، وdefault_branch إن لم يكن main؛ ويجب أن يكون المستودع مربوطًا بمؤسّستك مسبقًا، كما تشرح صفحة مستودعات Git.

الأسرار لا توضع في environment. أرسلها في secrets؛ فهي تُحفظ على حدة ولا يعيدها أي طلب أبدًا.

قراءة حالته

curl -fsS "$ISOGRID_API/applications/$APP_ID/status" \
  -H "Authorization: Bearer $ISOGRID_TOKEN"
{
  "application_id": "5b0c...",
  "deployment_status": "running",
  "desired": 1,
  "running": 1,
  "message": null,
  "checked_at": "2026-10-07T09:12:44Z",
  "listens": true,
  "tasks": [ ... ]
}

desired هو عدد النسخ المطلوبة وrunning عدد النسخ العاملة الآن. وللانتظار في سكربت:

while :; do
  STATUS=$(curl -fsS "$ISOGRID_API/applications/$APP_ID/status" \
    -H "Authorization: Bearer $ISOGRID_TOKEN" | jq -r '.deployment_status')
  echo "$STATUS"
  case "$STATUS" in running|degraded|stopped|failed) break ;; esac
  sleep 5
done

النشر من جديد

لتطبيق يشغّل صورة، أعد نشره:

curl -fsS -X POST "$ISOGRID_API/applications/$APP_ID/deploy" \
  -H "Authorization: Bearer $ISOGRID_TOKEN"

ولتطبيق مبنيّ من مستودع، ابدأ بناء فرع أو وسم أو إيداع؛ ويُنشر حين ينجح البناء:

curl -fsS -X POST "$ISOGRID_API/applications/$APP_ID/builds" \
  -H "Authorization: Bearer $ISOGRID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"git_ref": "main"}'

سرد قواعد بياناتك

curl -fsS "$ISOGRID_API/databases" -H "Authorization: Bearer $ISOGRID_TOKEN" \
  | jq '.items[] | {id, name, engine, status}'

هذه هي قواعد البيانات المنشأة على خادم مشترك. أمّا خوادم قواعد البيانات الخاصة بك فقائمة مستقلّة، GET /database-instances. وقيمة status لقاعدة بيانات هي إحدى pending أو creating أو importing أو ready أو failed أو deleting.

تفاصيل الاتصال، ومنها كلمة المرور، طلب مستقلّ (GET /databases/{id}/connection) بصلاحية مستقلّة: أن ترى أن قاعدة بيانات موجودة ليس كأن تُسلَّم بيانات اعتمادها.

حالات حدّية يحسن معرفتها قبل أن تصادفها

401 على رمز كان يعمل أمس. انتهت صلاحيته أو أُبطل. أنشئ واحدًا جديدًا؛ لا شيء آخر يتغيّر. والجواب واحد عمدًا للرمز المجهول والمنتهي والمُبطَل.

403 يسمّي مؤسّسة أخرى. أرسلت X-Organization لمؤسّسة ليست بيانات الاعتماد مثبّتة عليها. احذف الترويسة، أو أنشئ بيانات اعتماد بينما تعرض وحدة التحكّم المؤسّسة التي تقصدها.

409 عند الإنشاء يذكر سعرًا. هذا المنتَج لا سعر له بعد في تلك المنطقة، فهو غير معروض للبيع فيها. اختر منطقة أخرى أو اسأل. انظر الأسعار والفوترة.

402 على is_public. على مؤسّستك مبلغ مستحقّ عن استخدام سابق، والنشر للعموم موقوف حتى يُسدَّد. أنشئ التطبيق خاصًّا، أو اشحن رصيدك.

نجح طلب الإنشاء وفشل التطبيق. لم يَعِد الطلب إلا بأن التطبيق موجود. اقرأ /status، ثم سجلّ البناء أو النشر. وتتناول صفحة حين تسوء الأمور الأسباب المعتادة.

المبالغ بوحدة nanos. المبالغ المنتهية بـ _nanos أجزاء من مليار من وحدة العملة: 1500000000 تساوي 1.5. والكائن prices المجاور يحمل الرقم نفسه منسّقًا للعرض.

ماذا تقرأ بعد ذلك