التوثيقمرجع REST API

مرجع REST API

راجع endpoints في /v1 ومعاملاتها وأمثلة استخدامها، أو نزل مواصفات OpenAPI بصيغة JSON أو YAML.

مقدمة

العنوان الأساسي (Base URL)
https://api.transcript1.com/v1

استخدم https://api.transcript1.com/v1 عنوانا أساسيا لاستدعاءات API.

  • أرسل body بصيغة JSON، واقرأ الرد بالصيغة نفسها. أسماء الحقول تستخدم snake_case.
  • الطوابع الزمنية بتوقيت UTC وصيغة ISO 8601، مثل 2026-10-13T09:30:00.000Z.
  • المدة والطوابع الزمنية داخل النص المفرغ تقاس بالثواني.
  • لردود الخطأ بنية موحدة؛ راجع التعامل مع الأخطاء.
  • تتضمن كل استجابة لطلب تمت مصادقته X-RateLimit-Limit وX-RateLimit-Remaining. تجد شرح الحدود في الفوترة وحدود الاستخدام.
  • عند source=auto، نبحث أولا عن ترجمة نصية مناسبة بلغة الفيديو الأصلية على YouTube وX وTikTok وBluesky وDailymotion وLinkedIn. إن لم تتوفر، نستخدم تحويل الصوت إلى نص؛ فليست لكل فيديو ترجمة نصية. وضع source=captions لا ينزل الصوت ولا ينتقل إلى STT، ويعيد no_captions إذا لم يجد مسارا مناسبا. ولتجاوز الترجمة النصية مباشرة، اختر source=stt أو فعل تمييز المتحدثين. راجع المصادر والخيارات لقيود جلب المسارات وتوقيت المقاطع وتوقيت كل كلمة.

يمكنك تنزيل مواصفات OpenAPI لاستخدامها برمجيا:

المصادقة

curl https://api.transcript1.com/v1/account \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"

أضف بيانات المصادقة إلى ترويسة Authorization بالصيغة Authorization: Bearer <token>.

  • مفتاح API بادئته t1_. أنشئه في صفحة «API keys»، واستخدمه مع أي endpoint.
  • OAuth access token بادئته t1o_. يحصل عليه عميل MCP، مثل Claude أو ChatGPT، أثناء الربط. صلاحياته هي transcriptions:read وtranscriptions:write.
الصلاحيةالاستدعاءات المتاحة
transcriptions:readGET /v1/transcriptions وGET /v1/transcriptions/:id وGET /v1/transcriptions/:id/upload وGET /v1/account
transcriptions:writePOST /v1/transcriptions وDELETE /v1/transcriptions/:id وPOST /v1/transcriptions/:id/upload/complete
  • إذا لم يملك token الصلاحية اللازمة، تحصل على 403 insufficient_scope.
  • إذا غابت بيانات المصادقة أو لم تكن صالحة، تحصل على 401 unauthorized.

عند إرسال أجزاء الملف إلى PUT /v1/transcriptions/:id/upload/chunks/:index، استخدم X-Upload-Token للمصادقة. يعيده API عند إنشاء عملية الرفع. راجع رفع الملفات.

إعادة الطلب دون تكرار التفريغ

curl -X POST https://api.transcript1.com/v1/transcriptions \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -H "Idempotency-Key: 5f1c2b0e-8d4a-4c3e-9b7a-2e6f1d0c9a8b" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'

أضف Idempotency-Key إلى ترويسات POST /v1/transcriptions حتى لا تنشئ تفريغا آخر إذا كررت الطلب.

اختر قيمة بطول 1 إلى 255 حرفا. مكانها في header، لا في query.

  • احتفظ بالمفتاح والمعاملات نفسها عند التكرار؛ يعيد API التفريغ الأصلي ولا يخصم دقائق مرة أخرى.
  • إذا غيرت المعاملات مع إبقاء المفتاح نفسه، تحصل على 409 idempotency_conflict.
  • عند الرفع على أجزاء، تكرار طلب الإنشاء بالمفتاح نفسه يمنحك token رفع جديدا.

الأخطاء

402 Payment Required
{
  "error": {
    "code": "insufficient_minutes",
    "message": "Not enough minutes",
    "retryable": false,
    "action_url": "https://transcript1.com/dashboard/billing",
    "minutes_needed": 20,
    "minutes_remaining": 3
  }
}
  • رفض الطلب يعني أن API لم يقبل الاستدعاء.
  • فشل التفريغ يحدث بعد قبول الطلب وبدء المعالجة؛ تنتهي المهمة بحالة failed في حقل status.

بنية رد الخطأ

عند رفض طلب على /v1، يعيد API كائن error بالحقول code وmessage وretryable.

  • اعتمد على code في منطق معالجة الخطأ.
  • اعرض message للمستخدم، لكن لا تعتمد على ثبات نصها.
  • إذا كانت retryable تساوي true، فقد ينجح الطلب نفسه بعد الانتظار.

قد تصلك حقول إضافية بجانب retryable لتوضح سبب المشكلة أو كيفية معالجتها:

الحقلرمز الخطأ المرتبط بهما الذي يوضحه؟
action_urlinsufficient_minutesرابط شراء باقة أو شحن دقائق إضافية.
minutes_needed، minutes_remaininginsufficient_minutesالدقائق المطلوبة والدقائق المتبقية في رصيدك. تكون المطلوبة null إذا لم نعرف المدة بعد.
supported_platformsunsupported_platformقيم المنصات المقبولة وهي ["youtube", "x", "tiktok", "instagram", "facebook", "bluesky", "twitch", "dailymotion", "pinterest", "linkedin", "snapchat"].
missing_chunksupload_incompleteأرقام الأجزاء التي لم تصل أثناء الرفع.
max_bytesmedia_too_largeحد حجم الملف المسموح لحسابك بالبايت.
paramsinvalid_requestكائن يحدد الحقول غير الصالحة وسبب الخطأ في كل منها، عند فحص body أو query.

لماذا لم يقبل API الطلب؟

رمز HTTPcodeهل تعيد المحاولة؟السبب أو الإجراء المطلوب
400، 422invalid_requestلاحقل أو معامل ناقص أو غير صالح، أو JSON غير صالح في body. من أمثلته الجمع بين diarize وsource: "captions"، أو بين reuse_recent وwebhook_url.
422invalid_urlلاأرسل رابطا من YouTube أو X أو TikTok أو Instagram أو Facebook أو Bluesky، أو إحدى المنصات في المصادر والخيارات. تأكد أيضا أن platform يطابق الرابط.
422unsupported_platformلاأرسلت قيمة غير مدعومة في platform.
422unsupported_mediaلاامتداد الملف الذي رفعته غير مدعوم.
401unauthorizedلابيانات المصادقة غائبة أو غير صالحة أو انتهت صلاحيتها أو ألغيت. وقد يكون token الرفع غير صالح أو منتهي الصلاحية.
403insufficient_scopeلالا يملك OAuth token صلاحية transcriptions:read أو transcriptions:write المطلوبة.
403email_not_verifiedلاأكد بريدك الإلكتروني أولا لتتمكن من إنشاء تفريغ.
402insufficient_minutesلارصيدك القابل للاستخدام 0، أو لا يكفي لمدة التسجيل.
402no_active_planلاحاولت شحن دقائق إضافية دون باقة مدفوعة نشطة. هذا الخطأ من endpoint الفوترة في لوحة التحكم، لا من endpoints التفريغ.
404not_foundلالا يوجد تفريغ بهذا المعرف، أو أنه يتبع فريقا آخر.
409upload_incompleteلالم تصل بعض أجزاء الملف. أرسلها ثم أكد اكتمال الرفع من جديد.
409invalid_stateلالم يعد التفريغ في حالة انتظار الرفع؛ لا يمكنك إرسال أجزاء أو تأكيد اكتمالها.
409idempotency_conflictلااستخدمت قيمة Idempotency-Key سابقا مع معاملات مختلفة.
413media_too_largeلاتجاوز الملف الحجم المسموح. راجع رفع الملفات.
413invalid_requestلاتجاوز body بصيغة JSON حد 1 MB. للملفات الكبيرة، يكون الرمز media_too_large بدلا منه.
429rate_limitedنعمتجاوزت عدد الطلبات المسموح في الدقيقة. انتظر عدد الثواني المحدد في Retry-After.
429too_many_active_jobsنعمبلغت حد التفريغات الجارية أو عمليات الرفع المفتوحة. انتظر المدة المحددة في Retry-After.
500internal_errorنعمواجهنا خطأ داخليا. انتظر قليلا وحاول مجددا.
503service_unavailableنعمtranscript1 غير متاح مؤقتا. حاول بعد قليل.

إذا اعتمد طلب المتصفح على cookie تسجيل الدخول، نتحقق أيضا من الموقع الذي أرسله. طلب موقع آخر يعيد 403 forbidden_origin.

هذا الفحص لا يؤثر في استدعاءات API التي تستخدم ترويسة Authorization.

تجد مع كل رد 429 ترويسة Retry-After بعدد الثواني التي يجب انتظارها. راجع الفوترة وحدود الاستخدام لمعرفة حد باقتك.

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

  • أعد الطلب نفسه فقط مع retryable: true، أي مع rate_limited أو too_many_active_jobs أو internal_error أو service_unavailable.
  • انتظر المدة المحددة في Retry-After إن وجدت. وفي غير ذلك، زد مدة الانتظار بين المحاولات.
  • عند تكرار POST /v1/transcriptions، استخدم قيمة Idempotency-Key نفسها. إذا نجح الطلب الأول، فلن تدفع مرة أخرى.
  • لبقية الرموز، عالج سبب الخطأ قبل إرسال الطلب مجددا.

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

عند وصول status إلى failed، يحتوي كائن التفريغ على error بحقلين هما code وmessage.

قد يصل رد قبول الطلب قبل حدوث الفشل. لذلك افحص error عند متابعة الحالة أو عند استقبال webhook من نوع transcription.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تعذر تحويل الصوت إلى نص رغم تكرار المحاولة.نعم، جرب لاحقا.

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

الكائن Transcription

الكائن Transcription
{
  "id": "tr_4fHq8ZbN2xLm0PqRsTuVwX",
  "object": "transcription",
  "status": "completed",
  "source": {
    "platform": "youtube",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "media_id": "dQw4w9WgXcQ"
  },
  "media": {
    "title": "Example video",
    "author": "Example channel",
    "author_url": "https://www.youtube.com/@examplechannel",
    "thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
    "duration_seconds": 212
  },
  "options": {
    "source": "auto",
    "language": "auto",
    "diarize": false
  },
  "transcript_source": "youtube_captions",
  "caption_kind": "auto_generated",
  "language": "en",
  "billed_minutes": 4,
  "cached": false,
  "error": null,
  "created_at": "2026-10-13T09:30:00.000Z",
  "completed_at": "2026-10-13T09:30:04.000Z",
  "deleted_at": null,
  "transcript": {
    "text": "Welcome back to the channel. Today we are looking at how transcripts are made.",
    "speakers": [],
    "segments": [
      {
        "start": 0,
        "end": 4.2,
        "speaker": null,
        "language": "en",
        "text": "Welcome back to the channel."
      },
      {
        "start": 4.2,
        "end": 9.8,
        "speaker": null,
        "language": "en",
        "text": "Today we are looking at how transcripts are made."
      }
    ]
  }
}

الحقول

  • idstringمطلوب
  • objectstringمطلوب

    القيم المسموح بهاtranscription

  • statusstringمطلوب

    القيم المسموح بهاawaiting_uploadqueuedfetchingtranscribingcompletedfailedcanceled

  • sourceobjectمطلوب
    عرض الحقول الفرعية
    With url
    • platformstringمطلوب
    • urlstringمطلوبيقبل null
    • media_idstringمطلوبيقبل null
    With filename
    • platformstringمطلوب

      القيم المسموح بهاupload

    • filenamestringمطلوبيقبل null
    • sizenumberمطلوبيقبل null
  • mediaobjectمطلوبيقبل null
    عرض الحقول الفرعية
    • titlestringاختيارييقبل null
    • authorstringاختيارييقبل null
    • author_urlstringاختيارييقبل null
    • thumbnail_urlstringاختيارييقبل null
    • filenamestringاختياري
    • mime_typestringاختياري
    • sizenumberاختياري
    • duration_secondsnumberاختيارييقبل null
  • optionsobjectمطلوب
    عرض الحقول الفرعية
    • sourcestringمطلوب

      القيم المسموح بهاautocaptionsstt

    • languagestringمطلوب
    • diarizebooleanمطلوب
  • transcript_sourcestringمطلوبيقبل null

    القيم المسموح بهاyoutube_captionsx_captionsspeech_to_text

  • caption_kindstringمطلوبيقبل null

    القيم المسموح بهاmanualauto_generated

  • languagestringمطلوبيقبل null
  • billed_minutesintegerمطلوبيقبل null
  • cachedbooleanمطلوب
  • errorobjectمطلوبيقبل null
    عرض الحقول الفرعية
    • codestringمطلوب
    • messagestringمطلوبيقبل null
  • created_atstring · date-timeمطلوبيقبل null
  • completed_atstring · date-timeمطلوبيقبل null
  • deleted_atstring · date-timeمطلوبيقبل null

    When the transcription was deleted. Always null unless the request includes include_deleted=true.

  • transcriptobjectاختياري

    Included in GET responses for completed transcriptions.

    عرض الحقول الفرعية
    • textstringمطلوب
    • speakersarray of stringsمطلوب
    • segmentsarray of objectsمطلوب
      عرض الحقول الفرعية
      • startnumberمطلوب
      • endnumberمطلوب
      • speakerstringمطلوبيقبل null
      • languagestringمطلوبيقبل null
      • textstringمطلوب
      • wordsarray of objectsاختيارييقبل null
        عرض الحقول الفرعية
        • startnumberمطلوب
        • endnumberمطلوب
        • textstringمطلوب
        • confidencenumberاختيارييقبل null
        • speakerstringمطلوبيقبل null

Transcriptions

Create, read, list and delete transcriptions of video links and uploaded files.

Create a transcription

POST /v1/transcriptions

Transcribes an uploaded file or a YouTube, X, TikTok, Instagram, Facebook, Bluesky, Twitch, Dailymotion, Pinterest, LinkedIn, Snapchat link. Social posts must be public; only the first video is used.

Twitch accepts clips and completed VODs; Pinterest accepts native video pins; LinkedIn accepts public video posts; Snapchat accepts Spotlight. New platforms require public recorded native media without supplied account cookies; no live streams or external embeds.

platform is optional and detected from the link. Captions are YouTube/X-only. All sources use the same per-minute price.

Returns 200 for a final result, 201 when awaiting an upload and 202 while processing. Pass wait to wait up to 60 seconds for a final status.

Pass reuse_recent=true with a platform URL to reuse a transcription of the same video and options from the last 24 hours. The response includes reused: true, with no additional charge. Short links may not be matched. An Idempotency-Key replay takes precedence.

curl -X POST https://api.transcript1.com/v1/transcriptions \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'
{
  "id": "tr_4fHq8ZbN2xLm0PqRsTuVwX",
  "object": "transcription",
  "status": "queued",
  "source": {
    "platform": "youtube",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "media_id": "dQw4w9WgXcQ"
  },
  "media": null,
  "options": {
    "source": "auto",
    "language": "auto",
    "diarize": false
  },
  "transcript_source": null,
  "caption_kind": null,
  "language": null,
  "billed_minutes": null,
  "cached": false,
  "error": null,
  "created_at": "2026-10-13T09:30:00.000Z",
  "completed_at": null,
  "deleted_at": null,
  "reused": false
}

Query

  • waitintegerاختيارييقبل nullالقيمة الافتراضية: 0

    Seconds to wait for a final status before responding, up to 60. Defaults to 0.

  • reuse_recentstringاختياريالقيمة الافتراضية: false

    For platform URLs only. Cannot be combined with webhook_url. Returns the team's most recent transcription of the same video with the same source, language and diarize. It must have been created in the last 24 hours and must not be failed or canceled. Reuses that transcription without creating or charging for a new one.

    القيم المسموح بهاtruefalse

Headers

  • Idempotency-Keystringاختياري

    Returns the original transcription when you repeat a request with the same key and parameters.

Body

With url
  • platformstringاختياري

    Optional; detected from the link. If supplied, must match the link.

    القيم المسموح بهاyoutubextiktokinstagramfacebookblueskytwitchdailymotionpinterestlinkedinsnapchat

  • urlstringمطلوب

    YouTube, X, TikTok, Instagram, Facebook, Bluesky, Twitch, Dailymotion, Pinterest, LinkedIn, Snapchat video link. Social posts must be public; only the first video is used. New platforms support public recorded native video without supplied account cookies, not live streams or external embeds.

  • sourcestringاختياري

    "auto" uses YouTube or X captions when available, otherwise speech-to-text. "captions" is YouTube/X-only. "stt" always uses speech-to-text.

    القيم المسموح بهاautocaptionsstt

  • languagestringاختياري
  • diarizebooleanاختياري
  • webhook_urlstring · uriاختياري
With upload
  • uploadobjectمطلوب
    عرض الحقول الفرعية
    • filenamestringمطلوب
    • sizeintegerمطلوب
    • mime_typestringاختياري
  • sourcestringاختياري

    القيم المسموح بهاautostt

  • languagestringاختياري
  • diarizebooleanاختياري
  • webhook_urlstring · uriاختياري
multipart/form-data
  • filestring · binaryمطلوب
  • sourcestringاختياري

    القيم المسموح بهاautostt

  • languagestringاختياري
  • diarizebooleanاختياري
  • webhook_urlstring · uriاختياري

الاستجابة

  • 200 OK — The transcription reached a final status
  • 201 Created — The transcription is awaiting a chunked upload. upload describes where to send each chunk.
  • 202 Accepted — The transcription is processing

حالات HTTP أخرى

  • 400 Bad Request — The JSON request body is malformed
  • 401 Unauthorized — Missing or invalid credential
  • 402 Payment Required — Not enough minutes. Applies to every request body format.
  • 403 Forbidden — Insufficient scope, unverified email, cross-site request or a single-member team plan
  • 409 Conflict — Idempotency-Key was reused with different parameters.
  • 413 Content Too Large — The upload or the JSON request body is too large
  • 422 Unprocessable Content — Invalid request, URL, platform or file type
  • 429 Too Many Requests — Too many requests or too many active transcriptions. Wait for the number of seconds in Retry-After.

Get a transcription

GET /v1/transcriptions/{id}

Returns the transcription object. Completed transcriptions include the transcript. Use format to render it as text, SRT or WebVTT.

If you request a rendered format before completion, the response is JSON. It returns 202 while processing or 200 if the transcription failed or was canceled.

With include_deleted=true, a deleted transcription is returned as a record without a transcript. For deleted records, wait is ignored and rendered formats return 404.

curl https://api.transcript1.com/v1/transcriptions/tr_4fHq8ZbN2xLm0PqRsTuVwX \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
{
  "id": "tr_4fHq8ZbN2xLm0PqRsTuVwX",
  "object": "transcription",
  "status": "completed",
  "source": {
    "platform": "youtube",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "media_id": "dQw4w9WgXcQ"
  },
  "media": {
    "title": "Example video",
    "author": "Example channel",
    "author_url": "https://www.youtube.com/@examplechannel",
    "thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
    "duration_seconds": 212
  },
  "options": {
    "source": "auto",
    "language": "auto",
    "diarize": false
  },
  "transcript_source": "youtube_captions",
  "caption_kind": "auto_generated",
  "language": "en",
  "billed_minutes": 4,
  "cached": false,
  "error": null,
  "created_at": "2026-10-13T09:30:00.000Z",
  "completed_at": "2026-10-13T09:30:04.000Z",
  "deleted_at": null,
  "transcript": {
    "text": "Welcome back to the channel. Today we are looking at how transcripts are made.",
    "speakers": [],
    "segments": [
      {
        "start": 0,
        "end": 4.2,
        "speaker": null,
        "language": "en",
        "text": "Welcome back to the channel."
      },
      {
        "start": 4.2,
        "end": 9.8,
        "speaker": null,
        "language": "en",
        "text": "Today we are looking at how transcripts are made."
      }
    ]
  }
}

Path

  • idstringمطلوب

Query

  • waitintegerاختيارييقبل nullالقيمة الافتراضية: 0

    Seconds to wait for a final status before responding, up to 60. Defaults to 0.

  • formatstringاختياريالقيمة الافتراضية: json

    القيم المسموح بهاjsontextsrtvtt

  • includestringاختياري

    القيم المسموح بهاwords

  • timestampsstringاختياريالقيمة الافتراضية: false

    القيم المسموح بهاtruefalse

  • include_deletedstringاختياريالقيمة الافتراضية: false

    Also returns deleted transcriptions as read-only records without a transcript. Their deleted_at is set. Defaults to false.

    القيم المسموح بهاtruefalse

الاستجابة

  • 200 OK — The transcription, or the rendered transcript
  • 202 Accepted — A rendered format was requested while the transcription is still processing

حالات HTTP أخرى

  • 401 Unauthorized — Missing or invalid credential
  • 403 Forbidden — Insufficient scope or a single-member team plan
  • 404 Not Found — Transcription not found
  • 422 Unprocessable Content — Invalid query parameters
  • 429 Too Many Requests — Too many requests. Wait for the number of seconds in Retry-After.

List transcriptions

GET /v1/transcriptions

Lists your team's transcriptions, newest first, without transcripts. Pass next_cursor as cursor to get the next page.

Deleted transcriptions are hidden unless you pass include_deleted=true.

curl https://api.transcript1.com/v1/transcriptions \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
{
  "object": "list",
  "data": [
    {
      "id": "tr_4fHq8ZbN2xLm0PqRsTuVwX",
      "object": "transcription",
      "status": "completed",
      "source": {
        "platform": "youtube",
        "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "media_id": "dQw4w9WgXcQ"
      },
      "media": {
        "title": "Example video",
        "author": "Example channel",
        "author_url": "https://www.youtube.com/@examplechannel",
        "thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
        "duration_seconds": 212
      },
      "options": {
        "source": "auto",
        "language": "auto",
        "diarize": false
      },
      "transcript_source": "youtube_captions",
      "caption_kind": "auto_generated",
      "language": "en",
      "billed_minutes": 4,
      "cached": false,
      "error": null,
      "created_at": "2026-10-13T09:30:00.000Z",
      "completed_at": "2026-10-13T09:30:04.000Z",
      "deleted_at": null
    }
  ],
  "next_cursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTEwLTEzVDA5OjMwOjAwLjAwMFoiLCJpZCI6IjViMGU2YzFjLTBkNmYtNGMxZi05YjVlLThmM2Y0ZDBhN2ExMSJ9"
}

Query

  • limitintegerاختياريالقيمة الافتراضية: 20
  • cursorstringاختياري
  • statusstringاختياري

    القيم المسموح بهاawaiting_uploadqueuedfetchingtranscribingcompletedfailedcanceled

  • platformstringاختياري
  • include_deletedstringاختياريالقيمة الافتراضية: false

    Also returns deleted transcriptions as read-only records without a transcript. Their deleted_at is set. Defaults to false.

    القيم المسموح بهاtruefalse

الاستجابة

  • 200 OK — A page of transcriptions

حالات HTTP أخرى

  • 401 Unauthorized — Missing or invalid credential
  • 403 Forbidden — Insufficient scope or a single-member team plan
  • 422 Unprocessable Content — Invalid query parameters or cursor
  • 429 Too Many Requests — Too many requests. Wait for the number of seconds in Retry-After.

Cancel or delete a transcription

DELETE /v1/transcriptions/{id}

Cancels an active transcription or one awaiting an upload. Any charged minutes are refunded.

Deletes a completed, failed or canceled transcription together with its stored transcript.

curl -X DELETE https://api.transcript1.com/v1/transcriptions/tr_4fHq8ZbN2xLm0PqRsTuVwX \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"

الاستجابة بلا محتوى

Path

  • idstringمطلوب

الاستجابة

  • 204 No Content — Canceled or deleted

حالات HTTP أخرى

  • 401 Unauthorized — Missing or invalid credential
  • 403 Forbidden — Insufficient scope, cross-site request or a single-member team plan
  • 404 Not Found — Transcription not found
  • 429 Too Many Requests — Too many requests. Wait for the number of seconds in Retry-After.

Uploads

Send a large file in chunks. Start with Create a transcription using an upload body. Send each chunk, then complete the upload.

Upload one chunk

PUT /v1/transcriptions/{id}/upload/chunks/{index}

Sends one chunk of a chunked upload as application/octet-stream.

Authenticate with the X-Upload-Token from the create response. This endpoint does not use a bearer credential.

The body must match the planned chunk size exactly. Sending a chunk again replaces it.

curl -X PUT https://api.transcript1.com/v1/transcriptions/tr_4fHq8ZbN2xLm0PqRsTuVwX/upload/chunks/0 \
  -H "X-Upload-Token: t1u_Zk3vYb8Nw1ZrT5xLpD0aHcE7sUj9GfMiO2yXtVnR4Bw" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @chunk-0.bin
{
  "object": "upload_chunk",
  "index": 0,
  "size": 838860
}

Path

  • idstringمطلوب
  • indexintegerاختيارييقبل null

    Zero-based chunk number from the upload plan

Headers

  • X-Upload-Tokenstringمطلوب

Body

  • (المحتوى الخام)string · binaryمطلوب

الاستجابة

  • 200 OK — The chunk was stored

حالات HTTP أخرى

  • 401 Unauthorized — Missing, invalid or expired upload token
  • 404 Not Found — Transcription not found
  • 409 Conflict — The transcription is no longer awaiting an upload
  • 422 Unprocessable Content — Index outside the chunk plan or wrong body size

Get upload progress

GET /v1/transcriptions/{id}/upload

Lists the received chunks of a chunked upload so an interrupted upload can resume.

curl https://api.transcript1.com/v1/transcriptions/tr_4fHq8ZbN2xLm0PqRsTuVwX/upload \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
{
  "object": "upload",
  "status": "awaiting_upload",
  "total_bytes": 48210334,
  "uploaded_bytes": 4194300,
  "received_chunks": [
    0,
    1,
    2,
    3,
    4
  ],
  "chunks": [
    {
      "index": 0,
      "offset": 0,
      "size": 838860
    },
    {
      "index": 1,
      "offset": 838860,
      "size": 838860
    },
    {
      "index": 2,
      "offset": 1677720,
      "size": 838860
    },
    {
      "index": 3,
      "offset": 2516580,
      "size": 838860
    },
    {
      "index": 4,
      "offset": 3355440,
      "size": 838860
    },
    {
      "index": 5,
      "offset": 4194300,
      "size": 8388608
    },
    {
      "index": 6,
      "offset": 12582908,
      "size": 8388608
    },
    {
      "index": 7,
      "offset": 20971516,
      "size": 8388608
    },
    {
      "index": 8,
      "offset": 29360124,
      "size": 8388608
    },
    {
      "index": 9,
      "offset": 37748732,
      "size": 8388608
    },
    {
      "index": 10,
      "offset": 46137340,
      "size": 2072994
    }
  ],
  "expires_at": "2026-10-13T10:30:00.000Z"
}

Path

  • idstringمطلوب

الاستجابة

  • 200 OK — Upload progress

حالات HTTP أخرى

  • 401 Unauthorized — Missing or invalid credential
  • 403 Forbidden — Insufficient scope or a single-member team plan
  • 404 Not Found — Transcription or upload not found
  • 429 Too Many Requests — Too many requests. Wait for the number of seconds in Retry-After.

Complete a chunked upload

POST /v1/transcriptions/{id}/upload/complete

Checks that every planned chunk arrived with the planned size. Then assembles the file and queues the transcription.

curl -X POST https://api.transcript1.com/v1/transcriptions/tr_4fHq8ZbN2xLm0PqRsTuVwX/upload/complete \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
{
  "id": "tr_4fHq8ZbN2xLm0PqRsTuVwX",
  "object": "transcription",
  "status": "queued",
  "source": {
    "platform": "upload",
    "filename": "interview.m4a",
    "size": 48210334
  },
  "media": {
    "filename": "interview.m4a",
    "mime_type": "audio/mp4",
    "size": 48210334
  },
  "options": {
    "source": "auto",
    "language": "auto",
    "diarize": false
  },
  "transcript_source": null,
  "caption_kind": null,
  "language": null,
  "billed_minutes": null,
  "cached": false,
  "error": null,
  "created_at": "2026-10-13T09:30:00.000Z",
  "completed_at": null,
  "deleted_at": null
}

Path

  • idstringمطلوب

الاستجابة

  • 202 Accepted — The transcription is queued

حالات HTTP أخرى

  • 401 Unauthorized — Missing or invalid credential
  • 402 Payment Required — Not enough minutes to queue the transcription. The upload stays awaiting completion.
  • 403 Forbidden — Insufficient scope, cross-site request or a single-member team plan
  • 404 Not Found — Transcription or upload not found
  • 409 Conflict — upload_incomplete means chunks are missing. missing_chunks lists them. invalid_state means the transcription is not awaiting an upload.
  • 429 Too Many Requests — Too many requests or too many active transcriptions. Wait for the number of seconds in Retry-After.

Account

Your plan, remaining minutes and rate limits.

Get your account

GET /v1/account

Returns the authenticated user, current plan and remaining transcription minutes.

curl https://api.transcript1.com/v1/account \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
{
  "object": "account",
  "user": {
    "id": "5b0e6c1c-0d6f-4c1f-9b5e-8f3f4d0a7a11",
    "email": "[email protected]"
  },
  "plan": {
    "id": "9d4e0c0a-2b8a-4f0c-8d63-6a8d3c8a1f22",
    "name": "Monthly"
  },
  "minutes": {
    "remaining": 1180,
    "cycle": 980,
    "topup": 200,
    "topup_usable": true,
    "resets_at": "2026-11-13T09:30:00.000Z"
  },
  "renews_at": "2026-11-13T09:30:00.000Z",
  "limits": {
    "requests_per_minute": 200,
    "max_active_jobs": 10
  }
}

الاستجابة

  • 200 OK — The authenticated user's account

حالات HTTP أخرى

  • 401 Unauthorized — Missing or invalid credential
  • 403 Forbidden — Insufficient scope or a single-member team plan
  • 404 Not Found — No account found
  • 429 Too Many Requests — Too many requests. Wait for the number of seconds in Retry-After.

الكائن Account

الكائن Account
{
  "object": "account",
  "user": {
    "id": "5b0e6c1c-0d6f-4c1f-9b5e-8f3f4d0a7a11",
    "email": "[email protected]"
  },
  "plan": {
    "id": "9d4e0c0a-2b8a-4f0c-8d63-6a8d3c8a1f22",
    "name": "Monthly"
  },
  "minutes": {
    "remaining": 1180,
    "cycle": 980,
    "topup": 200,
    "topup_usable": true,
    "resets_at": "2026-11-13T09:30:00.000Z"
  },
  "renews_at": "2026-11-13T09:30:00.000Z",
  "limits": {
    "requests_per_minute": 200,
    "max_active_jobs": 10
  }
}

الحقول

  • objectstringمطلوب

    القيم المسموح بهاaccount

  • userobjectمطلوب
    عرض الحقول الفرعية
    • idstringمطلوب
    • emailstringمطلوب
  • planobjectمطلوبيقبل null
    عرض الحقول الفرعية
    • idstringمطلوب
    • namestringمطلوب
  • minutesobjectمطلوب
    عرض الحقول الفرعية
    • remainingnumberمطلوب
    • cyclenumberمطلوب
    • topupnumberمطلوب
    • topup_usablebooleanمطلوب
    • resets_atstring · date-timeمطلوبيقبل null
  • renews_atstring · date-timeمطلوبيقبل null
  • limitsobjectمطلوب
    عرض الحقول الفرعية
    • requests_per_minutenumberمطلوب
    • max_active_jobsnumberمطلوب

إشعارات webhook

import { Buffer } from 'node:buffer';
import crypto from 'node:crypto';

// header: X-Transcript1-Signature, rawBody: the request body exactly as received,
// secret: your full signing secret including the whsec_ prefix.
export const verifySignature = (secret, header, rawBody, nowSeconds = Math.floor(Date.now() / 1000)) => {
  const fields = Object.fromEntries(header.split(',').map(part => part.trim().split('=')));
  const t = Number(fields.t);

  if (!Number.isInteger(t) || !fields.v1 || Math.abs(nowSeconds - t) > 300) {
    return false;
  }

  const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');

  return fields.v1.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(fields.v1), Buffer.from(expected));
};
transcription.completed
{
  "type": "transcription.completed",
  "created_at": "2026-10-13T09:30:04.000Z",
  "data": {
    "id": "tr_8fK2Lm0PqRsTuVwXyZaBcD",
    "object": "transcription",
    "status": "completed",
    "transcript_source": "youtube_captions",
    "billed_minutes": 4,
    "error": null
  }
}

أضف webhook_url عند إنشاء التفريغ ليصلك إشعار بانتهائه. يرسل transcript1 طلب POST يحمل توقيعا إلى الرابط إذا اكتمل التفريغ أو فشل.

استخدم REST API لهذه الميزة؛ لا تقبل أدوات خادم MCP معامل webhook.

أضف رابط استقبال الإشعارات

مكان webhook_url في طلب POST /v1/transcriptions يعتمد على طريقة إرسال التسجيل:

  • عند إرسال رابط فيديو مدعوم أو حجز رفع على أجزاء، ضعه في body بصيغة JSON.
  • عند رفع الملف بطلب واحد، ضعه في حقل من حقول النموذج.

تحقق من شروط الرابط:

  • يستخدم HTTPS.
  • لا يتضمن اسم مستخدم أو كلمة مرور.
  • يشير إلى عنوان IP عام.

لا نقبل عناوين الشبكات الخاصة أو loopback أو link-local أو غيرها من العناوين غير العامة؛ تحصل معها على 422 invalid_request. نفحص العنوان عند إنشاء التفريغ وقبل كل محاولة إرسال.

لا ترسل webhook_url مع reuse_recent=true؛ لا يمكن استخدامهما معا.

متى يصلك الإشعار؟

typeسبب الإرسال
transcription.completedاكتمل التفريغ وأصبحت حالته completed.
transcription.failedفشل التفريغ وأصبحت حالته failed. تجد code وmessage في data.error.

إذا ألغيت التفريغ، لا نرسل webhook.

محتوى الإشعار

يحتوي body بصيغة JSON على بيانات الحدث:

  • يبين created_at وقت إنشاء الحدث.
  • يحتوي data على كائن التفريغ دون حقل transcript.

لجلب النص المفرغ، خذ id من data واستخدمه مع GET /v1/transcriptions/:id.

نرسل مع الطلب الترويسات التالية:

  • Content-Type: application/json
  • User-Agent: transcript1-webhooks/1.0
  • X-Transcript1-Signature للتحقق من التوقيع كما يلي.

تحقق من التوقيع قبل قراءة JSON

تصل ترويسة X-Transcript1-Signature مع كل إشعار بالصيغة t=<unix seconds>,v1=<hex digest>.

  • t وقت توقيع الطلب، بصيغة Unix وبالثواني.
  • v1 توقيع HMAC-SHA256 بترميز hex للسلسلة "<t>.<raw body>". احسبه من قيمة t ثم نقطة ثم body كما وصل تماما. المفتاح هو سر التوقيع كاملا، بما فيه البادئة whsec_.

تحقق من بايتات الطلب الأصلية قبل تحويل JSON إلى كائن. إعادة تحويل الكائن إلى JSON قد تغير المسافات أو ترتيب المفاتيح، وعندها لن يطابق التوقيع.

  • استخدم مقارنة للتوقيع بزمن ثابت.
  • ارفض الطلب إذا ابتعدت t عن الوقت الحالي أكثر من المهلة المقبولة. تسمح الأمثلة بفارق 5 دقائق.
  • في Express، اقرأ body كنص كما وصل، دون تحليل JSON مسبقا.
  • في Flask، استخدم request.get_data(as_text=True) للحصول على raw_body.

أين تجد سر التوقيع؟

لفريقك سر توقيع واحد بادئته whsec_، ويستخدم لجميع إشعارات التفريغ التي ينشئها الفريق.

لعرضه أو استبداله، افتح صفحة «Webhooks».

يصبح السر الجديد ساريا فور استبداله. كل الإشعارات التي نرسلها بعد ذلك تستخدمه.

الاستقبال وإعادة المحاولة

  • أعد أي رمز 2xx لتأكيد وصول الإشعار.
  • نعتبر المحاولة فاشلة عند وصول رمز آخر، أو حدوث خطأ اتصال، أو عدم الرد خلال 10 ثوان.
  • نكرر الإرسال بعد الفشل حتى 6 محاولات إجمالا. تتضاعف فترات الانتظار إلى 2 ثم 4 ثم 8 ثم 16 ثم 32 دقيقة. تأتي المحاولة الأخيرة بعد نحو ساعة من الأولى.
  • أرسل الرابط النهائي مباشرة. لا يتبع transcript1 إعادة التوجيه، ويعامل 3xx كمحاولة فاشلة.
  • قد يصلك الإشعار نفسه مجددا إذا أجاب خادمك بعد المهلة. استخدم data.id وtype لاكتشاف التكرار وتجاهله.