# التعامل مع الأخطاء

> افهم ردود الخطأ ورموزها، واعرف متى تعيد المحاولة ومتى تحتاج إلى تعديل الطلب.

Canonical: https://transcript1.com/ar/docs/errors
Language: ar
Last updated: 2026-11-05

ميز بين رفض الطلب وفشل التفريغ. في الحالة الأولى، لم يقبل API الطلب. وفي الثانية، قبله وبدأت المعالجة، لكنها انتهت لاحقا بحالة `failed` في حقل `status`.

## بنية رد الخطأ

تأتي أخطاء الطلبات على `/v1` بهذه البنية:

```json
{
  "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، أو إحدى المنصات في [المصادر والخيارات](https://transcript1.com/ar/docs/sources-and-options). تأكد أيضا أن `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، أو لا يكفي لمدة التسجيل، أو أقل من دقيقة واحدة بدأت في جلسة مباشرة. إذا كان [الشحن التلقائي](https://transcript1.com/ar/docs/billing-and-limits#auto-top-up) مفعلا، يحاول 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` | لا | تجاوز الملف الحجم المسموح. راجع [رفع الملفات](https://transcript1.com/ar/docs/uploads). |
| 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` عدد الثواني التي يجب انتظارها. حدود كل باقة موضحة في [الفوترة وحدود الاستخدام](https://transcript1.com/ar/docs/billing-and-limits).

## متى ترسل الطلب من جديد؟

- أعد الطلب نفسه فقط مع `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. راجع [التفريغ المباشر](https://transcript1.com/ar/docs/live#websocket-protocol) لكل الأحداث.

| رمز الإغلاق | المعنى |
|---|---|
| `1000` | إغلاق عادي، بعد `session.ended`. |
| `1011` | خطأ غير متوقع في الخادم. استأنف الجلسة برمز مميز جديد. |
| `1012` | إعادة تشغيل الخادم، بعد `reconnect`. استأنف الجلسة برمز مميز جديد. |
| `4001` | الرمز المميز غير صالح أو منتهي أو مستخدم من قبل. |
| `4004` | لم تُعثر على الجلسة أو انتهت بالفعل. |
| `4008` | مخالفة للبروتوكول: إطار صوت بطول فردي أو بحجم كبير أكثر من اللازم. |
| `4010` | حلّ محله اتصال أحدث بالجلسة نفسها. |

الجلسة المباشرة التي تنتهي لسبب مثل `balance_exhausted` أو `idle_timeout` ليست خطأ: فهي ترسل `session.ended` مع سبب الانتهاء وتُحفظ. راجع [أسباب الانتهاء](https://transcript1.com/ar/docs/live#end-reasons).

## إذا فشل التفريغ بعد قبول الطلب

قد يصل رد قبول الطلب ثم يفشل التفريغ لاحقا. عند `status=failed`، يحتوي الكائن على `error: { "code", "message" }`. اقرأ `error` عند متابعة الحالة أو عند استقبال [webhook](https://transcript1.com/ar/docs/webhooks) من نوع `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` | تعذر تحويل الصوت إلى نص رغم تكرار المحاولة. | نعم، جرب لاحقا. |

إذا فشل التفريغ أو ألغيته، لا تدفع شيئا. نعيد إلى رصيدك أي دقائق خصمناها له.
