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 carrier name (e.g. "Cigna", "Aetna"), not the plan/product name |
providerNpi | Provider's 10-digit NPI from the onboarding step |
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. Must be unique per partner. | — |
patient.insurance.payerId | Payer's electronic ID (e.g. "62308" for Cigna). Helps with claim routing and filing. | — |
patient.insurance.groupNumber | Insurance group number from patient's card | — |
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. | — |
We strongly recommend providing patient.insurance.payerId when you have it. This ensures claims are routed to the correct payer and filed with the right claim filing code (e.g. CI for commercial, MC for Medicaid, MB for Medicare).
Use Search Payers to autocomplete the insurance carrier and capture payerId. This is the safest way to avoid mixing up a payer like "Cigna" with a plan/product name like "PPO Select Plus".
Integration notes
patient.insurance.payerNameis the insurance carrier/payer name, not the plan name.authNumberandauthorizedSessionsare not accepted by the partner API today, so you can keep them in your own app if useful, but Taiga will not store or use them.- The current partner API does not accept a separate policy-holder/subscriber object. The
patientfields are what flow into claim creation today. - On session submission, the only therapist identifier you send is
providerNpi. Provider and practice demographics are captured during provider onboarding.
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). For telehealth sessions, modifier 95 is automatically added if not explicitly provided. |
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 |
409 | Duplicate externalSessionId — a session with this ID already exists for your organization. The response includes the existing sessionId. |
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": "", "message": "Provide one of: (1) session.noteText, (2) session.diagnosisCodes + session.procedureCodes, or (3) session.diagnosisCodes + session.durationMinutes." }
]
}Duplicate session error
If you send the same externalSessionId twice:
{
"error": "A session with this externalSessionId already exists for your partner organization.",
"sessionId": "existing-session-uuid"
}Update a Session
PATCH /api/v1/partner/sessions/{sessionId}Update patient demographics, insurance info, or codes on an existing session. Only allowed while the session is still in processing status — once a claim has been submitted to a payer, the session is locked.
Only include the fields you want to change. Omitted fields remain unchanged.
If you update session.diagnosisCodes or session.procedureCodes, the new codes replace all existing codes of that type. Send the complete list, not just the additions.
Request
const response = await fetch("https://api.usetaiga.com/api/v1/partner/sessions/SESSION_ID", {
method: "PATCH",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
patient: {
insurance: {
memberId: "MEM-2026-CORRECTED",
groupNumber: "7778888",
},
},
session: {
diagnosisCodes: [
{ code: "F32.1", description: "Major depressive disorder, single episode, moderate" },
{ code: "F41.1", description: "Generalized anxiety disorder" },
],
},
}),
});
const data = await response.json();curl -X PATCH https://api.usetaiga.com/api/v1/partner/sessions/SESSION_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"patient": {
"insurance": {
"memberId": "MEM-2026-CORRECTED",
"groupNumber": "7778888"
}
},
"session": {
"diagnosisCodes": [
{ "code": "F32.1", "description": "Major depressive disorder, single episode, moderate" },
{ "code": "F41.1", "description": "Generalized anxiety disorder" }
]
}
}'Updatable fields
All fields are optional. Only include the ones you want to change.
Patient 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 |
patient.address.zip | ZIP code |
patient.insurance.memberId | Insurance member ID |
patient.insurance.payerName | Insurance company name |
patient.insurance.payerId | Payer's electronic ID |
patient.insurance.groupNumber | Insurance group number |
Session fields:
| Field | Description |
|---|---|
session.dateOfService | YYYY-MM-DD format |
session.placeOfService | "office" or "telehealth" |
session.diagnosisCodes | Replaces all existing ICD-10 codes |
session.procedureCodes | Replaces all existing CPT codes |
Response
{
"sessionId": "uuid",
"status": "updated",
"message": "Session updated successfully. Changes will be reflected in the next claim submission."
}Errors
| Status | Cause |
|---|---|
401 | Invalid or missing API key |
404 | Session not found |
409 | Session already submitted — cannot modify after claim submission |