التوثيقمرجع REST API
مرجع REST API
راجع endpoints في /v1 ومعاملاتها وأمثلة استخدامها، أو نزل مواصفات OpenAPI بصيغة JSON أو YAML.
مقدمة
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:read | GET /v1/transcriptions وGET /v1/transcriptions/:id وGET /v1/transcriptions/:id/upload وGET /v1/account |
transcriptions:write | POST /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 رفع جديدا.
الأخطاء
{
"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_url | insufficient_minutes | رابط شراء باقة أو شحن دقائق إضافية. |
minutes_needed، minutes_remaining | insufficient_minutes | الدقائق المطلوبة والدقائق المتبقية في رصيدك. تكون المطلوبة null إذا لم نعرف المدة بعد. |
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، أو لا يكفي لمدة التسجيل. |
| 402 | no_active_plan | لا | حاولت شحن دقائق إضافية دون باقة مدفوعة نشطة. هذا الخطأ من endpoint الفوترة في لوحة التحكم، لا من endpoints التفريغ. |
| 404 | not_found | لا | لا يوجد تفريغ بهذا المعرف، أو أنه يتبع فريقا آخر. |
| 409 | upload_incomplete | لا | لم تصل بعض أجزاء الملف. أرسلها ثم أكد اكتمال الرفع من جديد. |
| 409 | invalid_state | لا | لم يعد التفريغ في حالة انتظار الرفع؛ لا يمكنك إرسال أجزاء أو تأكيد اكتمالها. |
| 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. |
| 500 | internal_error | نعم | واجهنا خطأ داخليا. انتظر قليلا وحاول مجددا. |
| 503 | service_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
{
"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
nullunless the request includesinclude_deleted=true. - transcriptobjectاختياري
Included in
GETresponses 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/transcriptionsTranscribes 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 samesource,languageanddiarize. It must have been created in the last 24 hours and must not befailedorcanceled. 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 status201 Created— The transcription is awaiting a chunked upload.uploaddescribes where to send each chunk.202 Accepted— The transcription is processing
حالات HTTP أخرى
400 Bad Request— The JSON request body is malformed401 Unauthorized— Missing or invalid credential402 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 plan409 Conflict—Idempotency-Keywas reused with different parameters.413 Content Too Large— The upload or the JSON request body is too large422 Unprocessable Content— Invalid request, URL, platform or file type429 Too Many Requests— Too many requests or too many active transcriptions. Wait for the number of seconds inRetry-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_atis set. Defaults tofalse.القيم المسموح بها
truefalse
الاستجابة
200 OK— The transcription, or the rendered transcript202 Accepted— A rendered format was requested while the transcription is still processing
حالات HTTP أخرى
401 Unauthorized— Missing or invalid credential403 Forbidden— Insufficient scope or a single-member team plan404 Not Found— Transcription not found422 Unprocessable Content— Invalid query parameters429 Too Many Requests— Too many requests. Wait for the number of seconds inRetry-After.
List transcriptions
GET /v1/transcriptionsLists 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_atis set. Defaults tofalse.القيم المسموح بها
truefalse
الاستجابة
200 OK— A page of transcriptions
حالات HTTP أخرى
401 Unauthorized— Missing or invalid credential403 Forbidden— Insufficient scope or a single-member team plan422 Unprocessable Content— Invalid query parameters or cursor429 Too Many Requests— Too many requests. Wait for the number of seconds inRetry-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 credential403 Forbidden— Insufficient scope, cross-site request or a single-member team plan404 Not Found— Transcription not found429 Too Many Requests— Too many requests. Wait for the number of seconds inRetry-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 token404 Not Found— Transcription not found409 Conflict— The transcription is no longer awaiting an upload422 Unprocessable Content— Index outside the chunk plan or wrong body size
Get upload progress
GET /v1/transcriptions/{id}/uploadLists 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 credential403 Forbidden— Insufficient scope or a single-member team plan404 Not Found— Transcription or upload not found429 Too Many Requests— Too many requests. Wait for the number of seconds inRetry-After.
Complete a chunked upload
POST /v1/transcriptions/{id}/upload/completeChecks 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 credential402 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 plan404 Not Found— Transcription or upload not found409 Conflict—upload_incompletemeans chunks are missing.missing_chunkslists them.invalid_statemeans 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 inRetry-After.
Account
Your plan, remaining minutes and rate limits.
Get your account
GET /v1/accountReturns 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 credential403 Forbidden— Insufficient scope or a single-member team plan404 Not Found— No account found429 Too Many Requests— Too many requests. Wait for the number of seconds inRetry-After.
الكائن 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));
};{
"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/jsonUser-Agent: transcript1-webhooks/1.0X-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لاكتشاف التكرار وتجاهله.