الرابط الأساسي https://api.echonova.ai

المطورون

أحداث Webhook

الأحداث الأربعة التي ترسلها إيكونوڤا، و headers في كل تسليم، والجسم JSON الدقيق لكل حدث.

تسرد هذه الصفحة كل حدث يستطيع Webhook أن يشترك فيه، والطلب الذي تستقبله نقطة النهاية لكل حدث. استخدمها لكتابة المعالج، واستخدم التحقق من توقيع Webhook للتأكد من أن الطلب صادر عن إيكونوڤا قبل أن تتصرف بناءً عليه.

أنواع الأحداث

الحدث تسمية البوابة يُرسل عندما
job.completed اكتمل الطلب تنتهي مهمة تحويل نص إلى كلام أو تحويل كلام إلى نص غير متزامنة بدأت بمفتاح API، ولها نتيجة.
job.failed فشل الطلب تفشل مهمة من النوع نفسه. تُرد الأرصدة التي حجزتها المهمة قبل إرسال الحدث.
spending.warning تنبيه الرصيد يصل استدعاء محسوب يأخذ مفتاح API له حد الرصيد إلى 80% من هذا الحد أو أكثر. يُرسل مرة واحدة في كل دورة فوترة.
spending.exhausted نفد الرصيد يترك استدعاء محسوب مفتاح API له حد الرصيد عند هذا الحد أو فوقه. يُرسل مع كل استدعاء من هذا النوع.

لا تُنتج الاستدعاءات المتزامنة أبدًا job.completed أو job.failed. ولا تُعلَن المهام التي بدأت من البوابة. تُنتج أحداث الرصيد الاستدعاءات المتزامنة وغير المتزامنة معًا، ولمفاتيح لها حد الرصيد فقط.

الطلب

كل تسليم هو طلب POST واحد إلى رابط نقطة النهاية لديك، مع هذه headers:

Header القيمة
Content-Type application/json
X-Webhook-Event اسم الحدث، مثل job.completed.
X-Webhook-Timestamp وقت Unix بالثواني عند توقيع هذه المحاولة، كسلسلة عشرية.
X-Webhook-Signature HMAC-SHA256 للقيمة <timestamp>.<body> بمفتاح سر التوقيع لديك، كـ 64 حرفًا سداسيًا عشريًا بأحرف صغيرة.

الجسم هو حمولة الحدث وحدها، دون غلاف. لا يوجد حقل id ولا type ولا createdAt داخل JSON. يحمل اسم الحدث header X-Webhook-Event فقط، لذلك اقرأه قبل أن تحلل الجسم.

تُرسل إعادة المحاولة الجسم نفسه مع طابع زمني وتوقيع جديدين. راجع التسليم وإعادة المحاولة والفشل.

job.completed

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

الحقل النوع الظهور المعنى
jobId string دائمًا المعرّف الذي أعادته POST التي بدأت المهمة.
apiKeyId string دائمًا معرّف مفتاح API الذي بدأ المهمة.
service string دائمًا tts أو stt.
durationSeconds number or null دائمًا مدة الصوت. null عندما لم تُقَس.
text string tts فقط النص الذي جرى تحويله إلى كلام، يُعاد لك حتى تطابق الاستدعاء مع طلبك.
audioUrl string tts فقط رابط موقّت وموقّع إلى الصوت. نزّله عند وصول الحدث، ولا تخزن الرابط.
transcription string stt فقط النص المفرّغ.

يحمل حدث تحويل الكلام إلى نص الحقل transcription وحده. لا يحمل الحدث segments ولا speakers لمهمة أُنشئت مع identify_speakers=true: اقرأهما من GET /v1/speech-to-text/jobs/{jobId}، أو نزّل المهمة كترجمة أو JSON من GET /v1/speech-to-text/jobs/{jobId}/export.

مثال تحويل النص إلى كلام:

{
  "jobId": "66e6b2f1c9a4d3e8f0a1b2c3",
  "apiKeyId": "66e6b1a0c9a4d3e8f0a1b2b9",
  "service": "tts",
  "durationSeconds": 3.42,
  "text": "مرحبا بكم في إيكونوڤا",
  "audioUrl": "https://storage.example.com/tts/tts-1a2b3c.wav?X-Amz-Signature=..."
}

مثال تحويل كلام إلى نص:

{
  "jobId": "66e6b3d4c9a4d3e8f0a1b2c7",
  "apiKeyId": "66e6b1a0c9a4d3e8f0a1b2b9",
  "service": "stt",
  "durationSeconds": 12.8,
  "transcription": "مرحبا بكم في إيكونوڤا"
}

job.failed

يُرسل بعد أن تُعلَّم المهمة فاشلة وتُرد أرصدتها.

الحقل النوع الظهور المعنى
jobId string دائمًا المعرّف الذي أعادته POST التي بدأت المهمة.
apiKeyId string دائمًا معرّف مفتاح API الذي بدأ المهمة.
service string دائمًا tts أو stt.
error string or null دائمًا سبب فشل المهمة. عند عدم توفر سبب، تكون القيمة AI server generation failed لـ tts، أو AI server transcription failed لـ stt.
{
  "jobId": "66e6b2f1c9a4d3e8f0a1b2c3",
  "apiKeyId": "66e6b1a0c9a4d3e8f0a1b2b9",
  "service": "tts",
  "error": "AI server generation failed"
}

spending.warning

يُرسل مرة واحدة في كل دورة فوترة، عند أول مرة يصل فيها استخدام مفتاح API إلى 80% من حد الرصيد الخاص به. يُرسل مرة أخرى في الدورة التالية بعد أن يُصفَّر استخدام المفتاح، وهذا يحدث عند أول استدعاء محسوب للمفتاح في تلك الدورة. راجع الرصيد.

الحقل النوع المعنى
apiKeyId string معرّف مفتاح API.
apiKeyName string القيمة نفسها كـ apiKeyId. لا ينتقل اسم المفتاح المعروض داخل الحدث؛ اربط معالجتك بـ apiKeyId.
creditsUsed number عدد صحيح من الأرصدة. الأرصدة المسجلة على المفتاح في دورة الفوترة هذه عند بداية هذا الطلب، بما فيها الاستدعاء الذي أطلق الحدث.
creditLimit number حد الرصيد الخاص بالمفتاح، بالأرصدة.
percentageUsed number creditsUsed / creditLimit * 100، مقرّبًا إلى أقرب عدد صحيح.
{
  "apiKeyId": "66e6b1a0c9a4d3e8f0a1b2b9",
  "apiKeyName": "66e6b1a0c9a4d3e8f0a1b2b9",
  "creditsUsed": 820,
  "creditLimit": 1000,
  "percentageUsed": 82
}

spending.exhausted

يُرسل في كل مرة يترك فيها استدعاء محسوب المفتاح عند حد الرصيد أو فوقه. يُرفض أي استدعاء سيتجاوز الحد بالرمز 429 والرسالة Monthly spending limit exhausted قبل أن يعمل، لذلك يأتي هذا الحدث بعد الاستدعاء الذي يصل إلى الحد بالضبط.

الحقل النوع المعنى
apiKeyId string معرّف مفتاح API.
apiKeyName string القيمة نفسها كـ apiKeyId. لا ينتقل اسم المفتاح المعروض داخل الحدث؛ اربط معالجتك بـ apiKeyId.
creditsUsed number عدد صحيح من الأرصدة. الأرصدة المسجلة على المفتاح في دورة الفوترة هذه عند بداية هذا الطلب، بما فيها الاستدعاء الذي أطلق الحدث.
creditLimit number حد الرصيد الخاص بالمفتاح، بالأرصدة.
{
  "apiKeyId": "66e6b1a0c9a4d3e8f0a1b2b9",
  "apiKeyName": "66e6b1a0c9a4d3e8f0a1b2b9",
  "creditsUsed": 1001,
  "creditLimit": 1000
}

الأسئلة الشائعة

كيف أعرف إلى أي Webhook أو تسليم ينتمي طلب معيّن؟

لا يحمل الجسم معرّف تسليم ولا معرّف Webhook. عرّف حدث المهمة بالحقل jobId مع X-Webhook-Event، وحدث الرصيد بالحقل apiKeyId مع اسم الحدث. إزالة التكرار موضحة في التسليم وإعادة المحاولة والفشل.

كيف أعرض اسم المفتاح من حدث الرصيد؟

يحمل apiKeyName معرّف المفتاح. تعرّف على apiKeyId لكل مفتاح من الحقل apiKeyId في حدث job.completed أو job.failed لمهمة بدأتها بذلك المفتاح، ثم احتفظ بخريطة خاصة بك من المعرّف إلى النظام الذي يحتفظ بالمفتاح.

هل تغيّر إعادة المحاولة الجسم؟

لا. تُرسل إعادة المحاولة الجسم نفسه مع X-Webhook-Timestamp جديد وX-Webhook-Signature جديد.

هل تُرسل الاستدعاءات المتزامنة أحداث المهام؟

لا. يُرسل job.completed وjob.failed للمهام غير المتزامنة التي بدأت بمفتاح API. أحداث الرصيد تُرسل لنوعي الاستدعاء معًا.

هل audioUrl في الحدث دائم؟

لا. هو رابط موقّت وموقّع. نزّل الملف عند وصول الحدث؛ تعيد GET /v1/text-to-speech/jobs/{jobId} رابطًا جديدًا إذا انتهت صلاحيته.