> For the complete documentation index, see [llms.txt](https://docs.concurrence.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.concurrence.com/developer-guide/platform-api/scribe/sessions.md).

# Sessions

List and retrieve provider-owned clinical documentation sessions with lifecycle state and transcript, note, summary, and coding artifact availability.

Sessions represent provider-owned clinical documentation encounters. Each session tracks its mode, lifecycle status, and artifact availability. Use the Scribe API base URL assigned to your deployment; these are not the Platform text-session WebSocket routes.

Read operations require `scribe:sessions:read_own`. Creating, updating, ending, cancelling, and controlling Zoom sessions require `scribe:sessions:write`, in addition to provider ownership and workspace access.

{% hint style="info" %}
Scribe has its own public OpenAPI schema and provider access boundary. Use the [Scribe HTTP Reference](https://docs.concurrence.com/api-reference/readme/scribe) for canonical operation contracts and [Capture to Finalized Note](/developer-guide/guides/scribe-capture-to-note.md) for the complete workflow. Use the Scribe deployment base assigned to your integration, separately from Platform text sessions.
{% endhint %}

## Session Object

Read the session schema in [Get Session](#get-session). Session lifecycle, capture mode, and individual artifact readiness describe different parts of the encounter.

### Artifact Availability

The `artifacts` object reports readiness for each artifact. Inspect the artifact's own [generation state](/developer-guide/platform-api/scribe/artifacts.md) before displaying a note or concluding that generation completed.

## List Sessions

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/sessions" method="get" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

Returns a paginated list of sessions owned by the authenticated provider, ordered by creation time (newest first).

### Query Parameters

Use the limit and continuation token in [List Sessions](#list-sessions); pass the returned continuation token unchanged for the next page.

### Response

Use the session items and pagination fields rendered in [List Sessions](#list-sessions).

### Example Request

```bash
curl -H "Authorization: Bearer {token}" \
  "$SCRIBE_API_BASE/v1/{workspace_id}/sessions?limit=10"
```

### Example Response

```json
{
  "items": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "status": "completed",
      "mode": "in_person",
      "external_appointment_id": "APT-12345",
      "started_at": "2026-07-15T10:00:00Z",
      "ended_at": "2026-07-15T10:30:00Z",
      "created_at": "2026-07-15T09:55:00Z",
      "updated_at": "2026-07-15T10:31:00Z",
      "artifacts": {
        "transcript": "available",
        "note": "available",
        "summary": "available",
        "codes": "available"
      }
    }
  ],
  "has_more": false,
  "continuation_token": null
}
```

## Get Session

```
GET /v1/{workspace_id}/sessions/{session_id}
```

Returns a single session owned by the authenticated provider.

### Path Parameters

Use the matching workspace and the provider-owned session identifier in [Get Session](#get-session).

### Response

Returns a session object (see schema above).

### Errors

| Status | Code        | Description                                                          |
| ------ | ----------- | -------------------------------------------------------------------- |
| 404    | `not_found` | Session does not exist or is not owned by the authenticated provider |

{% hint style="info" %}
**Cancelled sessions are excluded from list results.** The list sessions endpoint does not return sessions with a cancelled status. Cancelled sessions are also excluded when resolving the current session for an appointment. An appointment whose only sessions are cancelled appears with no linked session, the same as an appointment that has never had a session started.
{% endhint %}

## Create an In-Person Session

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/sessions" method="post" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

Create a provider-owned microphone session. The general create route accepts only `in_person` mode. Supply a canonical `visit_type`; the service resolves and pins the corresponding supported note template. A supplied `note_template` must match. A missing visit type returns `422 note_template_required`; an unsupported or mismatched selection returns `422 unsupported_note_template` before session creation.

The request also supports patient display-name fields, an optional appointment reference, metadata, and `external_id` for idempotency. Inspect the assigned Scribe schema for field constraints. A successful create returns the session with HTTP 201. Recording attachment and artifact generation are separate operations.

## Session Mode

Every session carries a `mode` that indicates the session modality:

| Value       | Description                                                                                                         |
| ----------- | ------------------------------------------------------------------------------------------------------------------- |
| `in_person` | An in-person microphone recording (default).                                                                        |
| `zoom`      | A Zoom meeting session. A practitioner may have at most one non-terminal Zoom session at a time within a workspace. |

The mode is fixed at creation. The general create-session route accepts `in_person`; use `POST /v1/{workspace_id}/zoom/sessions` for a Zoom session. PATCH does not change the mode.

## Session Lifecycle

{% hint style="info" %}
**In-person (mic) sessions.** In-person mic sessions now automatically receive post-visit note generation when they reach the review stage. Note generation is asynchronous. Inspect artifact availability separately from the session transition.
{% endhint %}

Sessions support explicit REST transitions in addition to streaming-driven state changes:

| Transition | Endpoint                                               | From States                           | To State    | Notes                                                                              |
| ---------- | ------------------------------------------------------ | ------------------------------------- | ----------- | ---------------------------------------------------------------------------------- |
| End        | `POST /v1/{workspace_id}/sessions/{session_id}/end`    | `created`, `in-progress`              | `in-review` | Refused with `409 session_streaming` while a streaming worker is attached.         |
| Cancel     | `POST /v1/{workspace_id}/sessions/{session_id}/cancel` | `created`, `in-progress`, `in-review` | `cancelled` | Compensation and abort path. Terminal sessions return `409 invalid_session_state`. |

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/sessions/{session\_id}/end" method="post" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/sessions/{session\_id}/cancel" method="post" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Update Session

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/sessions/{session\_id}" method="patch" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

Only fields present in the request body are written. Omission preserves a field; an accepted explicit null clears the corresponding nullable value. Mode remains fixed.

Use the operation above for accepted fields and constraints.

Returns the full refreshed session response. Changes to `visit_type` or `note_template` revalidate the supported pair. Changing the visit type also refreshes its checklist; that change is rejected for a terminal session.

## Create Session Idempotency

When `external_id` is supplied on create, it acts as a per-attempt idempotency key:

* **Matching fingerprint**: A repeated `external_id` with the same effective create parameters returns the existing session. Use the same request when retrying an ambiguous result.
* **Divergent fingerprint**: If the effective create parameters differ from the stored session, the endpoint returns `409` with error code `idempotency_key_conflict`. Generate a new `external_id` for a deliberately new session.

Omitting `external_id` or sending `null` does not supply an idempotency key. Creation remains subject to permissions, validation, and the active-Zoom-session guard.

## Conflict Error Codes

Session lifecycle and create endpoints return `409` responses with a stable machine-readable `code` in the error envelope:

| Code                         | Trigger                                                                     |
| ---------------------------- | --------------------------------------------------------------------------- |
| `idempotency_key_conflict`   | Create reused an `external_id` with a different request fingerprint.        |
| `active_zoom_session_exists` | A second non-terminal Zoom session was attempted for the same practitioner. |
| `session_streaming`          | End was called while a streaming worker is still attached.                  |
| `invalid_session_state`      | The session is not in a state that permits the requested transition.        |

## Zoom

### Zoom Session Lifecycle

The Scribe API manages the full Zoom capture lifecycle server-side. The browser provides a meeting link and disclosure preferences; it never handles Zoom access tokens or communicates with internal capture services.

#### Create a Zoom Session

Supply a canonical `visit_type` that resolves to a supported note template. If `note_template` is supplied, it must match that visit type. Missing or unsupported selections fail before a session is created, even though these fields are optional in the generated request model.

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/zoom/sessions" method="post" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

Creates a Zoom capture session in one call. The server validates the meeting link, confirms the provider has a connected Zoom account, creates the session, and dispatches the capture bot.

**Error responses:**

| Status | Code                         | Description                                                              |
| ------ | ---------------------------- | ------------------------------------------------------------------------ |
| 400    | `invalid_meeting_link`       | The meeting link is not a valid Zoom URL.                                |
| 409    | `active_zoom_session_exists` | The provider already has an active Zoom session.                         |
| 409    | `idempotency_key_conflict`   | The `external_id` was reused with different parameters.                  |
| 409    | `zoom_not_connected`         | The provider has not connected Zoom.                                     |
| 503    | `bot_dispatch_failed`        | Bot dispatch failed; the session was automatically cancelled. Retryable. |

#### Pause Zoom Bot

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/sessions/{session\_id}/zoom/pause" method="post" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

Pauses the capture bot bound to the session.

**Error responses:**

| Status | Code                 | Description                           |
| ------ | -------------------- | ------------------------------------- |
| 409    | `bot_not_active`     | No live bot is bound to this session. |
| 502    | `bot_command_failed` | The command could not be delivered.   |

#### Resume Zoom Bot

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/sessions/{session\_id}/zoom/resume" method="post" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

Resumes a paused capture bot. Same response and error contract as pause.

#### End Zoom Session

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/sessions/{session\_id}/zoom" method="delete" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

Ends a Zoom session. Returns immediately; the platform stops the bot and finalizes the transcript in the background. Inspect the session and artifact state for the eventual result; the 202 acknowledgement does not establish that finalization has completed.

Idempotent - a second delete returns 202 and is a no-op.

**Error responses:**

| Status | Code               | Description                        |
| ------ | ------------------ | ---------------------------------- |
| 409    | `not_zoom_session` | The session is not a Zoom session. |

### Zoom Connection

Providers can connect their Zoom account through the Scribe API. The platform manages the OAuth lifecycle server-side - the browser initiates the flow and reads connection status, but never handles token material.

### Endpoints

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/zoom/oauth/authorize" method="post" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/zoom/oauth/callback" method="get" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/zoom/connection" method="get" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://scribe.platform.amigo.ai/v1/openapi.json>" path="/v1/{workspace\_id}/zoom/connection" method="delete" %}
<https://scribe.platform.amigo.ai/v1/openapi.json>
{% endopenapi %}

The callback is the authorization redirect target and should not be called directly.

### Authorize Response

Navigate to the authorization URL returned by the [Zoom authorize operation](#endpoints) while it remains valid. The browser follows the consent flow; it does not handle provider token material.

### Connection Response

Read the [Zoom connection operation](#endpoints) to confirm the provider connection before creating a capture session. A connected account does not establish that a particular meeting is ready to capture.

### Error Handling

| Status | Condition                                                                                                                      |
| ------ | ------------------------------------------------------------------------------------------------------------------------------ |
| `401`  | Missing or invalid bearer token.                                                                                               |
| `403`  | Insufficient scope or provider mismatch.                                                                                       |
| `503`  | Zoom connect is temporarily unavailable (the authorize endpoint could not mint a verifiable state). Retry after a brief delay. |

The callback endpoint never returns JSON. Every outcome - success or failure - results in a 302 redirect to the configured web settings page with a `zoom_connected=true` or `zoom_error=<reason>` query parameter.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.concurrence.com/developer-guide/platform-api/scribe/sessions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
