Capturia mesure ses publicités et la fréquentation du site avec le pixel Meta et Google Analytics. Tu peux refuser en tout temps. En savoir plus

EN

Conversation imports

3 points d'accès

get/v1/conversation-imports

Lire l'état d'une conversation envoyée

L'état d'un envoi de POST /v1/conversation-imports : reçu sur sa fiche, en attente d'une fiche, refusé avec sa raison, ou reçu en double, et où en est l'analyse de sa rencontre (recording.analysis).

Un envoi d'un autre compte répond 404, comme un envoi inexistant. Un envoi refusé ou en double s'efface après 30 jours ; un envoi reçu part avec sa rencontre.

Scopes requis : conversations:import

Paramètres de requête

NomTypeObligatoireDescription
idstringobligatoireL'identifiant de l'envoi, rendu par POST /v1/conversation-imports (id). Absent ou mal formé, la requête répond 400 validation_error.

Réponses

StatutDescription
200

État de l'envoi.

400

Requête invalide. code distingue les refus que l'opération rend sous ce statut, et chaque exemple en montre un.

validation_errorid · required
{
  "error": {
    "type": "validation_error",
    "code": "validation_error",
    "message": "La validation de la requête a échoué.",
    "hint": "`details` nomme chaque champ à corriger et la raison du refus.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#validation_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": [
      {
        "field": "id",
        "reason": "required"
      }
    ]
  }
}
validation_errorid · invalid_uuid
{
  "error": {
    "type": "validation_error",
    "code": "validation_error",
    "message": "La validation de la requête a échoué.",
    "hint": "`details` nomme chaque champ à corriger et la raison du refus.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#validation_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": [
      {
        "field": "id",
        "reason": "invalid_uuid"
      }
    ]
  }
}
401

La clé API manque, est inconnue ou a expiré. code distingue les trois causes : missing_api_key (aucun en-tête Authorization: Bearer), invalid_api_key (clé inconnue, révoquée ou de format invalide) et expired_api_key (date d'expiration dépassée).

missing_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "missing_api_key",
    "message": "Aucune clé API n'a été fournie.",
    "hint": "Ajoute un header Authorization sous la forme : Bearer cap_live_<ta_clé>",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#missing_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "La clé API est invalide ou a été révoquée.",
    "hint": "Vérifie la clé dans ton dashboard ou génère-en une nouvelle.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#invalid_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
expired_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "expired_api_key",
    "message": "La clé API a expiré.",
    "hint": "Roule la clé depuis le dashboard pour en générer une nouvelle valide.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#expired_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
403

Refus d'autorisation. code distingue les refus que l'opération rend sous ce statut, et chaque exemple en montre un.

browser_not_allowed
{
  "error": {
    "type": "authorization_error",
    "code": "browser_not_allowed",
    "message": "Les clés API s'utilisent depuis un serveur, jamais depuis un navigateur.",
    "hint": "La requête porte un en-tête `Origin` : appelle l'API depuis ton serveur, où la clé reste secrète.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#browser_not_allowed",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
account_suspended
{
  "error": {
    "type": "authorization_error",
    "code": "account_suspended",
    "message": "L'accès à ce compte est suspendu par l'équipe Capturia.",
    "hint": "Le refus vient du compte, pas de la clé. Tant que la suspension dure, aucune requête n'est acceptée : contacte l'équipe Capturia.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#account_suspended",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
feature_not_available
{
  "error": {
    "type": "authorization_error",
    "code": "feature_not_available",
    "message": "Cette fonctionnalité n'est pas incluse dans ton forfait.",
    "hint": "Le refus vient du forfait du compte, pas de la clé. Contacte ton conseiller Capturia pour en parler.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#plan",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "feature": "public_api"
    }
  }
}
insufficient_scope
{
  "error": {
    "type": "authorization_error",
    "code": "insufficient_scope",
    "message": "Cette clé API ne contient pas le scope requis pour ce point d'accès.",
    "hint": "Cette clé n'a pas le scope `conversations:import`. Crée une nouvelle clé avec le preset « Lecture + écriture » ou ajoute le scope via le dashboard.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#scopes",
    "dashboard_url": "https://capturia.io/platform/dashboard/admin/integrations/api-keys/6f1e2d3c-4b5a-4c6d-8e7f-9a0b1c2d3e4f?tab=permissions",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "required_scope": "conversations:import",
      "required_permission": "call_review.manage",
      "current_scopes": [
        "leads:capture"
      ],
      "suggested_preset": "read_write"
    }
  }
}
404

resource_not_found : aucun envoi de ce compte ne porte cet identifiant.

resource_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "resource_not_found",
    "message": "La ressource demandée est introuvable.",
    "hint": "Vérifie l'ID de la ressource. Elle a peut-être été supprimée ou n'a jamais existé.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#resource_not_found",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
429

Limite de débit atteinte. rate_limit_exceeded : le quota horaire de la clé est épuisé. too_many_attempts : trop de clés invalides présentées depuis cette adresse IP (protection contre la force brute). Dans les deux cas, Retry-After donne le délai en secondes.

rate_limit_exceeded
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Limite de requêtes atteinte.",
    "hint": "Réessaie après le nombre de secondes indiqué dans retry_after_seconds, et envisage d'implémenter un backoff exponentiel.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/rate-limits",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "limit": 100,
      "count": 100,
      "limit_type": "per_key",
      "retry_after_seconds": 42
    }
  }
}
too_many_attempts
{
  "error": {
    "type": "rate_limit_error",
    "code": "too_many_attempts",
    "message": "Trop de tentatives d'authentification invalides depuis cette IP.",
    "hint": "Attends la période indiquée par retry_after_seconds avant de réessayer.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#brute-force",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "limit_type": "brute_force",
      "retry_after_seconds": 300
    }
  }
}
500

Erreur serveur inattendue. Toujours fournir le request_id au support.

internal_error
{
  "error": {
    "type": "server_error",
    "code": "internal_error",
    "message": "Erreur serveur. L'équipe Capturia a été notifiée.",
    "hint": "Si le problème persiste, contacte le support en incluant le request_id de cette réponse.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#internal_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
501

Les clés de test (cap_test_) ne sont pas encore servies : seules les clés cap_live_ sont acceptées.

not_implemented
{
  "error": {
    "type": "server_error",
    "code": "not_implemented",
    "message": "Cette fonctionnalité n'est pas encore implémentée.",
    "hint": "Consulte la documentation API pour les fonctionnalités disponibles et le changelog pour les prochaines versions.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#not_implemented",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
503

Un service dont la requête dépend n'a pas répondu (lecture de la clé, du compte ou du forfait). La même requête passera quand il reviendra : réessaie après le délai de Retry-After.

service_unavailable
{
  "error": {
    "type": "server_error",
    "code": "service_unavailable",
    "message": "Service temporairement indisponible.",
    "hint": "Réessaie après la période indiquée par Retry-After.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#service_unavailable",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}

Exemple de requête

curl -X GET 'https://api.capturia.io/v1/conversation-imports?id=4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b' \
  -H 'Authorization: Bearer cap_live_<your-key>' \
  -H 'Content-Type: application/json'
post/v1/conversation-imports

Envoyer une conversation tenue hors de Capturia

Une agence d'appels, un outil comme Zapier ou Make, ou ton propre système envoie une conversation tenue hors de Capturia : un appel, une rencontre en vidéo ou en personne. Capturia la range sur la fiche de la personne et l'analyse comme une rencontre enregistrée dans Capturia.

En texte

Envoie la transcription telle quelle dans transcript.text : Capturia la lit comme un texte collé dans l'application. Une ligne « Nom : texte » ouvre un tour de parole ; un fichier WebVTT ou SRT se lit aussi. Ou envoie les tours déjà découpés dans transcript.turns. speakers donne le rôle de chaque voix par son nom (agent, prospect ou other) ; sans lui, l'analyse déduit qui parle. La conversation part à l'analyse dès la réponse.

En audio, en trois temps

  1. Annonce le fichier dans media : son nom, son type et sa taille exacte en octets. La réponse rend un lien d'envoi dans upload, valable 2 h.
  2. Téléverse le fichier par PUT à upload.url, avec l'en-tête Content-Type du type annoncé.
  3. Appelle POST /v1/conversation-imports/complete avec l'id de l'envoi : Capturia vérifie le fichier, puis le fait transcrire et analyser.

Renvoyer la même annonce avant l'arrivée du fichier rend un nouveau lien d'envoi. Un audio dont le fichier n'est pas arrivé un jour après son annonce est retiré.

Avis d'enregistrement

recording_notice: "given" déclare que chaque personne de la conversation a été informée qu'elle est enregistrée et analysée par une intelligence artificielle ; sans cette déclaration, l'envoi est refusé (422 recording_notice_required). La direction du compte doit aussi avoir signé l'attestation des conversations envoyées par un fournisseur, dans Administration › Conversations importées (422 import_attestation_missing sinon).

Qui a tenu la conversation

Nomme-le dans held_by, dans seller, ou dans les deux. held_by : une personne hors du compte, par exemple l'agent d'une agence d'appels. Sa conversation reçoit son analyse, son compte rendu et son plan, jamais de note ni de coaching. seller : le membre du compte responsable de la conversation. Sans seller, la conversation revient au vendeur de la fiche, sinon au vendeur par défaut du compte.

La fiche

contact.id désigne la fiche ; sans lui, Capturia la cherche par external_id, puis phone, puis email. Une personne inconnue reçoit une fiche, créée sans aucun consentement de communication (contact_created: true). Avec create_if_missing: false, ou sans téléphone ni courriel, la conversation attend qu'un membre du compte la rattache à une fiche (status: awaiting_contact). Une fiche dont la personne a refusé d'être enregistrée ne reçoit aucune conversation (422 contact_refused_recording).

Doublons

Une conversation n'entre qu'une fois par compte. Un texte aux mêmes mots (noms des voix et horodatages mis à part), un audio annoncé à l'identique pour la même personne (même nom de fichier, même taille, même occurred_at), ou le même external_id sous le même external_source répond 200 already_received avec l'identifiant du premier envoi, sans créer de nouvelle rencontre. Un audio dit donc toujours laquelle des conversations il est : external_id, la reconnaissance la plus sûre, ou occurred_at (media_identity_required sans l'un ni l'autre). L'en-tête Idempotency-Key reste disponible pour les relances d'une transcription ; une annonce d'audio ne le lit pas, pour que sa relance rende toujours un lien d'envoi neuf.

Plafond et coût

Chaque compte reçoit un nombre limité de conversations par jour (UTC) : au-delà, 429 import_daily_limit_reached jusqu'au lendemain. L'audio a son propre plafond, 40 heures transcrites par jour (UTC) : il se juge à la transcription, une fois le fichier reçu. Un fichier doit tenir dans ce qui reste, d'après la durée mesurée des audios déjà transcrits ce jour-là et une estimation haute de la sienne, tirée de sa taille. Un audio qui ne tient pas est retiré ; GET /v1/conversation-imports?id= le montre alors refused avec audio_daily_limit_reached. L'analyse se débite des crédits du compte, comme celle d'une rencontre enregistrée dans Capturia.

Scopes requis : conversations:import

En-têtes

NomTypeObligatoireDescription
Idempotency-KeystringoptionnelClé d'idempotence : de 16 à 128 caractères [A-Za-z0-9_-] (un UUID v4 ou un ULID conviennent). Une clé d'une autre forme est refusée en 400 invalid_request (details.field : idempotency-key) ; un en-tête vide vaut une requête sans clé. Une 2e requête avec la même clé et la même charge utile renvoie la réponse d'origine, avec l'en-tête Idempotency-Replayed: true, sans refaire l'opération ; la même clé avec une autre charge utile est refusée en 409 idempotency_conflict. Stockée 24 h. Optionnelle mais recommandée.

Corps de requête

PropriétéTypeObligatoireDescription
transcriptConversationImportTranscriptoptionnelLa conversation en texte : text ou turns, jamais les deux (details[].reason : text_or_turns). Au moins 15 mots (422 transcript_too_short), au plus 500 000 caractères au total.
mediaConversationImportMediaoptionnelL'enregistrement audio annoncé. Son fichier se téléverse ensuite au lien rendu dans upload, puis POST /v1/conversation-imports/complete le fait transcrire et analyser.
contactConversationImportContactoptionnelLa personne avec qui la conversation a eu lieu. id désigne sa fiche (inconnu : 404 contact_not_found) ; sans id, Capturia la cherche par external_id, puis phone, puis email. Une fiche fusionnée mène à la fiche conservée. Une personne inconnue reçoit une fiche, créée sans aucun consentement de communication. Avec create_if_missing: false, ou sans téléphone ni courriel, la conversation attend qu'un membre du compte la rattache à une fiche (status: awaiting_contact).
recording_noticestringobligatoiregiven : chaque personne de la conversation a été informée qu'elle est enregistrée et analysée par une intelligence artificielle. Toute autre valeur, ou son absence, refuse l'envoi (422 recording_notice_required).
speakersobjectoptionnelLe rôle de chaque voix d'une transcription, par le nom qu'elle y porte : agent (la personne qui a tenu la conversation), prospect ou other. 20 voix au plus. Un nom absent de la transcription est ignoré. Une voix que speakers ne nomme pas est déduite par l'analyse, qui garde les rôles donnés pour les autres ; sans speakers, elle déduit toutes les voix.
held_byobjectoptionnelLa personne hors du compte qui a tenu la conversation, par exemple l'agent d'une agence d'appels. Sa conversation reçoit son analyse, son compte rendu et son plan, jamais de note ni de coaching : elle ne fait pas partie de l'équipe du compte.
sellerobjectoptionnelLe membre du compte responsable de la conversation, par id ou par email ; avec les deux, id décide. Un membre inconnu ou inactif refuse l'envoi (422 seller_not_found). Sans seller, la conversation revient au vendeur de la fiche, sinon au vendeur par défaut du compte.
meeting_type_idstringoptionnelLe type de rencontre de la conversation. Sans lui, le type par défaut du compte. Un type inconnu ou retiré refuse l'envoi (422 meeting_type_not_found).
occurred_atstringoptionnelLe moment où la conversation a eu lieu, avec son fuseau (Z ou un décalage).
duration_secondsintegeroptionnelDurée d'une conversation envoyée en texte, en secondes. Sans elle, la durée se lit à la fin de son dernier tour minuté, sinon s'estime d'après son nombre de mots. Ignorée pour un audio, dont la durée se mesure à sa transcription.
languagestringoptionnelLangue de la conversation, en code de deux lettres, avec ou sans sa région (fr, en, fr-CA).
titlestringoptionnelTitre de la rencontre dans Capturia.
channelstringoptionnelComment la conversation s'est tenue : phone (au téléphone), video (en vidéo) ou in_person (en personne). Une conversation au téléphone suit la durée minimale d'analyse des appels, pas celle des rencontres.
external_idstringoptionnelL'identifiant de la conversation chez l'expéditeur. Un envoi qui reprend le même external_id et le même external_source est reconnu : 200 already_received, aucune rencontre n'est créée une deuxième fois.
external_sourcestringoptionnelEspace de noms de external_id (ex. appels-pro). Défaut : api.
source_labelstringoptionnelNom de la source, affiché au compte avec chaque envoi (ex. « Appels Pro »).

Réponses

StatutDescription
200

Conversation déjà reçue : la réponse rend l'identifiant de son premier envoi, sans créer de nouvelle rencontre.

201

Conversation reçue. Une transcription part à l'analyse ; un audio attend son fichier au lien de upload.

400

Requête invalide. code distingue les refus que l'opération rend sous ce statut, et chaque exemple en montre un.

invalid_request
{
  "error": {
    "type": "validation_error",
    "code": "invalid_request",
    "message": "Le format de la requête est invalide.",
    "hint": "Vérifie que les headers, le body et l'encodage JSON respectent le contrat documenté dans l'API Reference.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#invalid_request",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_encoding
{
  "error": {
    "type": "validation_error",
    "code": "invalid_encoding",
    "message": "L'encodage de la requête doit être UTF-8.",
    "hint": "Utilise Content-Type: application/json; charset=utf-8.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/conventions#encoding",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_payload
{
  "error": {
    "type": "validation_error",
    "code": "invalid_payload",
    "message": "Le contenu de la requête est invalide.",
    "hint": "Avec `details`, chaque champ refusé est nommé avec sa raison. Sans `details`, le corps n'a pas pu être lu comme du JSON.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#invalid_payload",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_requestidempotency-key · invalid_format
{
  "error": {
    "type": "validation_error",
    "code": "invalid_request",
    "message": "Le format de la requête est invalide.",
    "hint": "Vérifie que les headers, le body et l'encodage JSON respectent le contrat documenté dans l'API Reference.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#invalid_request",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "field": "idempotency-key",
      "reason": "invalid_format"
    }
  }
}
401

La clé API manque, est inconnue ou a expiré. code distingue les trois causes : missing_api_key (aucun en-tête Authorization: Bearer), invalid_api_key (clé inconnue, révoquée ou de format invalide) et expired_api_key (date d'expiration dépassée).

missing_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "missing_api_key",
    "message": "Aucune clé API n'a été fournie.",
    "hint": "Ajoute un header Authorization sous la forme : Bearer cap_live_<ta_clé>",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#missing_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "La clé API est invalide ou a été révoquée.",
    "hint": "Vérifie la clé dans ton dashboard ou génère-en une nouvelle.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#invalid_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
expired_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "expired_api_key",
    "message": "La clé API a expiré.",
    "hint": "Roule la clé depuis le dashboard pour en générer une nouvelle valide.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#expired_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
403

Refus d'autorisation. code distingue les refus que l'opération rend sous ce statut, et chaque exemple en montre un.

browser_not_allowed
{
  "error": {
    "type": "authorization_error",
    "code": "browser_not_allowed",
    "message": "Les clés API s'utilisent depuis un serveur, jamais depuis un navigateur.",
    "hint": "La requête porte un en-tête `Origin` : appelle l'API depuis ton serveur, où la clé reste secrète.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#browser_not_allowed",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
account_suspended
{
  "error": {
    "type": "authorization_error",
    "code": "account_suspended",
    "message": "L'accès à ce compte est suspendu par l'équipe Capturia.",
    "hint": "Le refus vient du compte, pas de la clé. Tant que la suspension dure, aucune requête n'est acceptée : contacte l'équipe Capturia.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#account_suspended",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
feature_not_available
{
  "error": {
    "type": "authorization_error",
    "code": "feature_not_available",
    "message": "Cette fonctionnalité n'est pas incluse dans ton forfait.",
    "hint": "Le refus vient du forfait du compte, pas de la clé. Contacte ton conseiller Capturia pour en parler.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#plan",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "feature": "public_api"
    }
  }
}
insufficient_scope
{
  "error": {
    "type": "authorization_error",
    "code": "insufficient_scope",
    "message": "Cette clé API ne contient pas le scope requis pour ce point d'accès.",
    "hint": "Cette clé n'a pas le scope `conversations:import`. Crée une nouvelle clé avec le preset « Lecture + écriture » ou ajoute le scope via le dashboard.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#scopes",
    "dashboard_url": "https://capturia.io/platform/dashboard/admin/integrations/api-keys/6f1e2d3c-4b5a-4c6d-8e7f-9a0b1c2d3e4f?tab=permissions",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "required_scope": "conversations:import",
      "required_permission": "call_review.manage",
      "current_scopes": [
        "leads:capture"
      ],
      "suggested_preset": "read_write"
    }
  }
}
404

contact_not_found : contact.id ne désigne aucune fiche de ce compte. Rien n'est enregistré : envoie l'identifiant d'une fiche du compte, ou retire contact.id pour que Capturia cherche la fiche par ses autres identifiants.

contact_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "contact_not_found",
    "message": "Aucune fiche du compte ne porte cet identifiant (`contact.id`). Rien n'a été enregistré.",
    "hint": "Vérifie `contact.id`, ou retire-le pour que Capturia cherche la fiche par l'`external_id`, le téléphone ou le courriel : une personne inconnue reçoit une fiche ; avec `create_if_missing: false`, ou sans téléphone ni courriel, la conversation attend d'être rattachée.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#contact_not_found",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
409

Conflit de clé d'idempotence. La même Idempotency-Key a servi pour un autre corps (details.reason : payload_mismatch), ou la première requête sous cette clé est encore en cours (in_flight, réessayer après Retry-After).

idempotency_conflictpayload_mismatch
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_conflict",
    "message": "Conflit de clé d'idempotence.",
    "hint": "Soit la même Idempotency-Key a été utilisée avec un contenu différent, soit une requête avec cette clé est encore en cours. Utilise une nouvelle Idempotency-Key par requête logique.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/conventions#idempotency",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "reason": "payload_mismatch"
    }
  }
}
idempotency_conflictin_flight
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_conflict",
    "message": "Conflit de clé d'idempotence.",
    "hint": "Soit la même Idempotency-Key a été utilisée avec un contenu différent, soit une requête avec cette clé est encore en cours. Utilise une nouvelle Idempotency-Key par requête logique.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/conventions#idempotency",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "reason": "in_flight"
    }
  }
}
413

Le corps de la requête dépasse 1 Mo (1 048 576 octets). details.max_bytes donne la limite, et details.received_bytes la taille annoncée par Content-Length quand la requête la déclare.

payload_too_large
{
  "error": {
    "type": "validation_error",
    "code": "payload_too_large",
    "message": "Le corps de la requête dépasse la limite de 1 Mo.",
    "hint": "Divise ta requête en plus petits lots.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/conventions#body-size",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "max_bytes": 1048576,
      "received_bytes": 1572864
    }
  }
}
415

L'en-tête Content-Type est absent, ou n'est pas application/json.

invalid_content_type
{
  "error": {
    "type": "validation_error",
    "code": "invalid_content_type",
    "message": "Content-Type non supporté.",
    "hint": "Envoie Content-Type: application/json sur les requêtes POST/PUT/PATCH.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/conventions#content-type",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
422

Requête refusée. code distingue les refus que l'opération rend sous ce statut, et chaque exemple en montre un.

validation_errorbody · held_by_or_seller_required
{
  "error": {
    "type": "validation_error",
    "code": "validation_error",
    "message": "La validation de la requête a échoué.",
    "hint": "`details` nomme chaque champ à corriger et la raison du refus.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#validation_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": [
      {
        "field": "body",
        "reason": "held_by_or_seller_required"
      }
    ]
  }
}
validation_errorcontact · invalid
{
  "error": {
    "type": "validation_error",
    "code": "validation_error",
    "message": "La validation de la requête a échoué.",
    "hint": "`details` nomme chaque champ à corriger et la raison du refus.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#validation_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": [
      {
        "field": "contact",
        "reason": "invalid"
      }
    ]
  }
}
recording_notice_required
{
  "error": {
    "type": "business_rule_error",
    "code": "recording_notice_required",
    "message": "L'envoi ne confirme pas que la personne a été informée de l'enregistrement. Rien n'a été enregistré.",
    "hint": "Envoie `recording_notice: \"given\"` seulement quand chaque personne de la conversation a été informée qu'elle est enregistrée et analysée par une intelligence artificielle.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#recording_notice_required",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
import_attestation_missing
{
  "error": {
    "type": "business_rule_error",
    "code": "import_attestation_missing",
    "message": "La direction du compte n'a pas signé l'attestation des conversations envoyées par un fournisseur. Rien n'a été enregistré.",
    "hint": "Fais-la signer par un propriétaire ou un admin du compte dans Administration › Conversations importées, puis renvoie la conversation.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#import_attestation_missing",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
contact_refused_recording
{
  "error": {
    "type": "business_rule_error",
    "code": "contact_refused_recording",
    "message": "La personne de cette fiche a refusé d'être enregistrée : sa fiche ne reçoit aucune conversation. Rien n'a été enregistré.",
    "hint": "Ne renvoie pas cette conversation. Si la personne change d'avis, un membre du compte retire le refus sur sa fiche.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#contact_refused_recording",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
transcript_unreadable
{
  "error": {
    "type": "validation_error",
    "code": "transcript_unreadable",
    "message": "La transcription ne contient aucun tour de parole lisible, ou ses temps ne sont pas ceux d'une conversation.",
    "hint": "Envoie le texte tel quel dans `transcript.text` (une ligne « Nom : texte » par tour, ou un fichier WebVTT ou SRT), ou les tours dans `transcript.turns`. Les temps se comptent depuis le début de la conversation, sur une journée au plus, la fin jamais avant le début.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#transcript_unreadable",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
transcript_too_short
{
  "error": {
    "type": "validation_error",
    "code": "transcript_too_short",
    "message": "La transcription est trop courte pour être analysée.",
    "hint": "`details.min_words` donne le nombre de mots minimal. Une conversation plus courte n'a rien à analyser.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#transcript_too_short",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "min_words": 15
    }
  }
}
transcript_too_long
{
  "error": {
    "type": "validation_error",
    "code": "transcript_too_long",
    "message": "La transcription dépasse la taille permise.",
    "hint": "`details.max_characters` donne la limite. Une conversation plus longue s'envoie par son enregistrement audio (`media`).",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#transcript_too_long",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "max_characters": 500000
    }
  }
}
unsupported_media_type
{
  "error": {
    "type": "validation_error",
    "code": "unsupported_media_type",
    "message": "Ce format d'audio n'est pas accepté.",
    "hint": "`details.allowed` liste les types acceptés. Convertis l'enregistrement, ou envoie sa transcription.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#unsupported_media_type",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "allowed": [
        "audio/mpeg",
        "audio/mp4",
        "audio/m4a",
        "audio/x-m4a",
        "audio/wav",
        "audio/x-wav",
        "audio/aac",
        "audio/ogg",
        "audio/opus",
        "audio/webm",
        "audio/flac",
        "audio/amr",
        "audio/3gpp"
      ]
    }
  }
}
media_too_large
{
  "error": {
    "type": "validation_error",
    "code": "media_too_large",
    "message": "Le fichier audio dépasse la taille permise.",
    "hint": "`details.max_bytes` donne la limite. Envoie la transcription de la conversation à la place.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#media_too_large",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "max_bytes": 268435456
    }
  }
}
seller_not_found
{
  "error": {
    "type": "business_rule_error",
    "code": "seller_not_found",
    "message": "Le vendeur nommé n'est pas un membre actif du compte. Rien n'a été enregistré.",
    "hint": "Vérifie `seller.email` ou `seller.id`, ou retire `seller` : la conversation revient alors au vendeur de la fiche, sinon au vendeur par défaut du compte.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#seller_not_found",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
meeting_type_not_found
{
  "error": {
    "type": "business_rule_error",
    "code": "meeting_type_not_found",
    "message": "Le type de rencontre nommé n'existe pas ou a été retiré. Rien n'a été enregistré.",
    "hint": "Vérifie `meeting_type_id`, ou retire-le : la conversation prend alors le type par défaut du compte.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#meeting_type_not_found",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
upload_incomplete
{
  "error": {
    "type": "business_rule_error",
    "code": "upload_incomplete",
    "message": "Le fichier audio n'est pas arrivé complet. L'envoi a été retiré.",
    "hint": "Renvoie la conversation pour obtenir un nouveau lien d'envoi, puis téléverse le fichier en entier avant d'appeler `complete`.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#upload_incomplete",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
429

Limite atteinte. rate_limit_exceeded : le quota horaire de la clé est épuisé. too_many_attempts : trop de clés invalides présentées depuis cette adresse IP. rate_limited_ip : plus de 120 requêtes par minute depuis cette adresse IP sur ce point d'accès, quelle que soit la clé ; l'en-tête X-RateLimit-Scope vaut alors ip. Pour ces trois codes, Retry-After donne le délai en secondes. import_daily_limit_reached : le compte a reçu aujourd'hui (UTC) le nombre de conversations qu'il peut recevoir par jour ; rien n'est enregistré, renvoie la conversation le lendemain. Ce refus compte dans le quota de la clé.

rate_limit_exceeded
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Limite de requêtes atteinte.",
    "hint": "Réessaie après le nombre de secondes indiqué dans retry_after_seconds, et envisage d'implémenter un backoff exponentiel.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/rate-limits",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "limit": 100,
      "count": 100,
      "limit_type": "per_key",
      "retry_after_seconds": 42
    }
  }
}
too_many_attempts
{
  "error": {
    "type": "rate_limit_error",
    "code": "too_many_attempts",
    "message": "Trop de tentatives d'authentification invalides depuis cette IP.",
    "hint": "Attends la période indiquée par retry_after_seconds avant de réessayer.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#brute-force",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "limit_type": "brute_force",
      "retry_after_seconds": 300
    }
  }
}
rate_limited_ip
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limited_ip",
    "message": "Limite de requêtes par adresse IP atteinte.",
    "hint": "`details` donne la limite et la fenêtre en secondes. Attends le délai de l'en-tête `Retry-After` avant de réessayer.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#rate_limited_ip",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "limit": 120,
      "window_seconds": 60
    }
  }
}
import_daily_limit_reached
{
  "error": {
    "type": "business_rule_error",
    "code": "import_daily_limit_reached",
    "message": "Le plafond de conversations importées aujourd'hui est atteint pour ce compte. Rien n'a été enregistré.",
    "hint": "Le plafond se compte par jour (UTC) et par compte. Renvoie la conversation demain.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#import_daily_limit_reached",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
500

Erreur serveur inattendue. Toujours fournir le request_id au support.

internal_error
{
  "error": {
    "type": "server_error",
    "code": "internal_error",
    "message": "Erreur serveur. L'équipe Capturia a été notifiée.",
    "hint": "Si le problème persiste, contacte le support en incluant le request_id de cette réponse.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#internal_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
501

Les clés de test (cap_test_) ne sont pas encore servies : seules les clés cap_live_ sont acceptées.

not_implemented
{
  "error": {
    "type": "server_error",
    "code": "not_implemented",
    "message": "Cette fonctionnalité n'est pas encore implémentée.",
    "hint": "Consulte la documentation API pour les fonctionnalités disponibles et le changelog pour les prochaines versions.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#not_implemented",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
503

Un service dont la requête dépend n'a pas répondu (lecture de la clé, du compte ou du forfait). La même requête passera quand il reviendra : réessaie après le délai de Retry-After.

service_unavailable
{
  "error": {
    "type": "server_error",
    "code": "service_unavailable",
    "message": "Service temporairement indisponible.",
    "hint": "Réessaie après la période indiquée par Retry-After.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#service_unavailable",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}

Exemple de requête

curl -X POST 'https://api.capturia.io/v1/conversation-imports' \
  -H 'Authorization: Bearer cap_live_<your-key>' \
  -H 'Content-Type: application/json' \
  -d '{
  "transcript": {
    "text": "Julie : Bonjour, ici Julie d'Appels Pro. Je vous appelle au sujet de votre demande de soumission pour la cuisine.\nMarc : Oui, bonjour. On aimerait refaire les armoires et le comptoir avant le printemps.\nJulie : Parfait. Quel budget avez-vous en tête pour le projet ?\nMarc : Autour de vingt mille dollars, installation comprise.\n"
  },
  "speakers": {
    "Julie": "agent",
    "Marc": "prospect"
  },
  "recording_notice": "given",
  "held_by": {
    "name": "Julie Bouchard",
    "organization": "Appels Pro"
  },
  "contact": {
    "phone": "+15145551234",
    "first_name": "Marc"
  },
  "occurred_at": "2026-11-04T14:30:00-05:00",
  "channel": "phone",
  "external_id": "appel-88213",
  "external_source": "appels-pro",
  "source_label": "Appels Pro"
}'
post/v1/conversation-imports/complete

Conclure le dépôt d'un audio

Dis à Capturia que le fichier audio annoncé par POST /v1/conversation-imports est déposé au lien d'envoi. Capturia vérifie qu'il est arrivé entier, à la taille annoncée, puis le fait transcrire et analyser (status: processing). Rejouable : un dépôt déjà conclu rend la même réponse.

Le corps nomme l'envoi par son identifiant (id), celui que rend POST /v1/conversation-imports.

Scopes requis : conversations:import

Corps de requête

PropriétéTypeObligatoireDescription
idstringobligatoireL'identifiant de l'envoi dont le fichier audio est déposé, rendu par POST /v1/conversation-imports.

Réponses

StatutDescription
200

Fichier reçu. La conversation part à sa transcription, puis à son analyse.

400

Requête invalide. code distingue les refus que l'opération rend sous ce statut, et chaque exemple en montre un.

invalid_request
{
  "error": {
    "type": "validation_error",
    "code": "invalid_request",
    "message": "Le format de la requête est invalide.",
    "hint": "Vérifie que les headers, le body et l'encodage JSON respectent le contrat documenté dans l'API Reference.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#invalid_request",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_encoding
{
  "error": {
    "type": "validation_error",
    "code": "invalid_encoding",
    "message": "L'encodage de la requête doit être UTF-8.",
    "hint": "Utilise Content-Type: application/json; charset=utf-8.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/conventions#encoding",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_json
{
  "error": {
    "type": "validation_error",
    "code": "invalid_json",
    "message": "Le corps de la requête n'est pas du JSON valide.",
    "hint": "Vérifie la syntaxe du JSON envoyé (guillemets, virgules, accolades) et son encodage UTF-8.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#invalid_json",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_body
{
  "error": {
    "type": "validation_error",
    "code": "invalid_body",
    "message": "Le corps de la requête doit être un objet JSON.",
    "hint": "Envoie un objet (`{ ... }`) : ce point d'accès n'accepte ni tableau, ni chaîne, ni nombre.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#invalid_body",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
validation_errorid · required
{
  "error": {
    "type": "validation_error",
    "code": "validation_error",
    "message": "La validation de la requête a échoué.",
    "hint": "`details` nomme chaque champ à corriger et la raison du refus.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#validation_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": [
      {
        "field": "id",
        "reason": "required"
      }
    ]
  }
}
validation_errorid · invalid_uuid
{
  "error": {
    "type": "validation_error",
    "code": "validation_error",
    "message": "La validation de la requête a échoué.",
    "hint": "`details` nomme chaque champ à corriger et la raison du refus.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#validation_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": [
      {
        "field": "id",
        "reason": "invalid_uuid"
      }
    ]
  }
}
401

La clé API manque, est inconnue ou a expiré. code distingue les trois causes : missing_api_key (aucun en-tête Authorization: Bearer), invalid_api_key (clé inconnue, révoquée ou de format invalide) et expired_api_key (date d'expiration dépassée).

missing_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "missing_api_key",
    "message": "Aucune clé API n'a été fournie.",
    "hint": "Ajoute un header Authorization sous la forme : Bearer cap_live_<ta_clé>",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#missing_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
invalid_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "La clé API est invalide ou a été révoquée.",
    "hint": "Vérifie la clé dans ton dashboard ou génère-en une nouvelle.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#invalid_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
expired_api_key
{
  "error": {
    "type": "authentication_error",
    "code": "expired_api_key",
    "message": "La clé API a expiré.",
    "hint": "Roule la clé depuis le dashboard pour en générer une nouvelle valide.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#expired_api_key",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
403

Refus d'autorisation. code distingue les refus que l'opération rend sous ce statut, et chaque exemple en montre un.

browser_not_allowed
{
  "error": {
    "type": "authorization_error",
    "code": "browser_not_allowed",
    "message": "Les clés API s'utilisent depuis un serveur, jamais depuis un navigateur.",
    "hint": "La requête porte un en-tête `Origin` : appelle l'API depuis ton serveur, où la clé reste secrète.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#browser_not_allowed",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
account_suspended
{
  "error": {
    "type": "authorization_error",
    "code": "account_suspended",
    "message": "L'accès à ce compte est suspendu par l'équipe Capturia.",
    "hint": "Le refus vient du compte, pas de la clé. Tant que la suspension dure, aucune requête n'est acceptée : contacte l'équipe Capturia.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#account_suspended",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
feature_not_available
{
  "error": {
    "type": "authorization_error",
    "code": "feature_not_available",
    "message": "Cette fonctionnalité n'est pas incluse dans ton forfait.",
    "hint": "Le refus vient du forfait du compte, pas de la clé. Contacte ton conseiller Capturia pour en parler.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#plan",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "feature": "public_api"
    }
  }
}
insufficient_scope
{
  "error": {
    "type": "authorization_error",
    "code": "insufficient_scope",
    "message": "Cette clé API ne contient pas le scope requis pour ce point d'accès.",
    "hint": "Cette clé n'a pas le scope `conversations:import`. Crée une nouvelle clé avec le preset « Lecture + écriture » ou ajoute le scope via le dashboard.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#scopes",
    "dashboard_url": "https://capturia.io/platform/dashboard/admin/integrations/api-keys/6f1e2d3c-4b5a-4c6d-8e7f-9a0b1c2d3e4f?tab=permissions",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "required_scope": "conversations:import",
      "required_permission": "call_review.manage",
      "current_scopes": [
        "leads:capture"
      ],
      "suggested_preset": "read_write"
    }
  }
}
404

resource_not_found : aucun envoi reçu de ce compte ne porte cet identifiant (inconnu, d'un autre compte, refusé ou retiré).

resource_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "resource_not_found",
    "message": "La ressource demandée est introuvable.",
    "hint": "Vérifie l'ID de la ressource. Elle a peut-être été supprimée ou n'a jamais existé.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#resource_not_found",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
413

Le corps de la requête dépasse 1 Mo (1 048 576 octets). details.max_bytes donne la limite, et details.received_bytes la taille annoncée par Content-Length quand la requête la déclare.

payload_too_large
{
  "error": {
    "type": "validation_error",
    "code": "payload_too_large",
    "message": "Le corps de la requête dépasse la limite de 1 Mo.",
    "hint": "Divise ta requête en plus petits lots.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/conventions#body-size",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "max_bytes": 1048576,
      "received_bytes": 1572864
    }
  }
}
415

L'en-tête Content-Type est absent, ou n'est pas application/json.

invalid_content_type
{
  "error": {
    "type": "validation_error",
    "code": "invalid_content_type",
    "message": "Content-Type non supporté.",
    "hint": "Envoie Content-Type: application/json sur les requêtes POST/PUT/PATCH.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/conventions#content-type",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
422

Le dépôt ne peut pas se conclure. business_rule_violation : details.reason vaut not_an_audio_import (l'envoi est une transcription, déjà partie à l'analyse) ou upload_not_received (le fichier n'est pas encore au lien d'envoi : téléverse-le, puis rappelle complete). upload_incomplete : le fichier déposé n'a pas la taille annoncée ; l'envoi est retiré, renvoie la conversation pour obtenir un nouveau lien d'envoi.

business_rule_violationnot_an_audio_import
{
  "error": {
    "type": "business_rule_error",
    "code": "business_rule_violation",
    "message": "Une règle métier empêche cette opération.",
    "hint": "`details` nomme la règle qui bloque l'opération. La référence du point d'accès liste chaque valeur possible et ce qu'elle demande.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#business_rule_violation",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "reason": "not_an_audio_import"
    }
  }
}
business_rule_violationupload_not_received
{
  "error": {
    "type": "business_rule_error",
    "code": "business_rule_violation",
    "message": "Une règle métier empêche cette opération.",
    "hint": "`details` nomme la règle qui bloque l'opération. La référence du point d'accès liste chaque valeur possible et ce qu'elle demande.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#business_rule_violation",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "reason": "upload_not_received"
    }
  }
}
upload_incomplete
{
  "error": {
    "type": "business_rule_error",
    "code": "upload_incomplete",
    "message": "Le fichier audio n'est pas arrivé complet. L'envoi a été retiré.",
    "hint": "Renvoie la conversation pour obtenir un nouveau lien d'envoi, puis téléverse le fichier en entier avant d'appeler `complete`.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#upload_incomplete",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
429

Limite de débit atteinte. rate_limit_exceeded : le quota horaire de la clé est épuisé. too_many_attempts : trop de clés invalides présentées depuis cette adresse IP (protection contre la force brute). Dans les deux cas, Retry-After donne le délai en secondes.

rate_limit_exceeded
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Limite de requêtes atteinte.",
    "hint": "Réessaie après le nombre de secondes indiqué dans retry_after_seconds, et envisage d'implémenter un backoff exponentiel.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/rate-limits",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "limit": 100,
      "count": 100,
      "limit_type": "per_key",
      "retry_after_seconds": 42
    }
  }
}
too_many_attempts
{
  "error": {
    "type": "rate_limit_error",
    "code": "too_many_attempts",
    "message": "Trop de tentatives d'authentification invalides depuis cette IP.",
    "hint": "Attends la période indiquée par retry_after_seconds avant de réessayer.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/authentication#brute-force",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7",
    "details": {
      "limit_type": "brute_force",
      "retry_after_seconds": 300
    }
  }
}
500

Erreur serveur inattendue. Toujours fournir le request_id au support.

internal_error
{
  "error": {
    "type": "server_error",
    "code": "internal_error",
    "message": "Erreur serveur. L'équipe Capturia a été notifiée.",
    "hint": "Si le problème persiste, contacte le support en incluant le request_id de cette réponse.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#internal_error",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
501

Les clés de test (cap_test_) ne sont pas encore servies : seules les clés cap_live_ sont acceptées.

not_implemented
{
  "error": {
    "type": "server_error",
    "code": "not_implemented",
    "message": "Cette fonctionnalité n'est pas encore implémentée.",
    "hint": "Consulte la documentation API pour les fonctionnalités disponibles et le changelog pour les prochaines versions.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#not_implemented",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}
503

Un service dont la requête dépend n'a pas répondu : la lecture de la clé, du compte ou du forfait, ou le stockage qui vérifie le fichier déposé. La même requête passera quand il reviendra : réessaie après le délai de Retry-After.

service_unavailable
{
  "error": {
    "type": "server_error",
    "code": "service_unavailable",
    "message": "Service temporairement indisponible.",
    "hint": "Réessaie après la période indiquée par Retry-After.",
    "doc_url": "https://capturia.io/fr/developers/api/v1/errors#service_unavailable",
    "request_id": "req_01J9X8Z3F4K2M5N7P9Q1R3S5T7"
  }
}

Exemple de requête

curl -X POST 'https://api.capturia.io/v1/conversation-imports/complete' \
  -H 'Authorization: Bearer cap_live_<your-key>' \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "6a7b8c9d-0e1f-4a2b-9c3d-4e5f6a7b8c9d"
}'