> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hipp.health/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Session

> Create a single (non-recurring) session (appointment) in the organization that owns the API key. A session is either billable (provide services) or non-billable (provide nonBillableCodeId).

## Create Session

Create a single (non-recurring) session (appointment) in the organization that owns the API key. All referenced entities (staff, client, clinician, location, provider location, non-billable code, service lines) must belong to that organization.

### Headers

```
Authorization: Bearer <your-api-key>
Content-Type: application/json
```

### Billable vs non-billable

A session is **either** billable **or** non-billable — exactly one, never both and never neither:

* **Billable**: provide `services` (a single service line public id). `clientId` and `clinicianId` are required.
* **Non-billable**: provide `nonBillableCodeId` instead. When `isSupervision` is `true`, `clinicianId` is required; for a standard (non-supervision) non-billable session `clinicianId` must **not** be provided.

### Time fields

`date`, `startTime`, `endTime` and `timezone` are combined server-side into UTC instants:

* `date` — `YYYY-MM-DD`. Must be a real calendar date; invalid days such as `2026-02-30` are rejected rather than shifted.
* `startTime` / `endTime` — `HH:mm` or `HH:mm:ss`
* `timezone` — IANA zone (for example `America/New_York`)

`endTime` must be after `startTime`, and the total duration must not exceed 8 hours (compared at second precision).

### Field Requirements

| Field                                      | Required                              | Notes                                                                                                                                                      |
| ------------------------------------------ | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `technicianId`                             | Always                                | Must be a staff member (technician, clinician, clinical admin or clinical superadmin). A technician can only be assigned to technician-only service lines. |
| `date`, `startTime`, `endTime`, `timezone` | Always                                | Combined into UTC instants.                                                                                                                                |
| `locationId`                               | Always                                | Session location.                                                                                                                                          |
| `placeOfService`                           | Always                                | Must be allowed by the service line on the session.                                                                                                        |
| `services`                                 | Billable only                         | Single service line public id. Mutually exclusive with `nonBillableCodeId`.                                                                                |
| `nonBillableCodeId`                        | Non-billable only                     | Mutually exclusive with `services`.                                                                                                                        |
| `clientId`                                 | Billable                              | Must reference a patient.                                                                                                                                  |
| `clinicianId`                              | Billable, or non-billable supervision | Must reference a clinician or clinical admin. Rejected on standard (non-supervision) non-billable sessions.                                                |
| `providerLocationId`                       | Telehealth                            | Required when `isTelehealth` is `true`.                                                                                                                    |
| `isTelehealth`                             | Optional                              | Billable only. Defaults to `false`.                                                                                                                        |
| `isSupervision`                            | Optional                              | Defaults to `false`.                                                                                                                                       |
| `isClientPresent`                          | Optional                              | Defaults to `true`.                                                                                                                                        |
| `title`                                    | Optional                              | Custom title.                                                                                                                                              |
| `status`                                   | Optional                              | Scheduling status of the new session. Defaults to `CONFIRMED`. See [Session status](#session-status).                                                      |

### Session status

`status` sets the scheduling status the session is created with.

* Allowed values: `CONFIRMED`, `UNCONFIRMED`, `DECLINED`, `PATIENT_NO_SHOW`, `REQUESTED_TO_CANCEL`.
* Omit it and the session is created **`CONFIRMED`**, so a session booked through the API behaves like one booked in the app. To create a session that still needs confirming, send `"status": "UNCONFIRMED"` explicitly.
* Values are matched exactly (uppercase). Any other value returns a `400`.

The created session response includes its current `status`.

### Success Response (201)

The response shape depends on `isBillable`. A **billable** session exposes `isTelehealth`, `clinicianId`, `providerLocationId` and `services` (and never `nonBillableCode`):

```json theme={null}
{
  "publicId": "apt_1a2b3c4d5e",
  "title": "John Doe — Adaptive behavior treatment",
  "status": "CONFIRMED",
  "startTime": "2026-01-05T14:00:00.000Z",
  "endTime": "2026-01-05T15:00:00.000Z",
  "isSupervision": false,
  "isClientPresent": true,
  "placeOfService": "HOME",
  "locationId": "loc_1a2b3c",
  "technicianId": "usr_tech123",
  "clientId": "usr_client789",
  "isBillable": true,
  "isTelehealth": false,
  "clinicianId": "usr_clin456",
  "providerLocationId": "loc_9f8e7d",
  "services": "svc_1a2b3c"
}
```

A **non-billable** session exposes `nonBillableCode` instead (and omits `isTelehealth`, `clinicianId` and `services`):

```json theme={null}
{
  "publicId": "apt_9z8y7x",
  "title": "Travel",
  "status": "CONFIRMED",
  "startTime": "2026-01-05T12:00:00.000Z",
  "endTime": "2026-01-05T12:30:00.000Z",
  "isSupervision": false,
  "isClientPresent": false,
  "placeOfService": "OTHER",
  "locationId": "loc_1a2b3c",
  "technicianId": "usr_tech123",
  "clientId": null,
  "isBillable": false,
  "nonBillableCode": "nbc_1a2b3c"
}
```

<Warning>
  **Known limitation.** A non-billable **supervision** session does store the
  `clinicianId` you send, but the non-billable response shape omits
  `clinicianId` entirely — so reading the session back shows no clinician even
  though one is set. This is a defect, not intended behaviour; do not rely on
  the absence of `clinicianId` to mean a session has no clinician.
</Warning>

### Error Responses

#### 400 - Bad Request

Returned for validation failures (missing required fields for the chosen mode, `endTime` not after `startTime`, total duration over 8 hours, an invalid calendar date, place of service not allowed by a service line, a `technicianId` whose role cannot deliver a session, a `clientId` that is not a patient, a `clinicianId` that is not a clinical role, or a technician assigned to a non-technician service line) and for references to entities that do not exist in the organization.

Business-rule failures (the billable/non-billable, telehealth, time, place-of-service, staff-role and referenced-entity rules above) are returned as a plain error:

```json theme={null}
{
  "error": "clientId is required for billable sessions (with services).",
  "statusCode": 400
}
```

Malformed field input caught before the business rules (bad enum, empty string, wrong type, invalid date pattern) is returned as a validation list, where each `path` is an array of segments:

```json theme={null}
{
  "message": "Validation Error",
  "statusCode": 400,
  "validationErrors": [
    {
      "code": "invalid_enum_value",
      "path": ["placeOfService"],
      "message": "Invalid enum value."
    }
  ]
}
```

#### 401 - Unauthorized

```json theme={null}
{
  "error": "API key required",
  "statusCode": 401
}
```

#### 403 - Forbidden

```json theme={null}
{
  "error": "Access denied",
  "statusCode": 403
}
```

## Examples

### Billable session (cURL)

```bash theme={null}
curl -X POST "https://app.hipp.health/api/v1/sessions" \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "technicianId": "usr_tech123",
    "clientId": "usr_client789",
    "clinicianId": "usr_clin456",
    "date": "2026-01-05",
    "startTime": "09:00",
    "endTime": "10:00",
    "timezone": "America/New_York",
    "locationId": "loc_1a2b3c",
    "services": "svc_1a2b3c",
    "placeOfService": "HOME"
  }'
```

### Non-billable session (cURL)

```bash theme={null}
curl -X POST "https://app.hipp.health/api/v1/sessions" \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "technicianId": "usr_tech123",
    "date": "2026-01-05",
    "startTime": "12:00",
    "endTime": "12:30",
    "timezone": "America/New_York",
    "locationId": "loc_1a2b3c",
    "nonBillableCodeId": "nbc_1a2b3c",
    "placeOfService": "OTHER"
  }'
```

### JavaScript Example

```javascript theme={null}
const createSession = async (payload) => {
  const response = await fetch("https://app.hipp.health/api/v1/sessions", {
    method: "POST",
    headers: {
      Authorization: "Bearer your-api-key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error || error.message || "Failed to create session");
  }

  return response.json();
};

// Usage
try {
  const session = await createSession({
    technicianId: "usr_tech123",
    clientId: "usr_client789",
    clinicianId: "usr_clin456",
    date: "2026-01-05",
    startTime: "09:00",
    endTime: "10:00",
    timezone: "America/New_York",
    locationId: "loc_1a2b3c",
    services: "svc_1a2b3c",
    placeOfService: "HOME",
  });
  console.log("Created session:", session);
} catch (error) {
  console.error("Error creating session:", error.message);
}
```


## OpenAPI

````yaml POST /v1/sessions
openapi: 3.0.0
info:
  title: Hipp Health API
  version: 1.0.0
  description: API for managing users and resources within your Hipp Health organization
servers:
  - url: https://app.hipp.health/api
    description: Production Server
security: []
paths:
  /v1/sessions:
    post:
      tags:
        - V1
      summary: Create session
      description: >-
        Create a single (non-recurring) session (appointment) in the
        organization that owns the API key. A session is either billable
        (provide services) or non-billable (provide nonBillableCodeId).
      operationId: post-v1-sessions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSessionRequest'
      responses:
        '201':
          description: Session created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Session'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '405':
          $ref: '#/components/responses/405'
        '500':
          $ref: '#/components/responses/500'
      security:
        - BearerAuth: []
components:
  schemas:
    CreateSessionRequest:
      type: object
      description: >-
        Payload for creating a single (non-recurring) session. A session is
        either billable (provide services) or non-billable (provide
        nonBillableCodeId) — exactly one, never both.
      properties:
        technicianId:
          type: string
          minLength: 1
          description: >-
            Public id of the staff member delivering the session. Must be a
            staff role (TECHNICIAN, CLINICIAN, CLINICAL_ADMIN or
            CLINICAL_SUPERADMIN); clients and other roles are rejected. A
            TECHNICIAN can only be assigned to technician-only service lines.
          example: usr_tech123
        clientId:
          type: string
          minLength: 1
          description: >-
            Public id of the client. Must reference a patient. Required for
            billable sessions.
          example: usr_client789
        clinicianId:
          type: string
          minLength: 1
          description: >-
            Public id of the clinician. Must reference a clinician or clinical
            admin. Required for billable sessions and for non-billable
            supervision sessions. Must NOT be provided for standard
            (non-supervision) non-billable sessions.
          example: usr_clin456
        date:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: >-
            Calendar date of the session (YYYY-MM-DD). Must be a real calendar
            date (e.g. 2026-02-30 is rejected). Combined with startTime/endTime
            in the given timezone to derive UTC instants.
          example: '2026-01-05'
        startTime:
          type: string
          pattern: ^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$
          description: Wall-clock start time (HH:mm or HH:mm:ss) in the given timezone.
          example: '09:00'
        endTime:
          type: string
          pattern: ^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$
          description: >-
            Wall-clock end time (HH:mm or HH:mm:ss) in the given timezone. Must
            be after startTime, and the total duration (compared at second
            precision) must not exceed 8 hours.
          example: '10:00'
        timezone:
          type: string
          minLength: 1
          description: IANA timezone used to interpret date/startTime/endTime.
          example: America/New_York
        locationId:
          type: string
          minLength: 1
          description: Public id of the session location.
          example: loc_1a2b3c
        providerLocationId:
          type: string
          minLength: 1
          description: >-
            Public id of the location the provider delivers from. Required when
            isTelehealth is true.
          example: loc_9x8y7z
        services:
          type: string
          minLength: 1
          description: >-
            Public id of the billable service line. Provide for billable
            sessions; omit for non-billable sessions. The session location's
            place of service must be allowed by the service line.
          example: svc_1a2b3c
        nonBillableCodeId:
          type: string
          minLength: 1
          description: >-
            Public id of the non-billable code. Provide for non-billable
            sessions instead of services.
          example: nbc_1a2b3c
        placeOfService:
          $ref: '#/components/schemas/PlaceOfServiceCode'
        isTelehealth:
          type: boolean
          default: false
          description: >-
            Whether the session is delivered via telehealth. Only allowed on
            billable sessions and requires providerLocationId.
        isSupervision:
          type: boolean
          default: false
          description: >-
            Whether the session is a supervision session. For non-billable
            supervision, clinicianId is required.
        isClientPresent:
          type: boolean
          default: true
          description: Whether the client is present for the session.
        title:
          type: string
          minLength: 1
          description: >-
            Optional custom title. Defaults to the client name, the non-billable
            code name, or a placeholder.
        status:
          allOf:
            - $ref: '#/components/schemas/AppointmentStatus'
          default: CONFIRMED
          description: >-
            Scheduling status the session is created with. Defaults to
            CONFIRMED, so a session booked through the API behaves like one
            booked in the app. Matched exactly (uppercase); any other value
            returns a 400.
      required:
        - technicianId
        - date
        - startTime
        - endTime
        - timezone
        - locationId
        - placeOfService
    Session:
      description: >-
        A scheduled session (appointment). The shape depends on isBillable:
        billable sessions expose isTelehealth, clinicianId and services;
        non-billable sessions expose nonBillableCode instead.
      oneOf:
        - $ref: '#/components/schemas/BillableSession'
        - $ref: '#/components/schemas/NonBillableSession'
      discriminator:
        propertyName: isBillable
    PlaceOfServiceCode:
      type: string
      enum:
        - TELEHEALTH_PROVIDED_ELSEWHERE
        - TELEHEALTH_PROVIDED_IN_PATIENT_HOME
        - OFFICE
        - HOME
        - SCHOOL
        - OTHER
        - TEMPORARY_LODGING
        - PLACE_OF_EMPLOYMENT
        - COMMUNITY_MENTAL_HEALTH_CENTER
      description: CMS place-of-service classification for the session
    AppointmentStatus:
      type: string
      enum:
        - CONFIRMED
        - UNCONFIRMED
        - DECLINED
        - PATIENT_NO_SHOW
        - REQUESTED_TO_CANCEL
      description: >-
        Scheduling status of the session. Matched exactly (uppercase); any other
        value returns a 400.
    BillableSession:
      allOf:
        - $ref: '#/components/schemas/SessionBase'
        - type: object
          properties:
            isBillable:
              type: boolean
              enum:
                - true
              description: Always true for billable sessions.
            isTelehealth:
              type: boolean
              example: false
            clinicianId:
              type: string
              nullable: true
              description: Public id of the assigned clinician, if any.
              example: usr_clin456
            providerLocationId:
              type: string
              nullable: true
              description: >-
                Public id of the provider location the care was delivered from,
                if any.
              example: loc_9f8e7d
            services:
              type: string
              description: >-
                Public id of the billable service line rendered. A session bills
                exactly one service line.
              example: svc_1a2b3c
          required:
            - isBillable
            - isTelehealth
            - clinicianId
            - providerLocationId
            - services
    NonBillableSession:
      allOf:
        - $ref: '#/components/schemas/SessionBase'
        - type: object
          properties:
            isBillable:
              type: boolean
              enum:
                - false
              description: Always false for non-billable sessions.
            nonBillableCode:
              type: string
              description: Public id of the non-billable code.
              example: nbc_1a2b3c
          required:
            - isBillable
            - nonBillableCode
    ValidationError:
      type: object
      required:
        - message
        - statusCode
        - validationErrors
      properties:
        message:
          type: string
          example: Validation Error
        statusCode:
          type: integer
          example: 400
        validationErrors:
          type: array
          description: Zod validation issues
          items:
            type: object
            properties:
              code:
                type: string
                example: invalid_type
              message:
                type: string
                example: Required
              path:
                type: array
                items:
                  oneOf:
                    - type: string
                    - type: integer
                example:
                  - email
    ApiErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Human-readable error message
          example: User not found
        statusCode:
          type: integer
          example: 404
      required:
        - error
        - statusCode
    SessionBase:
      type: object
      properties:
        publicId:
          type: string
          example: apt_1a2b3c4d5e
        title:
          type: string
          example: John Doe — Adaptive behavior treatment
        status:
          $ref: '#/components/schemas/AppointmentStatus'
        startTime:
          type: string
          format: date-time
          description: Session start instant in UTC (ISO-8601).
          example: '2026-01-05T14:00:00.000Z'
        endTime:
          type: string
          format: date-time
          description: Session end instant in UTC (ISO-8601).
          example: '2026-01-05T15:00:00.000Z'
        isSupervision:
          type: boolean
          example: false
        isClientPresent:
          type: boolean
          example: true
        placeOfService:
          $ref: '#/components/schemas/PlaceOfServiceCode'
        locationId:
          type: string
          description: Public id of the session location.
          example: loc_1a2b3c
        technicianId:
          type: string
          nullable: true
          description: Public id of the assigned technician, if any.
          example: usr_tech123
        clientId:
          type: string
          nullable: true
          description: Public id of the client, if any.
          example: usr_client789
      required:
        - publicId
        - title
        - status
        - startTime
        - endTime
        - isSupervision
        - isClientPresent
        - placeOfService
        - locationId
        - technicianId
        - clientId
  responses:
    '400':
      description: Bad Request - Validation Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationError'
    '401':
      description: Unauthorized - API key required
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            error: API key required
            statusCode: 401
    '403':
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            error: Access denied
            statusCode: 403
    '405':
      description: Method Not Allowed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            error: Method not allowed
            statusCode: 405
    '500':
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
          example:
            error: An unexpected error occurred
            statusCode: 500
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        API key authentication. Include your API key in the Authorization header
        as 'Bearer <your-api-key>'

````