التوثيقالتعامل مع الأخطاء
التعامل مع الأخطاء
افهم ردود الخطأ ورموزها، واعرف متى تعيد المحاولة ومتى تحتاج إلى تعديل الطلب.
ميز بين رفض الطلب وفشل التفريغ. في الحالة الأولى، لم يقبل API الطلب. وفي الثانية، قبله وبدأت المعالجة، لكنها انتهت لاحقا بحالة failed في حقل status.
بنية رد الخطأ
تأتي أخطاء الطلبات على /v1 بهذه البنية:
{
"error": {
"code": "insufficient_minutes",
"message": "Not enough minutes",
"retryable": false,
"action_url": "https://transcript1.com/dashboard/billing",
"minutes_needed": 20,
"minutes_remaining": 3
}
}اكتب منطق معالجة الخطأ بناء على code، لا نص الرسالة. اعرض message للمستخدم، لكن لا تعتمد على ثبات صياغتها. إذا كانت retryable تساوي true، فقد ينجح الطلب نفسه بعد الانتظار.
قد تجد حقولا إضافية إلى جانب retryable توضح ما تحتاج إلى فعله:
| الحقل | رمز الخطأ المرتبط به | ما الذي يوضحه؟ |
|---|---|---|
action_url | insufficient_minutes، no_active_plan، topup_needs_user | رابط شراء باقة أو شحن دقائق إضافية. |
minutes_needed، minutes_remaining | insufficient_minutes | الدقائق المطلوبة والدقائق المتبقية في رصيدك. تكون المطلوبة null إذا لم نعرف المدة بعد. |
reason، packs | topup_needs_user | سبب عدم الخصم من البطاقة، وعدد الحزم المطلوبة. |
supported_platforms | unsupported_platform | قيم المنصات المقبولة وهي ["youtube", "x", "tiktok", "instagram", "facebook", "bluesky", "twitch", "dailymotion", "pinterest", "linkedin", "snapchat"]. |
missing_chunks | upload_incomplete | أرقام الأجزاء التي لم تصل أثناء الرفع. |
max_bytes | media_too_large | حد حجم الملف المسموح لحسابك بالبايت. |
params | invalid_request | كائن يحدد الحقول غير الصالحة وسبب الخطأ في كل منها، عند فحص body أو query. |
لماذا لم يقبل API الطلب؟
| رمز HTTP | code | هل تعيد المحاولة؟ | السبب أو الإجراء المطلوب |
|---|---|---|---|
| 400، 422 | invalid_request | لا | حقل أو معامل ناقص أو غير صالح، أو JSON غير صالح في body. من أمثلته الجمع بين diarize وsource: "captions"، أو بين reuse_recent وwebhook_url. |
| 422 | invalid_url | لا | أرسل رابطا من YouTube أو X أو TikTok أو Instagram أو Facebook أو Bluesky، أو إحدى المنصات في المصادر والخيارات. تأكد أيضا أن platform يطابق الرابط. |
| 422 | unsupported_platform | لا | أرسلت قيمة غير مدعومة في platform. |
| 422 | unsupported_media | لا | امتداد الملف الذي رفعته غير مدعوم. |
| 401 | unauthorized | لا | بيانات المصادقة غائبة أو غير صالحة أو انتهت صلاحيتها أو ألغيت. وقد يكون token الرفع غير صالح أو منتهي الصلاحية. |
| 403 | insufficient_scope | لا | لا يملك OAuth token صلاحية transcriptions:read أو transcriptions:write المطلوبة. |
| 403 | email_not_verified | لا | أكد بريدك الإلكتروني أولا لتتمكن من إنشاء تفريغ أو جلسة مباشرة. |
| 402 | insufficient_minutes | لا | رصيدك القابل للاستخدام 0، أو لا يكفي لمدة التسجيل، أو أقل من دقيقة واحدة بدأت في جلسة مباشرة. إذا كان الشحن التلقائي مفعلا، يحاول transcript1 الشحن أولا. اشترِ الدقائق عبر action_url، أو دع وكيلا يشتريها عبر POST /v1/topups أو أداة MCP المسماة top_up. |
| 402 | no_active_plan | لا | حاولت شحن دقائق إضافية دون باقة مدفوعة نشطة. يصدر هذا الخطأ من POST /v1/topups ومن endpoints الفوترة في لوحة التحكم، لا من endpoints التفريغ. |
| 402 | topup_needs_user | فقط مع pending وin_progress | لم يخصم POST /v1/topups من البطاقة. يوضح reason السبب: not_allowed (بيانات الاعتماد غير مسموح لها بشراء الشحن، أو مستخدمها ليس مشرفا في الفريق)، أو cap_reached (لم يعد في الحد الشهري للوكلاء هامش)، أو card_declined أو authentication_required أو no_card. يمكن للمستخدم شراء الحزم عبر action_url. ومع pending (لم يتأكد الدفع بعد) وin_progress (عملية شحن أخرى جارية)، قد يكتمل الدفع لاحقا: أعد المحاولة لاحقا بقيمة Idempotency-Key نفسها بدلا من توجيه المستخدم إلى الشراء. |
| 404 | not_found | لا | لا يوجد تفريغ بهذا المعرف، أو أنه يتبع فريقا آخر. |
| 409 | upload_incomplete | لا | لم تصل بعض أجزاء الملف. أرسلها ثم أكد اكتمال الرفع من جديد. |
| 409 | invalid_state | لا | لم يعد التفريغ في حالة انتظار الرفع؛ لا يمكنك إرسال أجزاء أو تأكيد اكتمالها. |
| 409 | session_ended | لا | انتهت جلسة مباشرة، لذا لا يستطيع POST /v1/live/sessions/:id/token إصدار رمز مميز. يُرسل أيضا بوصفه حدث error في WebSocket. |
| 422 | unsupported_language | لا | قيمة language في جلسة مباشرة غير مدعومة. |
| 422 | unsupported_translation | لا | لغة translate_to في جلسة مباشرة غير مدعومة، أو الترجمة المباشرة غير متاحة. |
| 409 | idempotency_conflict | لا | استخدمت قيمة Idempotency-Key سابقا مع معاملات مختلفة. |
| 413 | media_too_large | لا | تجاوز الملف الحجم المسموح. راجع رفع الملفات. |
| 413 | invalid_request | لا | تجاوز body بصيغة JSON حد 1 MB. للملفات الكبيرة، يكون الرمز media_too_large بدلا منه. |
| 429 | rate_limited | نعم | تجاوزت عدد الطلبات المسموح في الدقيقة. انتظر عدد الثواني المحدد في Retry-After. |
| 429 | too_many_active_jobs | نعم | بلغت حد التفريغات الجارية أو عمليات الرفع المفتوحة. انتظر المدة المحددة في Retry-After. |
| 429 | too_many_live_sessions | نعم | استُخدمت جلسات باقتك المباشرة المتزامنة كلها. انتظر عدد الثواني (30) المحدد في Retry-After. |
| 500 | internal_error | نعم | واجهنا خطأ داخليا. انتظر قليلا وحاول مجددا. |
| 503 | service_unavailable | نعم | transcript1 غير متاح مؤقتا. حاول بعد قليل. |
| 503 | live_capacity | نعم | السعة المباشرة كلها مستخدمة. انتظر عدد الثواني (30) المحدد في Retry-After ثم أنشئ الجلسة من جديد. |
| 503 | live_unavailable | لا | التفريغ المباشر غير متاح الآن. |
إذا اعتمد طلب المتصفح على cookie تسجيل الدخول بدلا من Bearer، نتحقق أيضا من الموقع الذي أرسله. طلب موقع آخر يعيد 403 forbidden_origin. هذا الفحص لا يؤثر في استدعاءات API التي تستخدم ترويسة Authorization.
مع كل 429، تجد في Retry-After عدد الثواني التي يجب انتظارها. حدود كل باقة موضحة في الفوترة وحدود الاستخدام.
متى ترسل الطلب من جديد؟
- أعد الطلب نفسه فقط مع
retryable: true. ينطبق ذلك علىrate_limitedوtoo_many_active_jobsوtoo_many_live_sessionsوlive_capacityوinternal_errorوservice_unavailable، وعلىtopup_needs_userعندما تكون قيمةreasonهيpendingأوin_progress. انتظرRetry-Afterإن وجد، وإلا فزد مدة الانتظار بين المحاولات. - إذا كررت
POST /v1/transcriptionsأوPOST /v1/topups، احتفظ بقيمةIdempotency-Keyنفسها. إذا نجح الطلب الأول، فلن تدفع مرتين. - لبقية الرموز، عالج سبب الخطأ قبل إرسال الطلب مجددا.
التفريغ المباشر
يستخدم POST /v1/live/sessions ونقاط النهاية المباشرة الأخرى بنية الرد نفسها. وتنطبق عليها أيضا الرموز invalid_request وunsupported_language وinsufficient_minutes وemail_not_verified، إضافة إلى رموز التفريغ المباشر في الجدول أعلاه. إنشاء الجلسة ليس idempotent، لذا تنشئ إعادة المحاولة بعد too_many_live_sessions أو live_capacity جلسة جديدة.
بعد أن تقوم الجلسة، تصل المشكلات عبر WebSocket بوصفها أحداث error ورموز إغلاق، لا أخطاء HTTP. راجع التفريغ المباشر لكل الأحداث.
| رمز الإغلاق | المعنى |
|---|---|
1000 | إغلاق عادي، بعد session.ended. |
1011 | خطأ غير متوقع في الخادم. استأنف الجلسة برمز مميز جديد. |
1012 | إعادة تشغيل الخادم، بعد reconnect. استأنف الجلسة برمز مميز جديد. |
4001 | الرمز المميز غير صالح أو منتهي أو مستخدم من قبل. |
4004 | لم تُعثر على الجلسة أو انتهت بالفعل. |
4008 | مخالفة للبروتوكول: إطار صوت بطول فردي أو بحجم كبير أكثر من اللازم. |
4010 | حلّ محله اتصال أحدث بالجلسة نفسها. |
الجلسة المباشرة التي تنتهي لسبب مثل balance_exhausted أو idle_timeout ليست خطأ: فهي ترسل session.ended مع سبب الانتهاء وتُحفظ. راجع أسباب الانتهاء.
إذا فشل التفريغ بعد قبول الطلب
قد يصل رد قبول الطلب ثم يفشل التفريغ لاحقا. عند status=failed، يحتوي الكائن على error: { "code", "message" }. اقرأ error عند متابعة الحالة أو عند استقبال webhook من نوع transcription.failed. عند فشل الترجمة يُرسَل webhook من النوع transcription.translation.failed، ولا يفشل التفريغ بسببها.
error.code | ماذا حدث؟ | هل تفيد محاولة أخرى؟ |
|---|---|---|
media_unavailable | الفيديو غير موجود أو لم يعد متاحا. | لا؛ تحقق من الرابط. |
media_private | لا يمكن جلب الفيديو لأنه خاص. | لا؛ اختر منشورا عاما، أو فيديو YouTube عاما أو غير مدرج. |
login_required | لا تتيح المنصة مشاهدة الفيديو دون تسجيل الدخول. | لا؛ فشل دائم لا نعيد محاولته. |
no_audio | لا يحتوي الفيديو على مسار صوتي. | لا؛ فشل دائم لا نعيد محاولته. |
age_restricted | يفرض الفيديو قيودا عمرية. | لا؛ ارفع الملف بدلا من الرابط. |
live_stream | البث ما زال مباشرا، أو لم يبدأ بعد. | انتظر انتهاء البث. |
no_captions | اخترت source=captions، ولم نجد مسار ترجمة نصية مناسبا. | اختر source: "auto" أو "stt". |
media_too_long | تجاوز التسجيل حد تحويل الصوت إلى نص، وهو 5 ساعات. | لا؛ قسم التسجيل إلى ملفات أقصر. |
unsupported_media | تعذر قراءة الملف أو لم نجد فيه مسارا صوتيا. | لا؛ أرسل ملفا مدعوما. |
no_speech | لم يُرصد أي كلام. | لا. |
unsupported_language | لغة التسجيل غير مدعومة. | لا؛ اضبط language على رمز مدعوم أو "auto". |
insufficient_minutes | نفدت الدقائق قبل خصم تكلفة التفريغ، ولم يتمكن الشحن التلقائي، إن كان مفعلا، من إضافة دقائق. | اشحن دقائق إضافية أولا. |
fetch_failed | تعذر جلب التسجيل رغم تكرار المحاولة. | نعم، جرب لاحقا. |
transcription_failed | تعذر تحويل الصوت إلى نص رغم تكرار المحاولة. | نعم، جرب لاحقا. |
إذا فشل التفريغ أو ألغيته، لا تدفع شيئا. نعيد إلى رصيدك أي دقائق خصمناها له.
تاريخ التحديث 5 نوفمبر 2026