---
title: "Create a new consultation"
method: POST
path: "/workspaces/{workspaceId}/consultations"
tags: ["consultations"]
---

# Create a new consultation

`POST /workspaces/{workspaceId}/consultations`

## Request

- Base URL: `https://vetnio.com/api/v2`
- URL: `https://vetnio.com/api/v2/workspaces/{workspaceId}/consultations`
- Auth: HTTP bearer

Creates a consultation owned by the authenticated user and returns a presigned URL for uploading its first audio recording.

With `externalId`, the call is an upsert: if an active consultation in the workspace already has that `externalId`, it is returned unchanged (with a fresh upload URL) and nothing is created. Without `externalId` or `clientConsultationId`, every call creates a new consultation, so retrying a request that timed out can create duplicates. With `clientConsultationId`, retries return the consultation the first request created, and an ID that belongs to another consultation returns `409`.

Creating a consultation does not record or transcribe anything. Next steps: `PUT` audio to `recordingUploadUrl`, then call `POST .../transcriptions/start`. The first consultation in a workspace that is waiting to start its free trial starts the trial.

## Path parameters

- `workspaceId` string, required: Identifier 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.

## Request body

- object
  - `clientConsultationId` string, uuid: Client-generated UUID that makes creation idempotent. Retrying with the same ID returns the consultation the original request created for the same workspace and user; an ID that belongs to any other consultation returns `409`. With `externalId`, an existing consultation for that `externalId` still takes precedence, and the ID is used when a new consultation is created.
  - `name` string, required: Display name for the consultation, typically the patient's name and the reason for the visit. Free text; not validated (an empty string is accepted).
  - `recordingLanguageCode` string, required: Language spoken in the consultation, as a lowercase ISO 639 code such as `en`, `sv` or `de`, optionally followed by subtags (`pt-BR`). Stored on the consultation and embedded in the returned upload URL's recording ID, which sets the transcription language of that first recording. A value that is not a two- or three-letter code with optional subtags returns `400`; use a supported language code.
  - `externalId` string: Identifier of the matching visit in your practice-management system. If an active (not archived or deleted) consultation in this workspace already has this `externalId`, that consultation is returned unchanged instead of creating a new one, whoever created it; `name` and `recordingLanguageCode` are then not applied. When `externalId` is set, `clinicalNoteTemplateId` is ignored, even if a new consultation is created.
  - `clinicalNoteTemplateId` string: ID of the clinical note template to use when generating this consultation's note. An unknown ID, or `auto`, is ignored and the consultation is created without a template. If the template is linked to a JSON template, that structured template is bound as well. Ignored when `externalId` is provided.

## Response `200`

The created (or matched) consultation with an upload URL for its first recording.

- ConsultationCreated: The new (or matched) consultation plus a presigned URL for uploading its first recording.
  - `consultationId` string, required: ID of the consultation that was created, or of the existing consultation returned because its `externalId` matched.
  - `recordingUploadUrl` string, uri, required: Presigned URL for uploading the first audio recording with `PUT` (raw bytes as the body), valid for 24 hours. It behaves exactly like a URL from `GET .../recording-upload-url`: its recording ID is fixed now, so upload promptly and fetch a new URL for each further segment.
  - `consultation` object, required: Summary of the created (or matched) consultation. Fetch `GET .../consultations/{consultationId}` for status fields.
    - `id` string, required: Consultation ID (UUID); same as `consultationId`.
    - `name` string, required: Display name. When an existing consultation was returned, this is its stored name, not the name in the request.
    - `createdAt` string, required: When the consultation was created, as an ISO-8601 UTC timestamp.
    - `recordingDurationInMilliseconds` number, required: Total length of all audio uploaded to the consultation, in milliseconds, including silence. Vetnio's audio processor updates it shortly after each upload; it is `0` until the first upload has been processed. `0` for a new consultation.
    - `uploadedRecordingDurationInMilliseconds` number, required: Same value as `recordingDurationInMilliseconds`.
    - `isGeneratingClinicalNote` boolean, required: `true` while Vetnio is generating the clinical note for this consultation; set back to `false` when generation ends. Poll it to detect when a requested note is ready.
    - `isGeneratingCommunication` boolean, required: `true` while Vetnio is generating the owner communication (the client-facing summary) for this consultation; set back to `false` when generation ends.
    - `externalId` string, nullable, required: Identifier of the matching visit or consultation in the clinic's practice-management system, or `null` if the consultation is not linked to one. Free text; not unique.

## Other responses

- `400`: Invalid input data
- `401`: Authorization not provided
- `403`: Insufficient access
- `500`: Internal server error

---

[API](https://skmtc.dev/vetnio/apis/vetnio-api.md) - [All operations](https://skmtc.dev/vetnio/apis/vetnio-api/llms.txt) - [OpenAPI document](https://skmtc.dev/vetnio/apis/vetnio-api/revisions/d004afd5617d?raw)
