Submit a Session
Submit a completed therapy session for billing.
POST /api/v1/partner/sessionsSubmit a completed therapy session for billing. We handle everything from here — validation, claim submission, and tracking.
The provider must be onboarded before you can submit sessions under their NPI.
Three ways to submit
You can submit a session in three ways depending on your workflow:
- Diagnosis codes + session duration (simplest) — Send ICD-10 codes and
durationMinutes. We derive the correct CPT code from the duration automatically. Best for therapists who track diagnoses but not procedure codes. - Diagnosis codes + CPT codes (full control) — Send both ICD-10 and CPT codes directly. Best for practices that already track all their codes.
- Clinical note (AI-powered) — Send the full note text. Our AI extracts all codes automatically. You can also send codes alongside the note.
You must provide at least one of: session.noteText, session.diagnosisCodes + session.procedureCodes, or session.diagnosisCodes + session.durationMinutes.
Request — with diagnosis codes + duration (simplest)
Most therapists track their diagnosis codes and session length. Send those and we derive the CPT code:
const response = await fetch("https://api.usetaiga.com/api/v1/partner/sessions", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
providerNpi: "1234567890",
patient: {
firstName: "Sarah",
lastName: "Johnson",
dateOfBirth: "1988-05-15",
gender: "F",
address: {
street: "2222 Random St",
city: "New York",
state: "NY",
zip: "10001",
},
insurance: {
memberId: "MEM-2026-0042",
payerName: "Cigna",
},
},
session: {
dateOfService: "2026-04-01",
placeOfService: "telehealth",
durationMinutes: 45,
diagnosisCodes: [
{ code: "F32.1", description: "Major depressive disorder, single episode, moderate" },
],
},
}),
});
const data = await response.json();curl -X POST https://api.usetaiga.com/api/v1/partner/sessions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"providerNpi": "1234567890",
"patient": {
"firstName": "Sarah",
"lastName": "Johnson",
"dateOfBirth": "1988-05-15",
"gender": "F",
"address": {
"street": "2222 Random St",
"city": "New York",
"state": "NY",
"zip": "10001"
},
"insurance": {
"memberId": "MEM-2026-0042",
"payerName": "Cigna"
}
},
"session": {
"dateOfService": "2026-04-01",
"placeOfService": "telehealth",
"durationMinutes": 45,
"diagnosisCodes": [
{ "code": "F32.1", "description": "Major depressive disorder, single episode, moderate" }
]
}
}'In this case, we derive CPT code 90834 (Psychotherapy, 45 min) from the 45-minute duration.
Request — with full codes (no note)
const response = await fetch("https://api.usetaiga.com/api/v1/partner/sessions", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
externalSessionId: "your-internal-session-id",
patient: {
firstName: "Sarah",
lastName: "Johnson",
dateOfBirth: "1988-05-15",
gender: "F",
address: {
street: "2222 Random St",
city: "New York",
state: "NY",
zip: "10001",
},
insurance: {
memberId: "MEM-2026-0042",
groupNumber: "3335555",
payerName: "Cigna",
},
},
providerNpi: "1234567890",
session: {
dateOfService: "2026-04-01",
placeOfService: "telehealth",
diagnosisCodes: [
{ code: "F32.1", description: "Major depressive disorder, single episode, moderate" },
],
procedureCodes: [
{ code: "90834", description: "Psychotherapy, 45 min" },
],
},
}),
});
const data = await response.json();import requests
response = requests.post(
"https://api.usetaiga.com/api/v1/partner/sessions",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"externalSessionId": "your-internal-session-id",
"patient": {
"firstName": "Sarah",
"lastName": "Johnson",
"dateOfBirth": "1988-05-15",
"gender": "F",
"address": {
"street": "2222 Random St",
"city": "New York",
"state": "NY",
"zip": "10001",
},
"insurance": {
"memberId": "MEM-2026-0042",
"groupNumber": "3335555",
"payerName": "Cigna",
},
},
"providerNpi": "1234567890",
"session": {
"dateOfService": "2026-04-01",
"placeOfService": "telehealth",
"diagnosisCodes": [
{"code": "F32.1", "description": "Major depressive disorder, single episode, moderate"}
],
"procedureCodes": [
{"code": "90834", "description": "Psychotherapy, 45 min"}
],
},
},
)
data = response.json()curl -X POST https://api.usetaiga.com/api/v1/partner/sessions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"externalSessionId": "your-internal-session-id",
"patient": {
"firstName": "Sarah",
"lastName": "Johnson",
"dateOfBirth": "1988-05-15",
"gender": "F",
"address": {
"street": "2222 Random St",
"city": "New York",
"state": "NY",
"zip": "10001"
},
"insurance": {
"memberId": "MEM-2026-0042",
"groupNumber": "3335555",
"payerName": "Cigna"
}
},
"providerNpi": "1234567890",
"session": {
"dateOfService": "2026-04-01",
"placeOfService": "telehealth",
"diagnosisCodes": [
{ "code": "F32.1", "description": "Major depressive disorder, single episode, moderate" }
],
"procedureCodes": [
{ "code": "90834", "description": "Psychotherapy, 45 min" }
]
}
}'Request — with a clinical note
If you prefer to send the clinical note and let our AI handle coding:
const response = await fetch("https://api.usetaiga.com/api/v1/partner/sessions", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
patient: {
firstName: "Sarah",
lastName: "Johnson",
dateOfBirth: "1988-05-15",
gender: "F",
address: {
street: "2222 Random St",
city: "New York",
state: "NY",
zip: "10001",
},
insurance: {
memberId: "MEM-2026-0042",
payerName: "Cigna",
},
},
providerNpi: "1234567890",
session: {
dateOfService: "2026-04-01",
placeOfService: "telehealth",
durationMinutes: 45,
noteText: "Patient returns for follow-up of major depressive disorder...",
},
}),
});
const data = await response.json();import requests
response = requests.post(
"https://api.usetaiga.com/api/v1/partner/sessions",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"patient": {
"firstName": "Sarah",
"lastName": "Johnson",
"dateOfBirth": "1988-05-15",
"gender": "F",
"address": {
"street": "2222 Random St",
"city": "New York",
"state": "NY",
"zip": "10001",
},
"insurance": {
"memberId": "MEM-2026-0042",
"payerName": "Cigna",
},
},
"providerNpi": "1234567890",
"session": {
"dateOfService": "2026-04-01",
"placeOfService": "telehealth",
"durationMinutes": 45,
"noteText": "Patient returns for follow-up of major depressive disorder...",
},
},
)
data = response.json()curl -X POST https://api.usetaiga.com/api/v1/partner/sessions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"patient": {
"firstName": "Sarah",
"lastName": "Johnson",
"dateOfBirth": "1988-05-15",
"gender": "F",
"address": {
"street": "2222 Random St",
"city": "New York",
"state": "NY",
"zip": "10001"
},
"insurance": {
"memberId": "MEM-2026-0042",
"payerName": "Cigna"
}
},
"providerNpi": "1234567890",
"session": {
"dateOfService": "2026-04-01",
"placeOfService": "telehealth",
"durationMinutes": 45,
"noteText": "Patient returns for follow-up of major depressive disorder..."
}
}'Required fields
| Field | Description |
|---|---|
patient.firstName | Patient first name |
patient.lastName | Patient last name |
patient.dateOfBirth | YYYY-MM-DD format |
patient.gender | M, F, or U |
patient.address.street | Street address |
patient.address.city | City |
patient.address.state | 2-letter state code (e.g. "NY") |
patient.address.zip | 5-digit ZIP code |
patient.insurance.memberId | Insurance member ID from card |
patient.insurance.payerName | Insurance company name (e.g. "Cigna", "Aetna") |
providerNpi | Provider's 10-digit NPI (must be onboarded first) |
session.dateOfService | YYYY-MM-DD format |
patient.address, patient.dateOfBirth, and patient.gender are required because insurance claims cannot be submitted without them.
Conditional fields
You must provide at least one of the following combinations:
| Option | Fields needed |
|---|---|
| Diagnosis + duration | session.diagnosisCodes (ICD-10) and session.durationMinutes — we derive the CPT code |
| Full codes | session.diagnosisCodes (ICD-10) and session.procedureCodes (CPT) |
| Clinical note | session.noteText — AI handles all coding |
| Codes + note | Any of the above plus session.noteText — your codes are used as-is, note is processed for validation |
Optional fields
| Field | Description | Default |
|---|---|---|
externalSessionId | Your internal session ID for correlation | — |
patient.insurance.payerId | Payer's electronic ID (helps with routing) | — |
patient.insurance.groupNumber | Insurance group number | — |
session.placeOfService | "office" or "telehealth" | "office" |
session.durationMinutes | Session length in minutes. Used to derive CPT code when procedureCodes is omitted. Also helps AI pick the right code when using notes. | — |
Diagnosis codes (ICD-10)
If the therapist tracks ICD-10 codes, include them in session.diagnosisCodes:
"diagnosisCodes": [
{ "code": "F32.1", "description": "Major depressive disorder, single episode, moderate" },
{ "code": "F41.1", "description": "Generalized anxiety disorder" }
]| Field | Required | Description |
|---|---|---|
code | Yes | ICD-10-CM code (e.g. "F32.1") |
description | No | Human-readable description |
Procedure codes (CPT)
Include CPT codes in session.procedureCodes:
"procedureCodes": [
{ "code": "90834", "description": "Psychotherapy, 45 min" }
]| Field | Required | Description |
|---|---|---|
code | Yes | CPT code (e.g. "90834") |
description | No | Human-readable description |
modifier | No | CPT modifier (e.g. "95" for synchronous telehealth) |
CPT derivation from duration
When you send durationMinutes without explicit procedureCodes, we derive the CPT code automatically:
| Duration | CPT Code | Description |
|---|---|---|
| 16–37 minutes | 90832 | Psychotherapy, 30 min |
| 38–52 minutes | 90834 | Psychotherapy, 45 min |
| 53+ minutes | 90837 | Psychotherapy, 60 min |
This also applies when you send a note without CPT codes — we use durationMinutes (or infer from the note) to select the correct code.
Response
201 Created
{
"sessionId": "uuid",
"externalSessionId": "your-internal-session-id",
"status": "processing",
"message": "Session received with codes. Ready for review. Poll GET /api/v1/partner/sessions/{sessionId} for status."
}Use sessionId to check the status of this session.
Errors
| Status | Cause |
|---|---|
400 | Missing or invalid required fields — response includes an issues array with field paths and messages |
401 | Invalid or missing API key |
404 | Provider NPI not found — onboard the provider first |
Validation error format
When validation fails, you get a structured response with the specific issues:
{
"error": "Validation failed",
"issues": [
{ "path": "patient.address.state", "message": "patient.address.state must be a 2-letter state code" },
{ "path": "session", "message": "Either session.noteText must be provided (AI will generate codes), or both session.diagnosisCodes and session.procedureCodes must be provided." }
]
}