واجهة REST API

ارفع الملفات، أنشئ مجموعات، وادِر المشاركات عبر HTTP. جميع الردود بصيغة JSON؛ لا يلزم مفتاح API لعمليات الرفع المجهولة.

مقدمة

تعمل واجهة storage.to API على تشغيل سطر الأوامر (CLI) وتطبيق سطح المكتب وأداة رفع الويب وأي عميل تابع لجهة خارجية تريد بناؤه.

تدفق الرفع على ثلاث خطوات:

  1. تهيئة — أخبرنا أنك تريد رفع ملف. سنُرجع عنوان URL مُوقّعًا مسبقًا واحدًا أو أكثر يشير إلى Cloudflare R2.
  2. الرفع إلى R2 — :قم بإرسال بياناتك (bytes) مباشرةً إلى عناوين URL المُوقَّعة مسبقًا. لا تمر البيانات عبر خوادمنا.
  3. تأكيد — أخبرنا أن عملية الرفع اكتملت. سننشئ سجل File ونزوّدك بعنوان URL قابلًا للمشاركة.

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

https://storage.to/api

جميع نقاط النهاية أدناه مرتبطة بهذا الأساس. مثال: POST /upload/init تعني POST https://storage.to/api/upload/init.

المصادقة

معظم نقاط النهاية لا تتطلب مصادقة. الرفع المجهول ميزة أساسية.

المصادقة اختيارية وتتيح:

  • عمليات الرفع المرتبطة بحسابك (تظهر في /dashboard)
  • ميزات Premium (ملفات دائمة، مساحة تخزين أكبر)
  • عمليات تعديل بناءً على الملكية (حذف، تعيين كلمة مرور، تغيير تاريخ الانتهاء) دون الحاجة إلى مطابقة visitor-token

نستخدم رموز Laravel Sanctum bearer. أنشئ رمزًا عبر تسليم OAuth لسطح المكتب أو تسجيل الدخول عبر الويب، ثم أرسله كـ:

Authorization: Bearer <token>

رمز الزائر

يحتاج العملاء المجهولون إلى طريقة لإثبات ملكيتهم لعمليات الرفع الخاصة بهم دون حساب. نستخدم رمز الزائر (visitor token) — سلسلة عشوائية ينشئها العميل مرة واحدة ويعيد استخدامها. أرسلها مع كل طلب:

X-Visitor-Token: <random-string>

على الويب، يتم تخزين الرمز تلقائيًا في ملف تعريف الارتباط visitor_token. يقوم سطر الأوامر (CLI) بتخزينه في ~/.config/storageto/token (انظر مستندات CLI).

بالنسبة لنقاط النهاية الخاصة بالعمليات (delete، set password، change expiry)، يتم تأكيد الملكية إذا إما كان رمز الزائر مطابقًا أو إذا جاءت الطلب من نفس عنوان IP الذي أنشأ الملف. يمكن أن يضيع كلاهما (حذف الكوكيز، تغييرات الشبكة). يُعدّ رمز المالك هو الدليل المفضل للمضي قدمًا.

رمز المالك

كل نقطة نهاية تنشئ موردًا (/upload/init multipart، /upload/confirm، /upload/reserve، /collection) تُرجع owner_token ضمن الاستجابة. الرمز هو إثبات ملكية مُوقّع مرتبط بهذا المورد تحديدًا، ومستقل عن عنوان IP أو رمز الزائر لديك.

احفظ الرمز إلى جانب معرّف المورد وأرسله مع أي عملية (mutation) كما يلي:

Authorization: Owner <token>

أو، إذا كنت تستخدم بالفعل Authorization: Bearer لجلسة مُصادَقة، أرسله كما يلي:

X-Owner-Token: <token>

يقبل الخادم رمز المالك كدليل ملكية صالح إلى جانب آلية الرجوع القديمة رمز الزائر (visitor token) + IP — فالعملاء الذين يحملون الرمز يستمرون في العمل بعد تغيير الشبكات أو مسح الكوكيز، والذين لا يحملونه يعملون تمامًا كما كان من قبل.

تعيش الرموز طالما يعيش المورد، وهي آمنة للاحتفاظ بها ولا تنتهي بشكل مستقل. تعني فقدان الرمز فقدان السيطرة على ذلك المورد (الملف/المجموعة/الرفع) — تعامل معها مثل كلمات المرور المحلية.

الأخطاء

تتبع الأخطاء شكلًا ثابتًا:

{
  "success": false,
  "error": "Human-readable message"
}

أكواد حالة HTTP الشائعة:

الكودالمعنى
200حسنًا.
201تم الإنشاء.
400طلب غير صالح (مثل تجاوز حد حجم المجموعة).
401كلمة المرور مطلوبة أو غير صحيحة.
403غير مصرح (لست مالك المورد).
404لم يتم العثور على المورد أو أنه انتهت صلاحيته.
422فشل التحقق، أو يوجد تقييد على الخطة/الحصة.
429تم تجاوز حد المعدّل أو حصة الرفع.
500خطأ في الخادم. تحقق من الحالة.

حدود المعدّل

جميع حدود المعدّل لكل عنوان IP. تتضمن استجابة 429 رؤوس Retry-After و X-RateLimit-Limit و X-RateLimit-Remaining القياسية.

النطاقالحد
بدء الرفع / تأكيد / إلغاء60 / دقيقة
إكمال الرفع متعدد الأجزاء500 / دقيقة
روابط أجزاء الرفع متعدد الأجزاء120 / دقيقة
بدء / تأكيد دفعي500 / دقيقة
استعلامات الحالة (الملف والمجموعة)120 / دقيقة
الإعدادات (كلمة المرور، تاريخ الانتهاء، الحد الأقصى للتنزيلات)30 / دقيقة
التحقق من كلمة المرور10 / دقيقة
إنشاء مجموعة30 / دقيقة
إدارة (ready، delete)60 / دقيقة
رفع صورة مصغّرة120 / دقيقة
رفع عبر ShareX20 / يوم
تحليلات التطبيق / الأخطاء120 و 60 / دقيقة

حصة الرفع: لعملاء مجهولين حدّان يعملان بالتوازي — 100 جيجابايت / 24 ساعة لكل رمز الزائر (visitor token) و 500 جيجابايت / 24 ساعة لكل IP (حدّ IP يلتقط حركة المرور بدون رمز والشبكات المشتركة). عند تجاوز أيٍّ منهما ستحصل على 429 مع التفاصيل. هذا رفع مخصص للحمولة فقط — التنزيلات غير محدودة وغير مُقيّدة (تُقدَّم مباشرةً من عناوين R2 المُوقَّعة).

رفع

تدفق الرفع من ثلاث خطوات لأي ملف، بما في ذلك الملفات التي تتجاوز 5 جيجابايت (يتم تلقائيًا تقسيمها إلى أجزاء multipart). إذا كنت تحتاج فقط إلى رفع سريع بأسلوب لقطة شاشة، فراجع ShareX بدلًا من ذلك.

POST /upload/init 60/min

ابدأ عملية رفع. للملفات >50 ميجابايت تكون الاستجابة رفعًا متعدد الأجزاء (حقل type: "multipart")؛ وإلا فسيكون PUT واحد مُوقّع مسبقًا.

نص الطلب

الحقلالنوعالوصف
filenamestring · requiredاسم الملف الأصلي. بحد أقصى 255 حرفًا.
content_typestring · requiredنوع MIME.
sizeinteger · requiredحجم الملف بالبايت. الحد الأدنى 1.
Request
curl -X POST https://storage.to/api/upload/init \ -H "Content-Type: application/json" \ -H "X-Visitor-Token: abc123" \ -d '{ "filename": "report.pdf", "content_type": "application/pdf", "size": 2202009 }'
Response · single upload
{ "success": true, "type": "single", "upload_url": "https://r2.cloudflarestorage.com/...signed...", "headers": { "Host": ["..."] }, "r2_key": "uuid-abc123" }
Response · multipart
{ "success": true, "type": "multipart", "upload_id": "01HXYZ...", "r2_key": "uuid-abc123", "part_size": 33554432, "total_parts": 4, "initial_urls": { "1": "https://...", "2": "https://..." }, "owner_token": "owner_v1_..." }
POST /upload/parts Owner only 120/min

اطلب عناوين URL إضافية للأجزاء لرفع متعدد الأجزاء قيد التنفيذ. يُستخدم عندما تُرجع /init عناوين URL أقل مما لديك من أجزاء (أو كانت قد انتهت صلاحيتها).

نص الطلب

الحقلالنوعالوصف
upload_idstring · requiredupload_id القادم من /init.
part_numbersarray<int> · requiredأرقام الأجزاء للحصول على عناوين URL لها.
Request
curl -X POST https://storage.to/api/upload/parts \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ...", "part_numbers": [3, 4] }'
Response
{ "success": true, "part_urls": [ { "partNumber": 3, "url": "https://..." }, { "partNumber": 4, "url": "https://..." } ] }
POST /upload/complete-multipart Owner only 500/min

أكمل رفع متعدد الأجزاء على R2 بمجرد رفع جميع الأجزاء.

نص الطلب

الحقلالنوعالوصف
upload_idstring · requiredupload_id القادم من /init.
partsarray · requiredكل إدخال: { partNumber, etag } من استجابة R2.
Request
curl -X POST https://storage.to/api/upload/complete-multipart \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ...", "parts": [ { "partNumber": 1, "etag": "\"abc...\"" }, { "partNumber": 2, "etag": "\"def...\"" } ] }'
Response
{ "success": true }
POST /upload/abort Owner only 60/min

ألغِ رفعًا متعدد الأجزاء ونظّف أي بيانات جزئية على R2.

نص الطلب

الحقلالنوعالوصف
upload_idstring · requiredالرفع الذي يجب إلغاؤه.
Request
curl -X POST https://storage.to/api/upload/abort \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ..." }'
POST /upload/confirm 60/min

أكد أن الرفع اكتمل. عندها ننشئ سجل File ونُرجع عنوان URL القابل للمشاركة.

نص الطلب

الحقلالنوعالوصف
filenamestring · requiredاسم الملف الأصلي.
sizeinteger · requiredحجم الملف بالبايت.
content_typestring · requiredنوع MIME.
r2_keystring · requiredr2_key القادم من /init.
collection_idstring · optionalإرفاقه إلى مجموعة.
crc32integer · optionalمجموع CRC32 للتحقق من سلامة البيانات.
file_idstring(9) · optionalإتمام معرف ملف محجوز سابقًا.
Request
curl -X POST https://storage.to/api/upload/confirm \ -H "Content-Type: application/json" \ -H "X-Visitor-Token: abc123" \ -d '{ "filename": "report.pdf", "size": 2202009, "content_type": "application/pdf", "r2_key": "uuid-abc123" }'
Response
{ "success": true, "file": { "id": "FQxyz1234", "url": "https://storage.to/FQxyz1234", "raw_url": "https://storage.to/r/FQxyz1234", "filename": "report.pdf", "size": 2202009, "human_size": "2.1 MB", "expires_at": "2026-04-15T12:00:00Z" }, "owner_token": "owner_v1_..." }
POST /file/reserve 60/min

احجز معرف ملف وعنوان URL قابل للمشاركة قبل أن تصبح البيانات جاهزة. مفيد عندما تحتاج إلى مشاركة رابط أولًا ثم إتمام الرفع لاحقًا. ترتبط الملكية برمز الزائر + عنوان IP الخاصين بك. أنهِ الرفع لاحقًا باستخدام /upload/init + /upload/confirm، مع تمرير file_id للتأكيد.

نص الطلب

الحقلالنوعالوصف
filenamestring · optionalاسم ملف بديل. القيمة الافتراضية هي "Pending".
content_typestring · optionalنوع MIME بديل.
Request
curl -X POST https://storage.to/api/file/reserve \ -H "X-Visitor-Token: abc123"
Response
{ "success": true, "file": { "id": "FQxyz1234", "url": "https://storage.to/FQxyz1234", "raw_url": "https://storage.to/r/FQxyz1234", "expires_at": "2026-04-12T18:00:00Z" }, "owner_token": "owner_v1_..." }
POST /upload/init-batch 500/min

مكافئ الدفعات لـ /upload/init، مُحسّن لرافع الويب. يبدأ حتى 250 ملفًا في رحلة واحدة.

يُستخدم داخليًا بواسطة رافع الويب. يجب أن يفضّل معظم العملاء استخدام /upload/init لملف واحد.

POST /upload/confirm-batch 500/min

مكافئ الدفعات لـ /upload/confirm. يؤكد رفع العديد من الملفات في رحلة واحدة.

المجموعات

تجمع المجموعة عدة ملفات تحت عنوان URL واحد للمشاركة (/c/{id}). حتى 10,000 ملف وبإجمالي 25 جيجابايت.

POST /collection 30/min

أنشئ مجموعة جديدة. أرفق الملفات لاحقًا عبر تمرير collection_id على /upload/confirm.

نص الطلب

الحقلالنوعالوصف
expected_file_countinteger · optionalتلميح لتعليم المجموعة تلقائيًا أنها جاهزة بمجرد تأكيد جميع الملفات المتوقعة.
Request
curl -X POST https://storage.to/api/collection \ -H "Content-Type: application/json" \ -H "X-Visitor-Token: abc123" \ -d '{ "expected_file_count": 3 }'
Response
{ "success": true, "collection": { "id": "ABC123xyz", "url": "https://storage.to/c/ABC123xyz", "expires_at": "2026-04-15T12:00:00Z" }, "owner_token": "owner_v1_..." }
GET /collection/{id}/status 120/min

استعلم عن حالة المجموعة. كما يعلّم المجموعة تلقائيًا أنها جاهزة إذا تم تأكيد جميع الملفات المتوقعة.

Request
curl https://storage.to/api/collection/ABC123xyz/status
Response
{ "success": true, "files": [ /* file objects: id, url, filename, size, ... */ ], "is_uploading": false, "file_count": 3, "expected_file_count": 3, "total_size": 6291456, "human_total_size": "6 MB" }
POST /collection/{id}/ready Owner only 60/min

علّم المجموعة على أنها جاهزة للتنزيل. ليس مطلوبًا عادةً — تصبح المجموعات جاهزة تلقائيًا بمجرد الوصول إلى expected_file_count.

DELETE /collection/{id} Owner only 60/min

احذف مجموعة وجميع ملفاتها.

POST /collection/{id}/password Owner only 30/min

عيّن كلمة مرور للمجموعة. تتطلب 4–100 حرفًا.

نص الطلب

الحقلالنوعالوصف
passwordstring · required4–100 حرفًا.
Request
curl -X POST https://storage.to/api/collection/ABC123xyz/password \ -H "X-Visitor-Token: abc123" \ -d '{ "password": "hunter22" }'
DELETE /collection/{id}/password Owner only 30/min

إزالة كلمة المرور من المجموعة.

POST /collection/{id}/verify-password 10/min

تحقق من كلمة المرور. تُرجع 200 عند النجاح و 401 عند كلمة مرور غير صحيحة.

نص الطلب

الحقلالنوعالوصف
passwordstring · required
POST /collection/{id}/expiry Owner only 30/min

تغيير مدة انتهاء صلاحية المجموعة (collection).

نص الطلب

الحقلالنوعالوصف
daysinteger · optionalمن الآن خلال 1–7 أيام. احذفها أو استخدم null للمدة الدائمة (فقط للمميز).
POST /collection/{id}/max-downloads Owner only 30/min

حدّد سقفًا للتنزيل (burn-after-N-downloads). يتم حذف المجموعة تلقائيًا عند الوصول إلى الحد.

نص الطلب

الحقلالنوعالوصف
max_downloadsinteger · optional1–1000. يجب أن يتجاوز عدد التنزيلات الحالي. استخدم null لإزالة السقف.

الملفات

تطابق جميع إعدادات مستوى الملف (كلمة المرور، الانتهاء، الحد الأقصى للتنزيلات) نقاط نهاية المجموعة. للمالك فقط.

GET /file/{id}/status 120/min

تحقق مما إذا كان الملف لا يزال بانتظار رفعه.

Response
{ "pending": false }
DELETE /file/{id} Owner only 60/min

احذف الملف فورًا.

POST /file/{id}/thumbnail Owner only 120/min

ارفع صورة مصغّرة لفيديو أو ملف صورة (تُستخدم في صفحة التنزيل). بحد أقصى 2 ميجابايت.

نص الطلب

الحقلالنوعالوصف
thumbnailimage · requiredرفع متعدد الأجزاء. بحد أقصى 2 ميجابايت.
Response
{ "success": true, "thumbnail_url": "https://..." }
POST /file/{id}/password Owner only 30/min

عيّن كلمة مرور لملف. تتطلب 4–100 حرفًا.

DELETE /file/{id}/password Owner only 30/min

إزالة كلمة مرور الملف.

POST /file/{id}/verify-password 10/min

التحقق من كلمة مرور الملف.

POST /file/{id}/expiry Owner only 30/min

تغيير مدة انتهاء صلاحية الملف.

نص الطلب

الحقلالنوعالوصف
daysinteger · optionalمن الآن خلال 1–7 أيام. احذفها أو استخدم null للمدة الدائمة (فقط للمميز).
POST /file/{id}/max-downloads Owner only 30/min

تحديد الحد الأقصى لإجمالي تنزيلات الملف. يتم الحذف تلقائيًا عند الوصول إلى الحد.

رفع عبر ShareX

نقطة نهاية رفع بنقرة واحدة — أرسل ملفًا متعدد الأجزاء، واحصل على عنوان URL قابل للمشاركة. بدون رقصة init/confirm. مثالي لأدوات لقطات الشاشة. دليل الإعداد الكامل على /ar/docs/sharex.

POST /sharex/upload 20/day

ارفع صورة أو ملفًا مباشرةً (نموذج multipart، حقل file). بحد أقصى 25 ميجابايت.

Request
curl -X POST https://storage.to/api/sharex/upload \ -F "[email protected]"
Response
{ "success": true, "url": "https://storage.to/FQxyz1234", "raw_url": "https://storage.to/r/FQxyz1234", "filename": "screenshot.png", "expires_at": "2026-04-15T12:00:00Z" }

مصادقة سطح المكتب

للعملاء الموثّقين (مثل تطبيق سطح المكتب) الذين يحملون رمز Sanctum.

GET /user Bearer token

إرجاع المستخدم المُصادَق عليه.

Request
curl https://storage.to/api/user \ -H "Authorization: Bearer <token>"
Response
{ "id": 42, "name": "Ada", "email": "[email protected]", "is_premium": true }
POST /auth/logout Bearer token

إبطال رمز الوصول الحالي.

متفرقات

GET /health

فحص الحالة. يرسل ping إلى قاعدة البيانات وتخزين R2 وذاكرة التخزين المؤقت Redis. يُرجع 200 إذا كانت كلها تعمل بشكل جيد، و503 بخلاف ذلك.

Response
{ "status": "healthy", "checks": { "database": "ok", "storage": "ok", "cache": "ok" }, "timestamp": "2026-04-12T12:00:00Z" }
GET /activity

بث نشاط مباشر لواجهة الكرة على الصفحة الرئيسية. يتم تخزينه مؤقتًا على حافة Cloudflare.

GET /bandwidth/status 60/min

استخدام حصة الرفع الحالية للمتصل — يستخدمه كل من CLI وتطبيق سطح المكتب لعرض السعة المتبقية. شكل الاستجابة يختلف للمستخدمين المُصادَق عليهم. وعلى الرغم من اسم الرابط، فهذا يتتبع رفع البايتات فقط؛ لا يتم احتساب التنزيلات.

Response · anonymous
{ "success": true, "authenticated": false, "has_token": true, "limit_bytes": 107374182400, "limit_gb": 100, "used_bytes": 12345678, "used_gb": 0.01, "remaining_bytes": 107361836722, "remaining_gb": 99.99, "window_hours": 24 }
Response · authenticated
{ "success": true, "authenticated": true, "plan": "premium" }
POST /app-analytics 120/min

إرسال حدث استخدام من أداة سطر الأوامر (CLI) أو تطبيق سطح المكتب.

نص الطلب

الحقلالنوعالوصف
appstring · requireddesktop أو cli أو web.
versionstring · optionalإصدار العميل.
eventstring · requiredاسم الحدث، مثل upload_complete.
contextobject · optionalبيانات تعريف إضافية.
POST /app-errors 60/min

إرسال تقرير خطأ من أداة سطر الأوامر (CLI) أو تطبيق سطح المكتب. إزالة التكرار من جهة الخادم — بحد أقصى 10 من نفس الخطأ لكل ساعة.

نص الطلب

الحقلالنوعالوصف
appstring · requireddesktop أو cli أو web.
typestring · requiredفئة/نوع الخطأ.
messagestring · requiredرسالة الخطأ.
stackstring · optionalتتبّع المكدس (Stack trace).
version, os, os_version, arch, contextvarious · optionalبيانات تعريف تشخيصية.