curl --request POST \
--url https://app.hipp.health/api/v1/sessions/bulk \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"sessions": [
{
"technicianId": "usr_tech123",
"date": "2026-01-05",
"startTime": "09:00",
"endTime": "10:00",
"timezone": "America/New_York",
"locationId": "loc_1a2b3c",
"clientId": "usr_client789",
"clinicianId": "usr_clin456",
"providerLocationId": "loc_9x8y7z",
"services": "svc_1a2b3c",
"nonBillableCodeId": "nbc_1a2b3c",
"isTelehealth": false,
"isSupervision": false,
"isClientPresent": true,
"title": "<string>",
"status": "CONFIRMED"
}
]
}
'import requests
url = "https://app.hipp.health/api/v1/sessions/bulk"
payload = { "sessions": [
{
"technicianId": "usr_tech123",
"date": "2026-01-05",
"startTime": "09:00",
"endTime": "10:00",
"timezone": "America/New_York",
"locationId": "loc_1a2b3c",
"clientId": "usr_client789",
"clinicianId": "usr_clin456",
"providerLocationId": "loc_9x8y7z",
"services": "svc_1a2b3c",
"nonBillableCodeId": "nbc_1a2b3c",
"isTelehealth": False,
"isSupervision": False,
"isClientPresent": True,
"title": "<string>",
"status": "CONFIRMED"
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
sessions: [
{
technicianId: 'usr_tech123',
date: '2026-01-05',
startTime: '09:00',
endTime: '10:00',
timezone: 'America/New_York',
locationId: 'loc_1a2b3c',
clientId: 'usr_client789',
clinicianId: 'usr_clin456',
providerLocationId: 'loc_9x8y7z',
services: 'svc_1a2b3c',
nonBillableCodeId: 'nbc_1a2b3c',
isTelehealth: false,
isSupervision: false,
isClientPresent: true,
title: '<string>',
status: 'CONFIRMED'
}
]
})
};
fetch('https://app.hipp.health/api/v1/sessions/bulk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.hipp.health/api/v1/sessions/bulk",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'sessions' => [
[
'technicianId' => 'usr_tech123',
'date' => '2026-01-05',
'startTime' => '09:00',
'endTime' => '10:00',
'timezone' => 'America/New_York',
'locationId' => 'loc_1a2b3c',
'clientId' => 'usr_client789',
'clinicianId' => 'usr_clin456',
'providerLocationId' => 'loc_9x8y7z',
'services' => 'svc_1a2b3c',
'nonBillableCodeId' => 'nbc_1a2b3c',
'isTelehealth' => false,
'isSupervision' => false,
'isClientPresent' => true,
'title' => '<string>',
'status' => 'CONFIRMED'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.hipp.health/api/v1/sessions/bulk"
payload := strings.NewReader("{\n \"sessions\": [\n {\n \"technicianId\": \"usr_tech123\",\n \"date\": \"2026-01-05\",\n \"startTime\": \"09:00\",\n \"endTime\": \"10:00\",\n \"timezone\": \"America/New_York\",\n \"locationId\": \"loc_1a2b3c\",\n \"clientId\": \"usr_client789\",\n \"clinicianId\": \"usr_clin456\",\n \"providerLocationId\": \"loc_9x8y7z\",\n \"services\": \"svc_1a2b3c\",\n \"nonBillableCodeId\": \"nbc_1a2b3c\",\n \"isTelehealth\": false,\n \"isSupervision\": false,\n \"isClientPresent\": true,\n \"title\": \"<string>\",\n \"status\": \"CONFIRMED\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.hipp.health/api/v1/sessions/bulk")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"sessions\": [\n {\n \"technicianId\": \"usr_tech123\",\n \"date\": \"2026-01-05\",\n \"startTime\": \"09:00\",\n \"endTime\": \"10:00\",\n \"timezone\": \"America/New_York\",\n \"locationId\": \"loc_1a2b3c\",\n \"clientId\": \"usr_client789\",\n \"clinicianId\": \"usr_clin456\",\n \"providerLocationId\": \"loc_9x8y7z\",\n \"services\": \"svc_1a2b3c\",\n \"nonBillableCodeId\": \"nbc_1a2b3c\",\n \"isTelehealth\": false,\n \"isSupervision\": false,\n \"isClientPresent\": true,\n \"title\": \"<string>\",\n \"status\": \"CONFIRMED\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.hipp.health/api/v1/sessions/bulk")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"sessions\": [\n {\n \"technicianId\": \"usr_tech123\",\n \"date\": \"2026-01-05\",\n \"startTime\": \"09:00\",\n \"endTime\": \"10:00\",\n \"timezone\": \"America/New_York\",\n \"locationId\": \"loc_1a2b3c\",\n \"clientId\": \"usr_client789\",\n \"clinicianId\": \"usr_clin456\",\n \"providerLocationId\": \"loc_9x8y7z\",\n \"services\": \"svc_1a2b3c\",\n \"nonBillableCodeId\": \"nbc_1a2b3c\",\n \"isTelehealth\": false,\n \"isSupervision\": false,\n \"isClientPresent\": true,\n \"title\": \"<string>\",\n \"status\": \"CONFIRMED\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"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": "TELEHEALTH_PROVIDED_ELSEWHERE",
"locationId": "loc_1a2b3c",
"technicianId": "usr_tech123",
"clientId": "usr_client789",
"isBillable": true,
"isTelehealth": false,
"clinicianId": "usr_clin456",
"providerLocationId": "loc_9f8e7d",
"services": "svc_1a2b3c"
}
],
"count": 2
}{
"error": "2 session(s) failed validation",
"statusCode": 400,
"errors": [
{
"index": 1,
"code": "STAFF_NOT_FOUND",
"message": "Staff member not found in this organization."
}
]
}{
"error": "API key required",
"statusCode": 401
}{
"error": "Access denied",
"statusCode": 403
}{
"error": "Method not allowed",
"statusCode": 405
}{
"error": "An unexpected error occurred",
"statusCode": 500
}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.
curl --request POST \
--url https://app.hipp.health/api/v1/sessions/bulk \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"sessions": [
{
"technicianId": "usr_tech123",
"date": "2026-01-05",
"startTime": "09:00",
"endTime": "10:00",
"timezone": "America/New_York",
"locationId": "loc_1a2b3c",
"clientId": "usr_client789",
"clinicianId": "usr_clin456",
"providerLocationId": "loc_9x8y7z",
"services": "svc_1a2b3c",
"nonBillableCodeId": "nbc_1a2b3c",
"isTelehealth": false,
"isSupervision": false,
"isClientPresent": true,
"title": "<string>",
"status": "CONFIRMED"
}
]
}
'import requests
url = "https://app.hipp.health/api/v1/sessions/bulk"
payload = { "sessions": [
{
"technicianId": "usr_tech123",
"date": "2026-01-05",
"startTime": "09:00",
"endTime": "10:00",
"timezone": "America/New_York",
"locationId": "loc_1a2b3c",
"clientId": "usr_client789",
"clinicianId": "usr_clin456",
"providerLocationId": "loc_9x8y7z",
"services": "svc_1a2b3c",
"nonBillableCodeId": "nbc_1a2b3c",
"isTelehealth": False,
"isSupervision": False,
"isClientPresent": True,
"title": "<string>",
"status": "CONFIRMED"
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
sessions: [
{
technicianId: 'usr_tech123',
date: '2026-01-05',
startTime: '09:00',
endTime: '10:00',
timezone: 'America/New_York',
locationId: 'loc_1a2b3c',
clientId: 'usr_client789',
clinicianId: 'usr_clin456',
providerLocationId: 'loc_9x8y7z',
services: 'svc_1a2b3c',
nonBillableCodeId: 'nbc_1a2b3c',
isTelehealth: false,
isSupervision: false,
isClientPresent: true,
title: '<string>',
status: 'CONFIRMED'
}
]
})
};
fetch('https://app.hipp.health/api/v1/sessions/bulk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.hipp.health/api/v1/sessions/bulk",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'sessions' => [
[
'technicianId' => 'usr_tech123',
'date' => '2026-01-05',
'startTime' => '09:00',
'endTime' => '10:00',
'timezone' => 'America/New_York',
'locationId' => 'loc_1a2b3c',
'clientId' => 'usr_client789',
'clinicianId' => 'usr_clin456',
'providerLocationId' => 'loc_9x8y7z',
'services' => 'svc_1a2b3c',
'nonBillableCodeId' => 'nbc_1a2b3c',
'isTelehealth' => false,
'isSupervision' => false,
'isClientPresent' => true,
'title' => '<string>',
'status' => 'CONFIRMED'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.hipp.health/api/v1/sessions/bulk"
payload := strings.NewReader("{\n \"sessions\": [\n {\n \"technicianId\": \"usr_tech123\",\n \"date\": \"2026-01-05\",\n \"startTime\": \"09:00\",\n \"endTime\": \"10:00\",\n \"timezone\": \"America/New_York\",\n \"locationId\": \"loc_1a2b3c\",\n \"clientId\": \"usr_client789\",\n \"clinicianId\": \"usr_clin456\",\n \"providerLocationId\": \"loc_9x8y7z\",\n \"services\": \"svc_1a2b3c\",\n \"nonBillableCodeId\": \"nbc_1a2b3c\",\n \"isTelehealth\": false,\n \"isSupervision\": false,\n \"isClientPresent\": true,\n \"title\": \"<string>\",\n \"status\": \"CONFIRMED\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.hipp.health/api/v1/sessions/bulk")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"sessions\": [\n {\n \"technicianId\": \"usr_tech123\",\n \"date\": \"2026-01-05\",\n \"startTime\": \"09:00\",\n \"endTime\": \"10:00\",\n \"timezone\": \"America/New_York\",\n \"locationId\": \"loc_1a2b3c\",\n \"clientId\": \"usr_client789\",\n \"clinicianId\": \"usr_clin456\",\n \"providerLocationId\": \"loc_9x8y7z\",\n \"services\": \"svc_1a2b3c\",\n \"nonBillableCodeId\": \"nbc_1a2b3c\",\n \"isTelehealth\": false,\n \"isSupervision\": false,\n \"isClientPresent\": true,\n \"title\": \"<string>\",\n \"status\": \"CONFIRMED\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.hipp.health/api/v1/sessions/bulk")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"sessions\": [\n {\n \"technicianId\": \"usr_tech123\",\n \"date\": \"2026-01-05\",\n \"startTime\": \"09:00\",\n \"endTime\": \"10:00\",\n \"timezone\": \"America/New_York\",\n \"locationId\": \"loc_1a2b3c\",\n \"clientId\": \"usr_client789\",\n \"clinicianId\": \"usr_clin456\",\n \"providerLocationId\": \"loc_9x8y7z\",\n \"services\": \"svc_1a2b3c\",\n \"nonBillableCodeId\": \"nbc_1a2b3c\",\n \"isTelehealth\": false,\n \"isSupervision\": false,\n \"isClientPresent\": true,\n \"title\": \"<string>\",\n \"status\": \"CONFIRMED\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"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": "TELEHEALTH_PROVIDED_ELSEWHERE",
"locationId": "loc_1a2b3c",
"technicianId": "usr_tech123",
"clientId": "usr_client789",
"isBillable": true,
"isTelehealth": false,
"clinicianId": "usr_clin456",
"providerLocationId": "loc_9f8e7d",
"services": "svc_1a2b3c"
}
],
"count": 2
}{
"error": "2 session(s) failed validation",
"statusCode": 400,
"errors": [
{
"index": 1,
"code": "STAFF_NOT_FOUND",
"message": "Staff member not found in this organization."
}
]
}{
"error": "API key required",
"statusCode": 401
}{
"error": "Access denied",
"statusCode": 403
}{
"error": "Method not allowed",
"statusCode": 405
}{
"error": "An unexpected error occurred",
"statusCode": 500
}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. If any element fails validation, nothing is created and the response lists every failing session by its index in thesessions 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 asessions 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 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 conveniencecount.
{
"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:
{
"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."
}
]
}
sessions, empty array, more than 100 items, or a field with the wrong type):
{
"message": "Validation Error",
"statusCode": 400,
"validationErrors": [
{
"code": "too_small",
"path": ["sessions"],
"message": "sessions must contain at least one session"
}
]
}
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
{
"error": "API key required",
"statusCode": 401
}
403 - Forbidden
{
"error": "Access denied",
"statusCode": 403
}
Examples
cURL
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
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);
}
Authorizations
API key authentication. Include your API key in the Authorization header as 'Bearer '
Body
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.
The sessions to create, 1 to 100 items. Each item has the same shape and rules as the single create request.
1 - 100 elementsShow child attributes
Show child attributes
Response
All sessions created
Result of a successful bulk create: the created sessions in request order plus the total count.
A scheduled session (appointment). The shape depends on isBillable: billable sessions expose isTelehealth, clinicianId and services; non-billable sessions expose nonBillableCode instead.
- Option 1
- Option 2
Show child attributes
Show child attributes
Number of sessions created.
2