Webhooks et callbacks
Recevez des notifications en temps réel sur l’état de vos transcriptions.
Configuration
Exemple de base
{
"type": "configure",
"config": {
"webhook_url": "https://votre-serveur.com/webhook",
"webhook_events": [
"transcription.completed",
"transcription.failed",
"session.ended"
]
}
}Événements disponibles
| Événement | Description | Payload |
|---|---|---|
transcription.completed | Transcription finale disponible | {session_id, transcription, metadata} |
transcription.failed | Erreur de transcription | {session_id, error, metadata} |
session.started | Session démarrée | {session_id, metadata} |
session.ended | Session terminée | {session_id, duration, metadata} |
transcription.partial | Transcription partielle (optionnel) | {session_id, text, status} |
Sécurité
Signature HMAC
Tous les webhooks sont signés avec HMAC-SHA256 pour vérifier l’origine.
Header : X-Ephia-Signature
Vérification :
import hmac
import hashlib
def verify_signature(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)Exemple de gestion (Python/Flask)
from flask import Flask, request
import hmac
import hashlib
import os
app = Flask(__name__)
WEBHOOK_SECRET = os.environ.get('EPHIA_WEBHOOK_SECRET')
@app.route('/webhook', methods=['POST'])
def webhook():
# Vérifier la signature
signature = request.headers.get('X-Ephia-Signature')
payload = request.get_data()
expected_signature = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
if signature != expected_signature:
return 'Invalid signature', 401
# Traiter l'événement
event = request.json
if event['type'] == 'transcription.completed':
# Sauvegarder la transcription
save_transcription(event['data'])
elif event['type'] == 'transcription.failed':
# Logger l'erreur
log_error(event['data'])
return 'OK', 200Exemple de gestion (Node.js/Express)
const express = require('express');
const crypto = require('crypto');
const app = express();
const WEBHOOK_SECRET = process.env.EPHIA_WEBHOOK_SECRET;
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
// Vérifier la signature
const signature = req.headers['x-ephia-signature'];
const payload = req.body;
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== expectedSignature) {
return res.status(401).send('Invalid signature');
}
// Traiter l'événement
const event = JSON.parse(payload.toString());
if (event.type === 'transcription.completed') {
// Sauvegarder la transcription
saveTranscription(event.data);
}
res.status(200).send('OK');
});Retry et gestion d’erreurs
- Retry automatique : 3 tentatives avec backoff exponentiel
- Timeout : 30 secondes
- Format attendu : HTTP 200 avec réponse JSON valide
- Logs : Disponibles dans le dashboard
Bonnes pratiques
- ✅ Toujours vérifier la signature HMAC
- ✅ Implémenter un endpoint idempotent
- ✅ Logger tous les événements reçus
- ✅ Gérer les timeouts et erreurs réseau
- ✅ Tester avec des outils comme ngrok
- ✅ Utiliser HTTPS pour les webhooks
Test local avec ngrok
# Installer ngrok
npm install -g ngrok
# Démarrer votre serveur local
python app.py
# Dans un autre terminal, créer un tunnel
ngrok http 5000
# Utiliser l'URL ngrok dans la configuration
# https://abc123.ngrok.io/webhookFormat des payloads
transcription.completed
{
"type": "transcription.completed",
"session_id": "session_abc123",
"data": {
"transcription": "Scanner cérébral sans injection de produit de contraste.",
"duration": 45.2,
"metadata": {
"patient_id": "P12345",
"consultation_type": "radiologie"
}
},
"timestamp": "2024-12-19T15:30:00Z"
}transcription.failed
{
"type": "transcription.failed",
"session_id": "session_abc123",
"data": {
"error": {
"code": "AUDIO_QUALITY_ERROR",
"message": "Audio quality too low"
}
},
"timestamp": "2024-12-19T15:30:00Z"
}