API reference · Core resources
Upload consultation audio, start transcription and read partial (live) transcripts.
The consultation's saved full transcript.
transcriptionstringrequiredFull transcript as plain text, or an empty string if nothing has been transcribed yet. Built from the consultation's partial transcriptions in recording order, joined with a single space; text partial transcriptions are included verbatim. Within a recording, a change of speaker starts a new paragraph (blank line), but speakers are not labelled. Medical terms that the spelling check is very confident about are annotated inline as term (Suggestion?).
{
"transcription": "This is a synthetic Vetnio demo recording, with no real patient information. Milo is a five year old Labrador here for an annual wellness visit. His owner reports a normal appetite, regular walks, and no recent vomiting or coughing. On the demo examination, Milo is bright and comfortable. His recorded weight is twenty eight point four kilograms. Mild dental plaque is noted. We discussed routine dental care and recorded the owner's questions. This visit is a fictional software test. No medication was prescribed."
}POST/workspaces/{workspaceId}/consultations/{consultationId}/partial-transcriptions
Adds text to the consultation's transcript as a new partial transcription. The text is stored as-is, merged into the full transcript immediately (ordered by creation time among the audio recordings), and used by later document generation. The text is not spell-checked or otherwise changed, and adding it does not start audio transcription.
Not idempotent: every call adds another entry, and there is no endpoint to edit or remove a partial transcription, so retry only when you know the first call failed. Returns 403 for archived consultations.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
textstringrequiredText to add to the transcript verbatim, 1 to 50,000 characters. Typical uses: notes typed during the visit, an owner's SMS or email, or a transcript produced by your own speech-to-text.
at least 1 characters · at most 50000 characters
languageCodeenumoptionalLanguage of the text, as one of the supported lowercase ISO 639 codes. Defaults to en. Stored in the generated recordingId; the text itself is not translated.
Possible values:svenafamarhyasastazbebnbsbgmyyuecacebnyzhhrcsdanletfilfifrffgllgkadeelguhahehihuisigidgaitjajvkeaknkkkmkokukylolvlnltluolbmkmsmlmtmimrmnnensonoocorpsfaplptparorusrsnsdskslsoesswtltatgtethtrukumburuzvicywoxhzu
Default en
successbooleanrequiredAlways true when the partial transcription was created successfully.
recordingIdstringrequiredGenerated ID of the new text partial transcription, in the form <epoch-ms>-<uuid>-text-<language>.
messagestringrequiredHuman-readable confirmation message. It says so when the text is stored but not yet in the consultation transcript because the consultation is being moved or erased.
curl -X POST "https://vetnio.com/api/v2/workspaces/demo-north-clinic/consultations/bc0cf418-6503-46eb-9828-c83f8c193426/partial-transcriptions" \
-H "Authorization: Bearer $VETNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Bella is in for her annual vaccination. Owner mentions some ear scratching.",
"languageCode": "en"
}'{
"success": true,
"recordingId": "1791130040129-ea4ddc50-99b5-4f6a-b56c-e61bb5024c92-text-en",
"message": "Partial transcription created successfully. It will be included in document generation."
}GET/workspaces/{workspaceId}/consultations/{consultationId}/partial-transcriptions
Lists the partial transcriptions of a consultation: one per transcribed audio recording plus one per text snippet added with POST .../partial-transcriptions. They are not live or streaming results; an audio partial appears only after its recording has been transcribed. Only metadata is returned; the text of individual partials is not available through the API. Read the combined text with GET .../transcription. Useful to check which recordings have been transcribed and whether text snippets were added.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
countnumberrequiredNumber of partial transcriptions for this consultation.
partialTranscriptionsarray of objectsrequiredPartial transcriptions sorted by recordingId, which is chronological order and the order in which they are joined into the full transcript. Recordings shorter than one second appear here with empty text.
recordingIdstringrequiredID of the recording this partial transcription belongs to. Audio recordings use <epoch-ms>-<language> (the ID fixed when the upload URL was issued); text partials use <epoch-ms>-<uuid>-text-<language>. IDs sort chronologically.
keystringrequiredInternal storage key of the partial transcription. Informational only: it cannot be used to download the text through the API.
isTextBasedbooleanrequiredtrue for text added with POST .../partial-transcriptions, false for the transcription of an uploaded audio recording. Derived from -text- in recordingId.
curl "https://vetnio.com/api/v2/workspaces/demo-north-clinic/consultations/bc0cf418-6503-46eb-9828-c83f8c193426/partial-transcriptions" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"count": 1,
"partialTranscriptions": [
{
"recordingId": "1791130040129-ea4ddc50-99b5-4f6a-b56c-e61bb5024c92-text-en",
"key": "transcriptions/demo-north-clinic/bc0cf418-6503-46eb-9828-c83f8c193426/1791130040129-ea4ddc50-99b5-4f6a-b56c-e61bb5024c92-text-en",
"isTextBased": true
}
]
}POST/workspaces/{workspaceId}/consultations/{consultationId}/process-recordings
Optional. Runs audio processing (conversion to 16 kHz mono WAV, silence removal and duration measurement) for every untranscribed recording and waits for the results. Transcription performs this step itself, so you do not need to call this before POST .../transcriptions/start; calling it first only does the processing earlier and lets you find too-short or unreadable audio before transcribing. Processed results are reused by transcription.
Synchronous: takes from a few seconds to minutes for long audio. Does not transcribe or change the consultation. Requires access to the consultation's audio: when the recording is private to its creator, other users get 403 (recordingPrivate). If nothing is untranscribed, both lists are empty.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
messagestringrequiredHuman-readable status message; always the same text on success.
recordingsProcessednumberrequiredNumber of entries in processedRecordings. Recordings whose processing failed outright appear in neither list.
processedRecordingsarray of objectsrequiredRecordings that were processed successfully and can be transcribed.
recordingKeystringrequiredInternal storage key of the original recording; its last segment is the recording ID (<epoch-ms>-<language>).
processedRecordingUrlstringrequiredPresigned GET URL, valid for 24 hours, for the processed audio: 16 kHz mono WAV with leading, trailing and long silences removed. This is the audio that is sent for transcription.
recordingLanguageCodestringrequiredLanguage code taken from the recording ID suffix (for example en); this is the language used to transcribe the recording.
durationInMillisecondsnumberrequiredDuration of the processed audio, after silence removal, in milliseconds.
skippedRecordingsarray of objectsrequiredRecordings that were processed but will not yield transcript text, because they are too short or unreadable.
recordingKeystringrequiredInternal storage key of the original recording; its last segment is the recording ID.
recordingLanguageCodestringrequiredLanguage code taken from the recording ID suffix.
durationInMillisecondsnumberrequiredDuration after silence removal, in milliseconds; 0 for unreadable input.
skippedReasonenumrequiredWhy the recording will not produce transcript text:
too_short — less than one second of audio remains after silence removal; transcription records it as empty text.unreadable_input — the file is empty or not decodable audio; transcription marks it as a permanent failure (unreadable_recording).curl -X POST "https://vetnio.com/api/v2/workspaces/furunculotic-loud-chihuahua/consultations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/process-recordings" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"message": "Recordings processed successfully",
"recordingsProcessed": 2,
"processedRecordings": [
{
"recordingKey": "recordings/furunculotic-loud-chihuahua/a1b2c3d4-e5f6-7890-abcd-ef1234567890/1726302600000-en",
"processedRecordingUrl": "https://example-bucket.s3.eu-central-1.amazonaws.com/processedRecordings/furunculotic-loud-chihuahua/a1b2c3d4-e5f6-7890-abcd-ef1234567890/1726302600000-en?X-Amz-Expires=86400&X-Amz-Signature=...",
"recordingLanguageCode": "en",
"durationInMilliseconds": 45200
}
],
"skippedRecordings": [
{
"recordingKey": "recordings/furunculotic-loud-chihuahua/a1b2c3d4-e5f6-7890-abcd-ef1234567890/1726302700000-en",
"recordingLanguageCode": "en",
"durationInMilliseconds": 140,
"skippedReason": "too_short"
}
]
}POST/workspaces/{workspaceId}/consultations/{consultationId}/recording-chunks
Registers one chunk of a recording and returns where to upload its audio. Upload the bytes with a single PUT to uploadUrl, sending the returned headers; an upload never replaces bytes already stored for the chunk. Safe to repeat: the same chunk returns a fresh upload URL, or alreadyUploaded: true once its exact bytes are stored. The same chunk id with different metadata, or stored bytes that do not match it, returns 409.
After every chunk is uploaded, submit them with POST .../recording-operations. Requires write access to the consultation's recordings.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
chunkobjectrequiredThe chunk of audio to register before uploading it.
idstring (uuid)requiredClient-generated UUID that permanently identifies this chunk of audio. Store it before the first request and reuse it on retries; reusing it for different audio returns 409.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
sessionIdstring (uuid)requiredUUID of the recording session the chunk belongs to. Within one submission, sessionId and index together must be unique.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
indexintegerrequiredPosition of the chunk within its recording session, starting at 0. Any non-negative integer that is unique within the session is accepted.
≥ 0 · ≤ 9007199254740991
recordedAtintegerrequiredWhen the chunk's audio was recorded, in Unix epoch milliseconds from the recording device. It places the chunk among the consultation's other recordings in the transcript.
≥ 1 · ≤ 9007199254740991
languageCodestringrequiredLanguage spoken in the chunk, as a lowercase ISO 639 code optionally followed by subtags, such as sv or pt-BR. Sets the transcription language.
matches `^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$`
sizeintegerrequiredExact size of the audio in bytes, at most 2 GiB.
≥ 1 · ≤ 2147483648
sha256stringrequiredLowercase hexadecimal SHA-256 digest of the audio bytes. Audio whose stored size or digest does not match is rejected before transcription.
matches `^[a-f0-9]{64}$`
alreadyUploadedbooleanrequiredtrue when the chunk's exact bytes are already stored, so no upload is needed and uploadUrl is null.
uploadUrlstringrequirednullablePresigned URL for one PUT of the audio bytes, valid for 15 minutes, or null when alreadyUploaded is true.
headersobjectrequiredHeaders to send with the PUT.
curl -X POST "https://vetnio.com/api/v2/workspaces/furunculotic-loud-chihuahua/consultations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/recording-chunks" \
-H "Authorization: Bearer $VETNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chunk": {
"id": "9b2f6c1e-3a4d-4f5e-8a7b-1c2d3e4f5a6b",
"sessionId": "5e1d2c3b-4a5f-4e6d-9c8b-7a6f5e4d3c2b",
"index": 0,
"recordedAt": 1759600000000,
"languageCode": "sv",
"size": 1048576,
"sha256": "4a1f0c6e3b2d9a8f7e6d5c4b3a2918070f1e2d3c4b5a69788776655443322110"
}
}'{
"alreadyUploaded": false,
"uploadUrl": "https://storage.example.com/recordings/...",
"headers": {
"If-None-Match": "*"
}
}POST/workspaces/{workspaceId}/consultations/{consultationId}/recording-operations
Queues transcription of uploaded chunks, and optionally clinical-note generation, and immediately returns the operation's receipt. On /api/v1 the response is 202 Accepted with a Location header for the status endpoint and a Retry-After header while the operation is still running; repeating the request for a finished operation returns 200 with its final receipt. On /api/v2 it is always 200. The work continues on the server even if the client disconnects. Repeating the request with the same operationId and payload returns the same receipt; a different payload with that ID returns 409. Operations on one consultation run one at a time, in the order they were submitted.
The generated note is merged into the consultation's current note, so earlier edits are kept. If the note is edited while the operation is generating, the edit is kept, the operation fails with note_conflict, and the generated note stays available from the result endpoint. Requires write access to the consultation's recordings.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
submissionobjectrequiredThe immutable recording command. Keep it unchanged for every retry of the same operationId.
protocolVersionnumberrequiredVersion of the recording-operation protocol. Must be 1.
operationIdstring (uuid)requiredClient-generated UUID that identifies this submission. Store it before sending and reuse it after a lost or failed response: the same ID with the same payload returns the existing receipt, and a different payload returns 409.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
chunksarray of objectsrequiredEvery chunk this operation covers, up to 2000, each registered with POST .../recording-chunks and uploaded first. Chunks already transcribed for this consultation are reused instead of being transcribed again. An empty list generates from the consultation's existing transcript.
at most 2000 items
idstring (uuid)requiredClient-generated UUID that permanently identifies this chunk of audio. Store it before the first request and reuse it on retries; reusing it for different audio returns 409.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
sessionIdstring (uuid)requiredUUID of the recording session the chunk belongs to. Within one submission, sessionId and index together must be unique.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
indexintegerrequiredPosition of the chunk within its recording session, starting at 0. Any non-negative integer that is unique within the session is accepted.
≥ 0 · ≤ 9007199254740991
recordedAtintegerrequiredWhen the chunk's audio was recorded, in Unix epoch milliseconds from the recording device. It places the chunk among the consultation's other recordings in the transcript.
≥ 1 · ≤ 9007199254740991
languageCodestringrequiredLanguage spoken in the chunk, as a lowercase ISO 639 code optionally followed by subtags, such as sv or pt-BR. Sets the transcription language.
matches `^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$`
sizeintegerrequiredExact size of the audio in bytes, at most 2 GiB.
≥ 1 · ≤ 2147483648
sha256stringrequiredLowercase hexadecimal SHA-256 digest of the audio bytes. Audio whose stored size or digest does not match is rejected before transcription.
matches `^[a-f0-9]{64}$`
generateClinicalNotebooleanrequiredWhether to generate the clinical note after transcription. With false the chunks are only added to the consultation's transcript.
templateIdstringoptionalnullableID of the clinical note template to generate with, or null to use the consultation's current template.
at least 1 characters · at most 200 characters
operationIdstring (uuid)requiredThe submission's operationId.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
statusenumrequiredaccepted (queued), processing, retrying (a step failed and is retried automatically), or the final succeeded or failed (see error).
stagestringrequiredCurrent step: uploads, transcribing, generating, publishing, or complete once the operation succeeded.
errorobjectrequirednullableThe most recent failure, or null. While status is retrying it is the failure being retried; when status is failed it is final.
codestringrequiredMachine-readable failure code, for example waiting_for_uploads, no_speech, note_conflict, transcript_changed, access_revoked or audio_integrity.
messagestringrequiredExplanation of the failure that can be shown to the user.
resultAvailablebooleanrequiredWhether a generated note can be read from GET .../recording-operations/{operationId}/result, including one kept after a note_conflict instead of being published.
skippedChunksobjectrequiredChunks left out of the transcript, by chunk ID, with the reason: too_short, unreadable_input or no_speech for audio without usable speech, or transcription_failed for a chunk that kept failing transcription for about an hour. The other chunks are still used.
curl -X POST "https://vetnio.com/api/v2/workspaces/furunculotic-loud-chihuahua/consultations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/recording-operations" \
-H "Authorization: Bearer $VETNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"submission": {
"protocolVersion": 1,
"operationId": "0c9d8e7f-6a5b-4c3d-8e2f-1a0b9c8d7e6f",
"chunks": [
{
"id": "9b2f6c1e-3a4d-4f5e-8a7b-1c2d3e4f5a6b",
"sessionId": "5e1d2c3b-4a5f-4e6d-9c8b-7a6f5e4d3c2b",
"index": 0,
"recordedAt": 1759600000000,
"languageCode": "sv",
"size": 1048576,
"sha256": "4a1f0c6e3b2d9a8f7e6d5c4b3a2918070f1e2d3c4b5a69788776655443322110"
}
],
"generateClinicalNote": true,
"templateId": "string"
}
}'{
"operationId": "0c9d8e7f-6a5b-4c3d-8e2f-1a0b9c8d7e6f",
"status": "processing",
"stage": "transcribing",
"error": {
"code": "note_conflict",
"message": "The note changed during generation. Your edits were preserved. Generate the note again to include this recording."
},
"resultAvailable": false,
"skippedChunks": {}
}GET/workspaces/{workspaceId}/consultations/{consultationId}/recording-operations/{operationId}
Returns the current state of a submitted recording operation. Poll it, a few seconds apart, until status is succeeded or failed. Returns 404 when the consultation has no operation with this ID.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
operationIdstring (uuid)requiredThe operationId the recording operation was submitted with.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
operationIdstring (uuid)requiredThe submission's operationId.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
statusenumrequiredaccepted (queued), processing, retrying (a step failed and is retried automatically), or the final succeeded or failed (see error).
stagestringrequiredCurrent step: uploads, transcribing, generating, publishing, or complete once the operation succeeded.
errorobjectrequirednullableThe most recent failure, or null. While status is retrying it is the failure being retried; when status is failed it is final.
codestringrequiredMachine-readable failure code, for example waiting_for_uploads, no_speech, note_conflict, transcript_changed, access_revoked or audio_integrity.
messagestringrequiredExplanation of the failure that can be shown to the user.
resultAvailablebooleanrequiredWhether a generated note can be read from GET .../recording-operations/{operationId}/result, including one kept after a note_conflict instead of being published.
skippedChunksobjectrequiredChunks left out of the transcript, by chunk ID, with the reason: too_short, unreadable_input or no_speech for audio without usable speech, or transcription_failed for a chunk that kept failing transcription for about an hour. The other chunks are still used.
curl "https://vetnio.com/api/v2/workspaces/furunculotic-loud-chihuahua/consultations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/recording-operations/0c9d8e7f-6a5b-4c3d-8e2f-1a0b9c8d7e6f" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"operationId": "0c9d8e7f-6a5b-4c3d-8e2f-1a0b9c8d7e6f",
"status": "processing",
"stage": "transcribing",
"error": {
"code": "note_conflict",
"message": "The note changed during generation. Your edits were preserved. Generate the note again to include this recording."
},
"resultAvailable": false,
"skippedChunks": {}
}GET/workspaces/{workspaceId}/consultations/{consultationId}/recording-operations/{operationId}/result
Returns the clinical note an operation generated, including one kept after a note_conflict instead of replacing an edited note. Returns 404 until a note has been generated, and for operations that do not generate one.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
operationIdstring (uuid)requiredThe operationId the recording operation was submitted with.
matches `^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$`
contentstringrequiredThe generated clinical note: HTML for free-text notes, or a JSON document serialized as a string for structured templates.
isJsonDocumentbooleanrequiredtrue when content is a JSON document from a structured template.
jsonTemplateIdstringoptionalID of the structured template the document follows, for structured notes.
curl "https://vetnio.com/api/v2/workspaces/furunculotic-loud-chihuahua/consultations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/recording-operations/0c9d8e7f-6a5b-4c3d-8e2f-1a0b9c8d7e6f/result" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"content": "<p>Bella presented for annual vaccination...</p>",
"isJsonDocument": false,
"jsonTemplateId": "jtpl_123"
}GET/workspaces/{workspaceId}/consultations/{consultationId}/recording-upload-url
Returns a presigned URL for uploading one audio recording (one segment of the consultation). Upload it with PUT <recordingUploadUrl> and the raw audio bytes as the body; the URL is valid for 24 hours.
Request a new URL for every segment, just before uploading it. The recording ID (<epoch-ms>-<language>) is fixed when the URL is issued and recordings are transcribed in recording-ID order. A recording uploaded after a later-issued recording has already been transcribed is never transcribed, so do not fetch URLs ahead of time or upload segments out of order. Fetching a URL changes nothing until something is uploaded.
After each upload, Vetnio's audio processor updates the consultation's recording duration and the full-length audio used for exports; uploaded audio counts toward the clinic's recorded usage. Uploading does not start transcription: call POST .../transcriptions/start when the segments are uploaded. Returns 403 for archived consultations.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
recordingLanguageCodestringrequiredLanguage spoken in this recording, as a lowercase ISO 639 code such as en, sv or de, optionally followed by subtags (pt-BR). It becomes part of the recording ID and sets the transcription language for this segment, so segments of one consultation can differ. A value that is not a two- or three-letter code with optional subtags returns 400; use a supported language code. An empty value falls back to English.
matches `^(?:[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*)?$`
recordingUploadUrlstring (uri)requiredPresigned URL for uploading one audio recording with a single PUT request whose body is the raw file bytes (no multipart form, no extra headers required). Valid for 24 hours. Any audio format FFmpeg can decode is accepted, for example WebM/Opus, MP4/AAC, M4A, MP3 or WAV. The recording ID (<epoch-ms>-<language>) is fixed when the URL is issued, and recordings are transcribed in recording-ID order.
curl "https://vetnio.com/api/v2/workspaces/demo-north-clinic/consultations/bc0cf418-6503-46eb-9828-c83f8c193426/recording-upload-url?recordingLanguageCode=en" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"recordingUploadUrl": "https://storage.example.com/recordings/demo-north-clinic/bc0cf418-6503-46eb-9828-c83f8c193426/1791130040069-en?X-Amz-Expires=86400&X-Amz-Signature=…"
}GET/workspaces/{workspaceId}/consultations/{consultationId}/transcription
Returns the saved full transcript of a consultation as plain text, or an empty string if none has been saved. By default it returns immediately and does not start transcription: call POST .../transcriptions/start and poll GET .../consultations/{consultationId} until transcriptionStatus is completed or failed before reading it.
Set waitForTranscriptions=true to start transcription and wait for it in one call, using the same completion flow as document generation; this requires write access. Waiting is best effort: stale jobs, permanent failures, exhausted retries or the 10-minute limit can leave a partial transcript, and the response does not say which happened, so check transcriptionStatus afterwards. Set your HTTP client timeout above 10 minutes when waiting.
Any member of the workspace can read the transcript, including for archived consultations.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
waitForTranscriptionsboolean or enumoptionalWhen true, first starts transcription of any untranscribed recordings (retrying failed ones) and waits until they settle, then returns the transcript. Defaults to false, which returns the saved transcript immediately without starting anything. Waiting requires write access to the consultation (403 for archived consultations) and can hold the request open for up to 10 minutes.
transcriptionstringrequiredFull transcript as plain text, or an empty string if nothing has been transcribed yet. Built from the consultation's partial transcriptions in recording order, joined with a single space; text partial transcriptions are included verbatim. Within a recording, a change of speaker starts a new paragraph (blank line), but speakers are not labelled. Medical terms that the spelling check is very confident about are annotated inline as term (Suggestion?).
curl "https://vetnio.com/api/v2/workspaces/demo-north-clinic/consultations/dfd6e768-51dd-5fcb-a786-c6dffe511d5f/transcription" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"transcription": "This is a synthetic Vetnio demo recording, with no real patient information. Milo is a five year old Labrador here for an annual wellness visit. His owner reports a normal appetite, regular walks, and no recent vomiting or coughing. On the demo examination, Milo is bright and comfortable. His recorded weight is twenty eight point four kilograms. Mild dental plaque is noted. We discussed routine dental care and recorded the owner's questions. This visit is a fictional software test. No medication was prescribed."
}POST/workspaces/{workspaceId}/consultations/{consultationId}/transcriptions/start
Starts background transcription of every uploaded recording that has not been transcribed yet, in recording-ID order. Uploading audio does not start transcription by itself; call this after your uploads. The endpoint returns immediately with the number of recordings waiting; the work continues after the response. Poll GET .../consultations/{consultationId} until transcriptionStatus is completed or failed, then read GET .../transcription.
Safe to call repeatedly: transcribed recordings are skipped, recordings another call is already transcribing are not processed twice, and failed recordings are retried (up to 3 attempts in total). If transcriptionStatus is still processing after about 10 minutes, call it again; jobs that have been running for more than 5 minutes are picked up again. If nothing is waiting, recordingsProcessed is 0 and no work starts.
Transcription uses third-party speech-to-text and AI spelling correction. Any member of the workspace can start it; returns 403 for archived consultations.
AcceptsPersonal key
workspaceIdstringrequiredIdentifier of the clinic (workspace), as returned by GET /workspaces. The key's user must be a member of the clinic, or an admin of the organization it belongs to.
consultationIdstringrequiredIdentifier of the consultation (UUID), as returned when it was created or by GET /workspaces/{workspaceId}/consultations. It must belong to the clinic in workspaceId.
messagestringrequiredHuman-readable outcome: Transcription process started when work was started, or No untranscribed recordings found when there was nothing to do. Use recordingsProcessed rather than parsing this text.
recordingsProcessednumberrequiredNumber of recordings waiting for transcription when the call was made. 0 means nothing was started. Recordings that an earlier call is already transcribing are counted but not transcribed twice; recordings that failed permanently are not counted.
curl -X POST "https://vetnio.com/api/v2/workspaces/furunculotic-loud-chihuahua/consultations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/transcriptions/start" \
-H "Authorization: Bearer $VETNIO_API_KEY"{
"message": "Transcription process started",
"recordingsProcessed": 3
}