> ## 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.

# Bulk Create Sessions

> Atomically create up to 100 non-recurring sessions in the organization that owns the API key. The batch is all-or-nothing: every element is validated with the same rules as a single create, and if any element fails, nothing is created and every failure is returned by index.

## Bulk Create Sessions

Create a batch of up to **100** non-recurring sessions (appointments) in a single request, in the organization that owns the API key.

The batch is **all-or-nothing**. Every element is validated with the exact same rules as [Create Session](/api-reference/endpoint/sessions/create). If **any** element fails validation, **nothing** is created and the response lists every failing session by its index in the `sessions` array. Only when all elements are valid are they created together inside one transaction.

### Headers

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

### Request

Wrap the sessions in a `sessions` array. Each item has the same shape and rules as the single create request (billable vs non-billable, time fields, field requirements). See [Create Session](/api-reference/endpoint/sessions/create) for the per-session contract.

* `sessions` — array, **1 to 100** items. Fewer than 1 or more than 100 is rejected with a schema validation error.

### Success Response (201)

The created sessions are returned in request order, with a convenience `count`.

```json theme={null}
{
  "sessions": [
    {
      "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"
    },
    {
      "publicId": "apt_6f7g8h9i0j",
      "title": "Jane Roe — Adaptive behavior treatment",
      "status": "CONFIRMED",
      "startTime": "2026-01-06T14:00:00.000Z",
      "endTime": "2026-01-06T15:00:00.000Z",
      "isSupervision": false,
      "isClientPresent": true,
      "placeOfService": "HOME",
      "locationId": "loc_1a2b3c",
      "technicianId": "usr_tech123",
      "clientId": "usr_client999",
      "isBillable": true,
      "isTelehealth": false,
      "clinicianId": "usr_clin456",
      "providerLocationId": "loc_9f8e7d",
      "services": "svc_1a2b3c"
    }
  ],
  "count": 2
}
```

### Error Responses

#### 400 - Bad Request

Two distinct shapes are returned under 400:

**Domain validation failure** — one or more sessions failed the same rules as single create (missing required fields for the chosen mode, `endTime` not after `startTime`, duration over 8 hours, 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, a technician on a non-technician service line, or a reference to an entity that does not exist in the organization). **Nothing is created.** Each failure is indexed:

```json theme={null}
{
  "error": "2 session(s) failed validation",
  "statusCode": 400,
  "errors": [
    {
      "index": 0,
      "code": "INVALID_TIME_RANGE",
      "message": "End time must be after start time."
    },
    {
      "index": 3,
      "code": "STAFF_NOT_FOUND",
      "message": "Staff member not found in this organization."
    }
  ]
}
```

**Schema validation failure** — the request body itself is malformed (missing `sessions`, empty array, more than 100 items, or a field with the wrong type):

```json theme={null}
{
  "message": "Validation Error",
  "statusCode": 400,
  "validationErrors": [
    {
      "code": "too_small",
      "path": ["sessions"],
      "message": "sessions must contain at least one session"
    }
  ]
}
```

Each entry's `path` is an array of segments; for a bad field inside a specific session it points at the item, for example `["sessions", 0, "technicianId"]`.

#### 401 - Unauthorized

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

#### 403 - Forbidden

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

## Examples

### cURL

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

### JavaScript Example

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

  const body = await response.json();

  if (!response.ok) {
    // On a domain validation failure, body.errors lists each failing session
    // by its index — nothing was created.
    throw new Error(body.error || body.message || "Bulk create failed");
  }

  return body; // { sessions: [...], count: N }
};

// Usage
try {
  const result = await createSessionsBulk([
    {
      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 ${result.count} sessions`);
} catch (error) {
  console.error("Error creating sessions:", error.message);
}
```


## OpenAPI

````yaml POST /v1/sessions/bulk
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/bulk:
    post:
      tags:
        - V1
      summary: Bulk create sessions
      description: >-
        Atomically create up to 100 non-recurring sessions in the organization
        that owns the API key. The batch is all-or-nothing: every element is
        validated with the same rules as a single create, and if any element
        fails, nothing is created and every failure is returned by index.
      operationId: post-v1-sessions-bulk
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSessionsBulkRequest'
      responses:
        '201':
          description: All sessions created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkSessionsResponse'
        '400':
          description: >-
            Bad Request. Either the request body failed schema validation, or
            one or more sessions failed domain validation. In the latter case
            nothing was created and each failing session is listed by its index
            in the request array.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/BulkValidationError'
                  - $ref: '#/components/schemas/ValidationError'
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '405':
          $ref: '#/components/responses/405'
        '500':
          $ref: '#/components/responses/500'
      security:
        - BearerAuth: []
components:
  schemas:
    CreateSessionsBulkRequest:
      type: object
      description: >-
        Payload for atomically creating a batch of non-recurring sessions. The
        batch is all-or-nothing: every element is validated with the exact same
        rules as a single create, and if any element fails, nothing is written
        and every failure is returned by index.
      properties:
        sessions:
          type: array
          minItems: 1
          maxItems: 100
          description: >-
            The sessions to create, 1 to 100 items. Each item has the same shape
            and rules as the single create request.
          items:
            $ref: '#/components/schemas/CreateSessionRequest'
      required:
        - sessions
    BulkSessionsResponse:
      type: object
      description: >-
        Result of a successful bulk create: the created sessions in request
        order plus the total count.
      properties:
        sessions:
          type: array
          items:
            $ref: '#/components/schemas/Session'
        count:
          type: integer
          description: Number of sessions created.
          example: 2
      required:
        - sessions
        - count
    BulkValidationError:
      type: object
      description: >-
        Returned when one or more elements of a bulk create fail validation.
        Because the batch is all-or-nothing, nothing was written; every
        offending element is listed by its index in the request array.
      properties:
        error:
          type: string
          example: 2 session(s) failed validation
        statusCode:
          type: integer
          example: 400
        errors:
          type: array
          items:
            type: object
            properties:
              index:
                type: integer
                description: Zero-based index of the failing session in the request array.
                example: 1
              code:
                type: string
                description: Machine-readable failure code.
                example: STAFF_NOT_FOUND
              message:
                type: string
                example: Staff member not found in this organization.
            required:
              - index
              - code
              - message
      required:
        - error
        - statusCode
        - errors
    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
    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
    ApiErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Human-readable error message
          example: User not found
        statusCode:
          type: integer
          example: 404
      required:
        - error
        - statusCode
    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
    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:
    '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>'

````