API Structural Diff
Une API REST qui compare une transcription générée par IA avec la version post-éditée par l'annotateur — détectant les changements structurels au niveau des lignes (divisions, fusions, modifications, ajouts, suppressions), avec détail des différences par colonne, scores CER/WER/SegER/SER/SACR et une note de qualité composite par lot.
Démarrage rapide
Aucun SDK nécessaire. Envoyez une requête POST avec vos deux tableaux de lignes de transcription et recevez un diff complet en JSON. L'API est en phase de dégustation — demandez une clé API pour commencer.
1. Vérifiez que le service est actif :
curl https://structural-diff-engine.onrender.com/v1/health2. Lancez une comparaison :
curl -X POST https://structural-diff-engine.onrender.com/v1/diff \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"original": [
{ "speaker": "Alice", "start_time": 0, "end_time": 1, "transcript": "Hello world" },
{ "speaker": "Bob", "start_time": 1, "end_time": 3, "transcript": "Good morning everyone" }
],
"reworked": [
{ "speaker": "Alice", "start_time": 0, "end_time": 1, "transcript": "Hello there" },
{ "speaker": "Bob", "start_time": 1, "end_time": 2, "transcript": "Good morning" },
{ "speaker": "Bob", "start_time": 2, "end_time": 3, "transcript": "everyone" }
]
}'URL de base
Tous les points de terminaison sont préfixés par /v1.
https://structural-diff-engine.onrender.comAuthentification
Incluez votre clé API dans l'en-tête de requête x-api-key à chaque appel vers /v1/diff.
curl -H "x-api-key: YOUR_API_KEY" -H "Content-Type: application/json" \
-X POST https://structural-diff-engine.onrender.com/v1/diff -d '{...}'Limites de débit
Deux niveaux indépendants sont appliqués par clé API, avec repli sur l'IP en l'absence de clé. Dépasser l'un ou l'autre renvoie 429 Too Many Requests.
| Niveau | Limite | En-tête de réponse |
|---|---|---|
| Rafale | 10 requêtes / minute | RateLimit-Limit |
| Fenêtre | 60 requêtes / 15 minutes | RateLimit-Remaining |
Points de terminaison
GET /v1/health
Sonde de disponibilité légère. Aucune authentification requise. Renvoie la version du service et le temps de fonctionnement.
/v1/health· Sans auth{ "status": "ok", "version": "1.0.0", "uptime": 42, "timestamp": "..." }POST /v1/diff
Comparez deux tableaux de lignes de transcription. Renvoie des résultats au niveau des lignes avec des scores de qualité. Charge utile max : 5 Mo · Lignes max : 30 000.
/v1/diff Auth requiseCorps de la requête
| Name | Type | Description |
|---|---|---|
original* | array | Objets de ligne de la version de référence / originale. |
reworked* | array | Objets de ligne à comparer. |
config | object | Surcharges optionnelles de l'algorithme. Voir . |
headers | string[] | Noms de colonnes — requis lors de l'utilisation d'un tableau 2D. |
columnMapping | object | Carte d'index de colonnes pour l'entrée en tableau 2D. Voir . |
Champs de l'objet ligne
Tous les champs sont optionnels sauf transcript. Les champs inconnus sont transmis sans modification.
| Name | Type | Description |
|---|---|---|
transcript* | string | Le contenu textuel de la ligne. |
speaker | string | Nom ou identifiant du locuteur. |
start_time | number|string | Heure de début du segment en secondes. |
end_time | number|string | Heure de fin du segment en secondes. |
non_speech_events | string | Annotations telles que [musique], [rires]. |
emotion | string | Étiquette d'émotion. |
language | string | Code de langue (ex. "fr", "ar"). |
locale | string | Code de locale (ex. "fr-FR"). |
accent | string | Étiquette d'accent. |
file_name | string | Nom du fichier source. Champ de passage uniquement — non utilisé par l'algorithme de diff. |
Structure de la réponse
Toutes les réponses réussies utilisent cette enveloppe :
{
"status": "success",
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-04-08T21:00:00.000Z",
"data": {
"results": [
{
"status": "MODIFIED",
"originalRow": { "transcript": "Hello world", ... },
"reworkedRow": { "transcript": "Hello there", ... },
"notes": "transcript changed"
},
{
"status": "SPLIT",
"originalRow": { "transcript": "Good morning everyone", ... },
"reworkedRows": [ { "transcript": "Good morning" }, { "transcript": "everyone" } ],
"notes": "split into 2 rows"
}
],
"scores": { "overallCER": 0.12, "overallWER": 0.18, "SegER": 0.33, "transcriptCER": 0.12, "transcriptWER": 0.18, "SER": 0.05, "transcriptSER": 0.04, "SACR": null },
"composite": { "grade": 3.8, "label": "Good", "percent": "12.3" },
"meta": { "originalRows": 2, "reworkedRows": 3, "headers": [...] }
}
}Statuts de diff
| Statut | Signification |
|---|---|
| UNCHANGED | La ligne est identique dans les deux versions. |
| MODIFIED | La ligne existe dans les deux versions mais le contenu a changé. |
| ADDED | La ligne est uniquement présente dans la version révisée. |
| DELETED | La ligne est uniquement présente dans la version originale. |
| SPLIT | Une ligne originale a été divisée en deux lignes révisées ou plus. |
| MERGED | Deux lignes originales ou plus ont été combinées en une ligne révisée. |
Scores
| Name | Type | Description |
|---|---|---|
overallCER | number | Taux d'erreur de caractères dans toutes les colonnes (0–1, plus bas = meilleur). |
overallWER | number | Taux d'erreur de mots dans toutes les colonnes (0–1). |
SegER | number | Taux d'erreur de segmentation — événements de frontière (divisions, fusions, lignes ajoutées et supprimées) / segments attendus (0–1, inférieur = meilleur). |
transcriptCER | number | CER calculé uniquement sur la colonne de transcription. |
transcriptWER | number | WER calculé uniquement sur la colonne de transcription. |
SER | number | Taux d'erreur de phrase — lignes MODIFIED / (UNCHANGED + MODIFIED). Fraction des lignes comparables avec au moins une modification (0–1). |
transcriptSER | number | SER calculé sur les phrases du texte dans la colonne de transcription. |
SACR | number | Taux de changement d'attribution du locuteur — lignes où le locuteur a changé / lignes MODIFIED. null si aucune colonne de locuteur n'est détectée. |
Note composite
| Name | Type | Description |
|---|---|---|
grade | number | Score numérique (1,0–5,0, plus élevé = meilleur) calculé en moyenne sur les métriques activées. |
label | string | Étiquette lisible — parmi : "Excellent", "Good", "Acceptable", "Below Average", "Poor", "Unacceptable". |
percent | string | Pourcentage d'erreur moyen sur les métriques de notation activées. |
enabledMetrics | string[] | Tableau des noms de métriques ayant contribué à ce composite (ex. : ["CER", "Transcript CER", "WER", "Transcript WER", "SegER", "SER", "Transcript SER"]). Vide si toutes les métriques sont désactivées. |
Méta de la réponse
| Name | Type | Description |
|---|---|---|
originalRows | number | Nombre de lignes dans le tableau original. |
reworkedRows | number | Nombre de lignes dans le tableau reworked. |
headers | string[] | Noms des colonnes utilisés pour ce diff. |
Options de configuration
Passez un objet config dans le corps de la requête pour remplacer les valeurs par défaut de l'algorithme. Tous les champs sont optionnels.
| Name | Type | Default | Description |
|---|---|---|---|
simpleMode | boolean | false | Désactiver la détection des divisions et fusions. Diff ligne par ligne pur. |
enableSplits | boolean | true | Activer la détection des lignes divisées. |
enableMerges | boolean | true | Activer la détection des lignes fusionnées. |
enableCER | boolean | true | Calculer le taux d'erreur de caractères. |
enableWER | boolean | true | Calculer le taux d'erreur de mots. |
enableSegER | boolean | true | Calculer le taux d'erreur de segmentation (divisions, fusions, événements de frontière). |
enableSER | boolean | true | Calculer le taux d'erreur de phrases. |
stripDiacritics | boolean | true | Normaliser les caractères arabes/accentués avant la comparaison. |
positionalMode | boolean | false | Comparer les lignes strictement par position, sans alignement. |
ignoreColNames | string[] | [] | Noms de colonnes exclus de la détection MODIFIED. |
enableInlineDiff | boolean | true | Inclure transcriptDiff dans les lignes MODIFIED. Mettre false pour ignorer le diff caractère par caractère et réduire la taille de réponse. |
structuralTransforms | TransformRule[] | [] | Règles find/replace appliquées aux deux côtés avant la comparaison par similarité (max 20 règles). |
enableTranscriptCER | boolean | true | Calculer le CER restreint à la colonne transcript uniquement. Indépendant de enableCER. |
enableTranscriptWER | boolean | true | Calculer le WER restreint à la colonne transcript uniquement. Indépendant de enableWER. |
enableTranscriptSER | boolean | true | SER au niveau des phrases dans la colonne transcript — compte les phrases modifiées dans les lignes MODIFIED, SPLIT et MERGED. |
enableSACR | boolean | true | Calculer le taux de changement d'attribution du locuteur (lignes MODIFIED avec locuteur changé / total MODIFIED). Détection auto de la colonne locuteur ; renvoie null si absente. |
speakerColName | string | auto-detect | Remplacer la détection automatique de la colonne locuteur. Correspondance insensible à la casse (ex. "spk_id"). |
enableComposite | boolean | true | Calculer la note composite de qualité (moyenne 1–5 des métriques activées). |
cerInComposite | boolean | true | Inclure overallCER dans la note composite. Le CER est toujours calculé quand false. |
werInComposite | boolean | true | Inclure overallWER dans la note composite. Le WER est toujours calculé quand false. |
segerInComposite | boolean | true | Inclure SegER dans la note composite. SegER est toujours calculé quand false. |
serInComposite | boolean | true | Inclure SER dans la note composite. SER est toujours calculé quand false. |
Mappage des colonnes
Lorsque original / reworked sont des tableaux 2D (tableaux de tableaux) plutôt que des objets, fournissez headers et/ou columnMapping pour indiquer au moteur quel index correspond à chaque champ.
{
"original": [[0, 1, "Alice", "Hello world"]],
"headers": ["start_time", "end_time", "speaker", "transcript"],
"columnMapping": { "transcript": 3, "speaker": 2, "start_time": 0, "end_time": 1 }
}| Name | Type | Description |
|---|---|---|
transcript* | integer | Index de colonne base 0 pour le champ de transcription. |
speaker | integer | Index de colonne base 0 pour le champ du locuteur. |
start_time | integer | Index de colonne base 0 pour l'heure de début. |
end_time | integer | Index de colonne base 0 pour l'heure de fin. |
nse | integer | Index de colonne base 0 pour les événements non-vocaux. |
extraCols | integer[] | Index de colonnes supplémentaires à inclure (max 20). |
Référence des erreurs
Toutes les erreurs utilisent une enveloppe uniforme :
{
"status": "error",
"requestId": "550e8400-...",
"timestamp": "2026-04-08T21:00:00.000Z",
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [{ "field": "original", "message": "\"original\" is required" }]
}
}| HTTP | Code | Cause |
|---|---|---|
| 400 | BAD_REQUEST | Corps JSON malformé |
| 401 | UNAUTHORIZED | En-tête x-api-key manquant ou invalide |
| 404 | NOT_FOUND | Point de terminaison inconnu |
| 413 | PAYLOAD_TOO_LARGE | Corps de requête dépasse 5 Mo |
| 422 | VALIDATION_ERROR | Échec de la validation du schéma (voir tableau details) |
| 429 | RATE_LIMIT_EXCEEDED | Limite de débit par rafale ou par fenêtre atteinte |
| 500 | INTERNAL_SERVER_ERROR | Erreur serveur ou moteur inattendue |
Traçage des requêtes
Fournissez un en-tête x-request-id pour corréler les requêtes dans votre système. Caractères alphanumériques, tirets et traits de soulignement uniquement, max 64 caractères. La valeur est renvoyée dans les en-têtes de réponse.
curl -H "x-request-id: job-2026-01-batch-3" \
-H "x-api-key: YOUR_KEY" \
-X POST https://structural-diff-engine.onrender.com/v1/diff -d '{...}'Obtenir un accès API
L'API est disponible pour les agences et équipes en phase de dégustation. Les clés sont provisionnées individuellement. Contactez-nous pour recevoir votre clé et commencer l'intégration.