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} رابطًا جديدًا إذا انتهت صلاحيته.