انتقل إلى المقال

واجهة API

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

المصادقة

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

curl https://solta.now/v1/me \
  -H "Authorization: Bearer solta_…"

أما الموصلات فتستخدم OAuth: راجع ربط Claude أو ChatGPT. وكلاهما يؤدي إلى الحساب نفسه، بالصلاحيات نفسها.

نشر ملف

curl -X POST https://solta.now/v1/sites \
  -H "Authorization: Bearer solta_…" \
  -H "Content-Type: application/json" \
  -d '{"source": "export default () => <h1>hi</h1>",
       "filename": "App.tsx",
       "title": "Hello",
       "channel": "api"}'

يُرجع الـ slug ورقم النسخة والرابط. أرسل الترويسة Idempotency-Key، فلن تؤدي إعادة الطلب نفسه إلى النشر مرتين.

لدى من يستخدم Free 3 مواقع منشورة في الوقت نفسه، في مكتبته الخاصة ومساحات عمل Free التي يملكها مجتمعةً، ولدى من يستخدم Plus 15 موقعًا في مكتباته على Plus. أما Pro وTeam فبلا حد. وعند بلوغ الحد، يُقابَل أي موقع جديد (ملف أو مجلد أو إعادة استخدام) بالرمز 402 مع الكود site_limit: لا يُنشر شيء، ويسرد الرد المواقع المنشورة في sites، ولكل منها library الخاصة به، وعدد ما يجب إيقافه (toUnpublish)، ثم libraryUrl وupgradeUrl. أضف بدلًا من ذلك نسخة إلى أحد المواقع، فيبقى رابطه كما هو، أو أفسح مكانًا أولًا: POST /v1/sites/{id}/offline يوقف الموقع مع الاحتفاظ بكل شيء، وPOST /v1/sites/{id}/online يعيده، ويُرفض بالطريقة نفسها عند بلوغ الحد. ولا تُرفض نسخة جديدة من موقع لهذا السبب أبدًا.

نشر مجلد

نقطة نهاية (endpoint) منفصلة، لأن جسم الطلب ملف وليس JSON. أرسل الملف المضغوط في archive، أو رابطًا في url نقرؤه منه.

curl -X POST https://solta.now/v1/sites/archive \
  -H "Authorization: Bearer solta_…" \
  -F "archive=@dist.zip" \
  -F "title=My site"

تُستبعد الملفات التي لا يستخدمها الموقع ويُنشر الباقي: كل ما قد يحتوي على أسرار (.env وكل .env.*، و.npmrc، والمفاتيح الخاصة، وcredentials.json)، والملفات والمجلدات المخفية مثل .git، والأنواع التي لا نقدّمها، مثل كود الخادم. ويسردها الرد في skipped، ولكل منها path وreason قيمته secret أو hidden أو unsupported، ويقول الشيء نفسه في warnings ليقرأه الإنسان. والمجلد الذي يحتوي على الكود المصدري لتطبيق بدل نسخته المبنية (build) يُقابَل بالرمز 422 مع الكود needs_build.

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

POST /v1/sites/{id}/versions            → { number: 2, state: "draft" }
POST /v1/sites/{id}/versions/2/publish  → { number: 2, state: "live" }

أو طلب واحد: "publish": true في الطلب الأول ينشر النسخة فورًا، إلا إذا كان الموقع يحتاج إلى موافقة، وعندها يحتوي الرد على awaitsApproval: true وتنتظر النسخة كمسودة.

بين حين وآخر، تطلب فحوصاتنا أن يطّلع إنسان على صفحة قبل نشرها، وعادةً خلال يوم واحد. ويحتوي الرد عندها على held: { url }: يقول رابط الموقع إن الصفحة قيد الفحص حتى تُجاز، وurl صفحة تبيّن حالتها، ويستطيع فيها من نشر دون حساب أن يترك بريده الإلكتروني ليُبلَّغ. ولا يغيّر النشر مرة أخرى شيئًا.

يتغير المجلد بملفاته. يقبل POST /v1/sites/{id}/versions/files بيانات multipart form data: ملفات files للإضافة (يُفتح أي ملف .zip بينها، والملف الذي يحمل اسمًا موجودًا يحل محل القديم)، وremove لكل مسار تريد حذفه، وreplace=true عندما يكون ما ترفعه هو الموقع كله. ومع publish=true تُنشر النسخة في الطلب نفسه، إلا إذا كان الموقع يحتاج إلى موافقة، وعندها يحتوي الرد على awaitsApproval: true وتنتظر النسخة كمسودة. وبين عدة ملفات، أو داخل ملف .zip، يُستبعد هنا أيضًا ما يستبعده المجلد، ويُسرد في skipped. أما الملف الواحد المرسل وحده الذي لن ننشره فيُرفض.

البقية

GET /v1/library
مواقعك.
GET /v1/sites/{slug}
موقع واحد، ونسخته المنشورة، وسجلّه.
PATCH /v1/sites/{id}/visibility
من يمكنه فتح الموقع.
PATCH /v1/sites/{id}
عنوانه الظاهر، أو عنوانه على الويب عبر { "slug": "…" }. ويظل العنوان القديم يوجّه الناس إلى الموقع. العنوان القصير، من 4 أحرف أو أقل، أو العنوان المكوّن من كلمة واحدة، أي كلمة شائعة وحدها، يحتاج إلى Pro أو Team: في Free يُقابَل بالرمز 402 مع code: "needs_pro_short_address"، وبعد تجاوز ما تسمح به الخطة من العناوين القصيرة أو المكوّنة من كلمة واحدة، short_address_limit. والعنوان الذي يحمل اسم شركة أو مصرف يُقابَل بالرمز 422 مع slug_brand، في أي خطة.
GET, POST /v1/sites/{id}/addresses
عناوينه، وعنوان آخر عبر { "slug": "…" } يوجّه الزوار إلى العنوان الرئيسي (Pro وTeam). POST …/addresses/{slug}/main يجعل أحدها العنوان الرئيسي، وDELETE …/addresses/{slug} يجعله عنوانًا قديمًا. ويُرفض الطلب بأحد الأكواد needs_pro_extra_address أو extra_address_limit أو needs_pro_short_address أو short_address_limit أو slug_brand أو slug_taken.
GET /v1/sites/{id}/compare?from=1&to=2
ما الذي تغيّر بين نسختين.
DELETE /v1/sites/{id}
يتوقف عرض الموقع فورًا. ويبقى العنوان محجوزًا سنة على الأقل، وطوال مدة استخدامه. وبعد 6 أشهر بلا زيارات نراسلك بالبريد، وبعد شهر من ذلك يُحرَّر العنوان.

الأخطاء

جسم JSON فيه error، وdetail عندما يكون هناك ما يفيد إضافته. والملف الذي نرفضه (مفتاح متروك داخله، أو نوع غير مدعوم) يُقابَل بالرمز 422 مع السبب بكلمات واضحة، لا بتتبّع أخطاء (stack trace).