Conversation imports
3 endpoints
/v1/conversation-importsRead the state of a sent conversation
The state of a submission to POST /: received
on its contact, waiting for a contact, refused with its reason, or
received as a duplicate, and where the analysis of its meeting stands
(recording.).
A submission from another account returns 404, like a submission
that doesn't exist. A refused or duplicate submission is erased after
30 days; a received submission goes away with its meeting.
conversations:importQuery parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | The submission's ID, as returned by POST / (id). Missing or malformed, the request returns 400 validation_. |
Responses
| Status | Description |
|---|---|
200 | State of the submission. |
400 | Invalid request.
|
401 | The API key is missing, unknown or expired.
|
403 | Authorization refused.
|
404 |
|
429 | Rate limit reached.
|
500 | Unexpected server error. Always include the
|
501 | Test keys (
|
503 | A service the request depends on didn't respond (reading the key, the
account or the plan). The same request will go through once it's back:
retry after the
|
Example request
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'/v1/conversation-importsSend a conversation held outside Capturia
A call agency, a tool such as Zapier or Make, or your own system sends a conversation held outside Capturia: a call, a video or in-person meeting. Capturia files it on the person's contact and analyzes it like a meeting recorded in Capturia.
As text
Send the transcript as is in transcript.: Capturia reads it like
a text pasted in the app. A "Name: text" line opens a speaking turn; a
WebVTT or SRT file is read too. Or send the turns already split in
transcript.. speakers gives each voice its role by its name
(agent, prospect or other); without it, the analysis works out
who is speaking. The conversation goes to analysis as soon as the
response is sent.
As audio, in three steps
- Announce the file in
media: its name, its type and its exact size in bytes. The response returns an upload link inupload, valid for 2 hours. - Upload the file with
PUTtoupload., with theurl Content-header of the announced type.Type - Call
POST /with the submission'sv1/ conversation- imports/ complete id: Capturia checks the file, then has it transcribed and analyzed.
Sending the same announcement again before the file arrives returns a new upload link. An audio whose file hasn't arrived one day after its announcement is removed.
Recording notice
recording_ declares that every person in the
conversation was told it is recorded and analyzed by artificial
intelligence; without this declaration, the submission is refused
(422 recording_). The account's management must also
have signed the attestation for conversations sent by a provider, in
Administration › Imported conversations (422 import_ otherwise).
Who held the conversation
Name them in held_, in seller, or in both. held_: someone
outside the account, for example an agent at a call agency. Their
conversation gets its analysis, its summary and its plan, never a
score or coaching. seller: the account member responsible for the
conversation. Without seller, the conversation goes to the
contact's seller, otherwise to the account's default seller.
The contact
contact. points to the contact; without it, Capturia looks it up by
external_, then phone, then email. An unknown person gets a
contact, created without any communication consent
(contact_). With create_, or without
a phone number or email, the conversation waits for an account member
to attach it to a contact (status: awaiting_). A contact whose
person refused to be recorded receives no conversation
(422 contact_).
Duplicates
A conversation comes in only once per account. A text with the same
words (voice names and timestamps aside), an audio announced
identically for the same person (same file name, same size, same
occurred_), or the same external_ under the same
external_ returns 200 already_ with the ID of the
first submission, without creating a new meeting. An audio therefore
always says which conversation it is: external_, the most reliable
match, or occurred_ (media_ with neither). The
Idempotency- header remains available for retries of a transcript;
an audio announcement doesn't read it, so that its retry always returns
a fresh upload link.
Limit and cost
Each account receives a limited number of conversations per day
(UTC): beyond it, 429 import_ until the next day.
Audio has its own limit, 40 transcribed hours per day (UTC): it is
checked at transcription, once the file is received. A file must fit in
what remains, based on the measured duration of the audio already
transcribed that day and a high estimate of its own, drawn from its
size. An audio that doesn't fit is removed;
GET / then shows it refused with
audio_. The analysis is
debited from the account's credits, like that of a meeting recorded in
Capturia.
conversations:importHeaders
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | optional | Idempotency key: 16 to 128 [A- characters (a UUID v4 or a ULID works). A key of any other
shape is refused with 400 invalid_ (details.: idempotency-); an empty header counts as
a request without a key. A second request with the same key and the same payload returns the original
response, with the Idempotency- header, without repeating the operation; the same key with
a different payload is refused with 409 idempotency_. Stored for 24 h. Optional but recommended. |
Request body
| Property | Type | Required | Description |
|---|---|---|---|
transcript | ConversationImportTranscript | optional | The conversation as text: text or turns, never both
(details[].: text_). At least 15 words (422 transcript_), at most 500,000 characters in total. |
media | ConversationImportMedia | optional | The announced audio recording. Its file is then uploaded to the link
returned in upload, then POST / has
it transcribed and analyzed. |
contact | ConversationImportContact | optional | The person the conversation was held with. id points to their
contact (unknown: 404 contact_); without id, Capturia
looks it up by external_, then phone, then email. A merged
contact leads to the contact that was kept. An unknown person gets a
contact, created without any communication consent. With
create_, or without a phone number or email, the
conversation waits for an account member to attach it to a contact
(status: awaiting_). |
recording_notice | string | required | given: every person in the conversation was told it is recorded and
analyzed by artificial intelligence. Any other value, or its absence,
refuses the submission (422 recording_). |
speakers | object | optional | The role of each voice in a transcript, by the name it carries there:
agent (the person who held the conversation), prospect or other.
20 voices at most. A name missing from the transcript is ignored. A
voice that speakers doesn't name is worked out by the analysis, which
keeps the roles given for the others; without speakers, it works out
every voice. |
held_by | object | optional | The person outside the account who held the conversation, for example an agent at a call agency. Their conversation gets its analysis, its summary and its plan, never a score or coaching: they aren't part of the account's team. |
seller | object | optional | The account member responsible for the conversation, by id or by
email; with both, id wins. An unknown or inactive member refuses
the submission (422 seller_). Without seller, the
conversation goes to the contact's seller, otherwise to the account's
default seller. |
meeting_type_id | string | optional | The meeting type of the conversation. Without it, the account's
default type. An unknown or removed type refuses the submission (422 meeting_). |
occurred_at | string | optional | When the conversation took place, with its time zone (Z or an offset). |
duration_seconds | integer | optional | Duration of a conversation sent as text, in seconds. Without it, the duration is read from the end of its last timed turn, otherwise estimated from its word count. Ignored for an audio, whose duration is measured at its transcription. |
language | string | optional | Language of the conversation, as a two-letter code, with or without its region (fr, en, fr-). |
title | string | optional | Title of the meeting in Capturia. |
channel | string | optional | How the conversation was held: phone (on the phone), video (on
video) or in_ (in person). A phone conversation follows the
minimum analysis duration of calls, not that of meetings. |
external_id | string | optional | The conversation's ID on the sender's side. A submission with the same
external_ and the same external_ is recognized: 200 already_, no meeting is created a second time. |
external_source | string | optional | Namespace of external_ (e.g. appels-). Default: api. |
source_label | string | optional | Name of the source, shown to the account with each submission (e.g. "Appels Pro"). |
Responses
| Status | Description |
|---|---|
200 | Conversation already received: the response returns the ID of its first submission, without creating a new meeting. |
201 | Conversation received. A transcript goes to analysis; an audio waits for its file at the |
400 | Invalid request.
|
401 | The API key is missing, unknown or expired.
|
403 | Authorization refused.
|
404 |
|
409 | Idempotency key conflict. The same
|
413 | The request body exceeds 1 MB (1,048,576 bytes).
|
415 | The
|
422 | Request refused.
|
429 | Limit reached.
|
500 | Unexpected server error. Always include the
|
501 | Test keys (
|
503 | A service the request depends on didn't respond (reading the key, the
account or the plan). The same request will go through once it's back:
retry after the
|
Example request
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"
}'/v1/conversation-imports/completeComplete an audio upload
Tell Capturia that the audio file announced through POST / is uploaded at the upload link. Capturia
checks that it arrived whole, at the announced size, then has it
transcribed and analyzed (status: processing). Replayable: an upload
already completed returns the same response.
The body names the submission by its ID (id), the one returned by
POST /.
conversations:importRequest body
| Property | Type | Required | Description |
|---|---|---|---|
id | string | required | The ID of the submission whose audio file is uploaded, as returned by POST /. |
Responses
| Status | Description |
|---|---|
200 | File received. The conversation goes to its transcription, then to its analysis. |
400 | Invalid request.
|
401 | The API key is missing, unknown or expired.
|
403 | Authorization refused.
|
404 |
|
413 | The request body exceeds 1 MB (1,048,576 bytes).
|
415 | The
|
422 | The upload can't be completed.
|
429 | Rate limit reached.
|
500 | Unexpected server error. Always include the
|
501 | Test keys (
|
503 | A service the request depends on didn't respond: reading the key, the
account or the plan, or the storage that checks the uploaded file. The
same request will go through once it's back: retry after the
|
Example request
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"
}'