Settlement Record
Complete schema for Settlement Records, which track the movement of funds from plan sponsor through Stripe to providers.
Overview
A Settlement Record documents the entire payment lifecycle from claim adjudication through bank deposit. It includes Stripe metadata and reconciliation information necessary for accounting and audit purposes.
Claim → Adjudication → Settlement Initiated → Stripe Processing → Bank Deposit
↓
Settlement Record created
Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
settlement_id | string | ✓ | Unique settlement identifier (e.g., "SETTLE-2024-001") |
claim_response_id | string | ✓ | Reference to ClaimResponse (e.g., "CLMR-2024-001") |
claim_id | string | ✓ | Original claim ID (e.g., "CLM-2024-001") |
status | string | ✓ | Settlement status (see table below) |
provider_npi | string | ✓ | Provider National Provider Identifier |
facility_npi | string | ✗ | Facility NPI (if applicable) |
member_id | string | ✓ | Patient/member identifier |
amount | object | ✓ | Payment amount with currency |
payouts | array | ✓ | Array of payout objects (see below) |
created_at | timestamp | ✓ | When settlement was initiated |
authorized_at | timestamp | ✗ | When TPA authorized settlement |
completed_at | timestamp | ✗ | When funds arrived (Stripe confirmed) |
stripe_transfer_id | string | ✓ | Stripe ACH transfer ID (e.g., "tr_abc123xyz") |
stripe_trace_id | string | ✓ | Opaque trace ID for bank reconciliation (no PHI) |
reconciliation_status | string | ✓ | Reconciliation state (see below) |
aeob_match | boolean | ✓ | Whether settlement matches AEOB |
metadata | object | ✗ | Custom key-value pairs |
Status Values
| Status | Meaning | Duration |
|---|---|---|
pending | Awaiting TPA authorization | Hours |
authorized | TPA approved, queued for Stripe | Minutes |
in_transit | ACH initiated to provider bank | 1-2 days |
completed | Funds arrived in provider account | Permanent |
failed | Settlement failed (insufficient funds, bad account, etc.) | Error state |
reversed | Settlement reversed (rare) | Error recovery |
Amount Object
{
"amount": {
"value": 1100.00,
"currency": "USD",
"turquoise_fee": 6.00,
"net_to_provider": 1100.00
}
}
| Field | Type | Description |
|---|---|---|
value | decimal | Total amount paid |
currency | string | Always "USD" |
turquoise_fee | decimal | 0.5% processing fee (paid by plan sponsor) |
net_to_provider | decimal | Amount credited to provider (same as value) |
The turquoise_fee is always deducted from plan sponsor reimbursement, never from provider payment. Provider receives full value.
Payout Structure
Settlement includes detailed payout information for multi-recipient claims:
{
"payouts": [
{
"sequence": 1,
"recipient_npi": "1234567890",
"recipient_name": "Dr. John Smith",
"recipient_type": "provider",
"amount": 800.00,
"metadata": {
"role": "operating_physician",
"specialty": "gastroenterology"
}
},
{
"sequence": 2,
"recipient_npi": "9876543210",
"recipient_name": "Sharp HealthCare",
"recipient_type": "facility",
"amount": 300.00,
"metadata": {
"role": "facility",
"type": "endoscopy_center"
}
}
]
}
| Field | Type | Description |
|---|---|---|
sequence | integer | Payout order (1, 2, 3...) |
recipient_npi | string | NPI or unique ID of recipient |
recipient_name | string | Name of provider or facility |
recipient_type | string | "provider", "facility", "anesthesia", "pathology" |
amount | decimal | Amount to this recipient |
metadata | object | Role, specialty, notes |
Reconciliation Status
| Status | Meaning | Action |
|---|---|---|
unverified | Not yet reconciled to AEOB | Pending review |
verified | Matches AEOB and member responsibility | ✓ Confirmed |
variance_minor | Small discrepancy ($1-100) | Review if needed |
variance_major | Large discrepancy (>$100) | Investigate |
disputed | Provider or member disputed amount | Escalate to TPA |
Complete Settlement Record Example
{
"settlement_id": "SETTLE-2024-001",
"claim_response_id": "CLMR-2024-001",
"claim_id": "CLM-2024-001",
"status": "completed",
"provider_npi": "1234567890",
"facility_npi": "9876543210",
"member_id": "SHP00123456",
"amount": {
"value": 1100.00,
"currency": "USD",
"turquoise_fee": 6.00,
"net_to_provider": 1100.00
},
"payouts": [
{
"sequence": 1,
"recipient_npi": "1234567890",
"recipient_name": "Dr. John Smith",
"recipient_type": "provider",
"amount": 800.00,
"metadata": {
"role": "operating_physician",
"specialty": "gastroenterology"
}
},
{
"sequence": 2,
"recipient_npi": "9876543210",
"recipient_name": "Sharp HealthCare",
"recipient_type": "facility",
"amount": 300.00,
"metadata": {
"role": "facility_fee",
"type": "endoscopy_center"
}
}
],
"created_at": "2024-03-11T10:30:00Z",
"authorized_at": "2024-03-11T10:35:00Z",
"completed_at": "2024-03-12T09:45:00Z",
"stripe_transfer_id": "tr_0311_abc123xyz",
"stripe_trace_id": "trace_0311_abc123xyz",
"reconciliation_status": "verified",
"aeob_match": true,
"metadata": {
"claim_type": "institutional",
"ssp_code": "SSP-EGD-001",
"procedure_date": "2024-03-10",
"plan_sponsor": "Sharp Health Plan",
"processing_time_hours": 23
}
}
Webhook Events
Settlements trigger a series of webhook events:
Event 1: settlement.initiated
{
"event_type": "settlement.initiated",
"settlement_id": "SETTLE-2024-001",
"claim_response_id": "CLMR-2024-001",
"status": "authorized",
"amount": 1100.00,
"created_at": "2024-03-11T10:30:00Z",
"stripe_transfer_id": "tr_0311_abc123xyz"
}
When sent: Immediately after TPA authorizes settlement Action: Log settlement initiation; update RCM pending status
Event 2: settlement.in_transit
{
"event_type": "settlement.in_transit",
"settlement_id": "SETTLE-2024-001",
"status": "in_transit",
"amount": 1100.00,
"expected_arrival": "2024-03-12T09:00:00Z",
"stripe_transfer_id": "tr_0311_abc123xyz"
}
When sent: When Stripe initiates ACH transfer (typically same day) Action: Optional—notify provider of pending deposit
Event 3: settlement.completed
{
"event_type": "settlement.completed",
"settlement_id": "SETTLE-2024-001",
"status": "completed",
"amount": 1100.00,
"arrived_at": "2024-03-12T09:45:00Z",
"stripe_transfer_id": "tr_0311_abc123xyz",
"stripe_trace_id": "trace_0311_abc123xyz",
"bank_deposit_reference": "STRIPE HEALTH INC",
"payouts": [
{
"recipient_npi": "1234567890",
"amount": 800.00
},
{
"recipient_npi": "9876543210",
"amount": 300.00
}
]
}
When sent: When funds confirmed in provider bank account (48 hours) Action: Post payment to RCM; mark claim as paid; close AR
Event 4: settlement.failed (Rare)
{
"event_type": "settlement.failed",
"settlement_id": "SETTLE-2024-001",
"status": "failed",
"failure_reason": "invalid_bank_account",
"failure_details": "Bank account number mismatch",
"created_at": "2024-03-11T10:30:00Z",
"retried_at": null,
"contact_required": true
}
When sent: When settlement fails (bad bank account, insufficient funds, etc.) Action: Contact Turquoise support to update bank information; retry settlement
Querying Settlements
Get Single Settlement
curl -X GET \
https://api.turquoise.health/tpa-api/v1/settlements/SETTLE-2024-001 \
-H "X-API-Key: $TURQUOISE_API_KEY"
List Settlements by Status
# Get all completed settlements from today
curl -X GET \
"https://api.turquoise.health/tpa-api/v1/settlements?status=completed&created_since=2024-03-10T00:00:00Z" \
-H "X-API-Key: $TURQUOISE_API_KEY"
Response:
{
"settlements": [
{ "settlement_id": "SETTLE-2024-001", "status": "completed", ... },
{ "settlement_id": "SETTLE-2024-002", "status": "completed", ... }
],
"pagination": {
"total": 127,
"page": 1,
"page_size": 20
}
}
List by Provider
curl -X GET \
"https://api.turquoise.health/tpa-api/v1/settlements?provider_npi=1234567890&status=completed" \
-H "X-API-Key: $TURQUOISE_API_KEY"
Reconciliation Workflow
Step 1: Receive webhook
@app.route('/webhooks/settlements', methods=['POST'])
def handle_settlement(request):
event = request.json
settlement = event['settlement_id']
if event['event_type'] == 'settlement.completed':
# Fetch full settlement record
settlement_record = turquoise_client.settlements.get(settlement)
return process_settlement(settlement_record)
Step 2: Post to RCM
def process_settlement(settlement_record):
# Extract settlement details
claim_id = settlement_record['claim_id']
amount = settlement_record['amount']['value']
stripe_trace_id = settlement_record['stripe_trace_id']
# Post payment to RCM system
rcm.post_payment(
claim_id=claim_id,
amount=amount,
method='ACH',
reference_id=stripe_trace_id,
timestamp=settlement_record['completed_at']
)
# Mark claim as paid
rcm.mark_claim_paid(claim_id, stripe_trace_id)
Step 3: Reconcile to Bank Deposit
def reconcile_bank_deposit(bank_deposit):
# Extract transaction reference from bank
reference = bank_deposit['description'] # e.g., "STRIPE HEALTH INC trace_..."
amount = bank_deposit['amount']
# Look up settlement by trace ID
settlements = turquoise_client.settlements.list(
stripe_trace_id=extract_trace_id(reference)
)
if settlements and settlements[0]['amount']['value'] == amount:
print(f"✓ Reconciled: {reference}")
else:
print(f"✗ Variance: {reference}")
Handling Multiple Payouts
Some claims split payment across multiple recipients:
{
"settlement_id": "SETTLE-2024-002",
"payouts": [
{
"sequence": 1,
"recipient_npi": "1111111111",
"recipient_type": "surgeon",
"amount": 700.00
},
{
"sequence": 2,
"recipient_npi": "2222222222",
"recipient_type": "anesthesiologist",
"amount": 200.00
},
{
"sequence": 3,
"recipient_npi": "9876543210",
"recipient_type": "facility",
"amount": 200.00
}
]
}
Each recipient receives their portion via ACH transfer to their registered bank account.
Variance Handling
Minor Variance ($1-100)
if settlement_record['reconciliation_status'] == 'variance_minor':
# Review if desired, but typically acceptable
log_variance(settlement_record)
# Proceed with posting payment
Major Variance (>$100)
if settlement_record['reconciliation_status'] == 'variance_major':
# Escalate to TPA for investigation
escalate_to_tpa(settlement_record)
# Don't post payment yet; wait for resolution
Common causes:
- Member responsibility adjusted due to deductible/coinsurance
- Rate discrepancy discovered during adjudication
- Modifier applied post-submission
True-Up Settlements
When adjustments are needed post-settlement:
{
"settlement_id": "SETTLE-2024-001-TRUEUP",
"original_settlement_id": "SETTLE-2024-001",
"type": "true_up",
"status": "completed",
"amount": {
"value": 50.00,
"currency": "USD"
},
"reason": "deductible_adjustment",
"created_at": "2024-03-15T10:00:00Z"
}
A true-up settlement references the original and indicates an adjustment was needed.
Auditing & Compliance
Every settlement is immutable and auditable:
{
"settlement_id": "SETTLE-2024-001",
"audit_trail": [
{
"timestamp": "2024-03-11T10:30:00Z",
"action": "initiated",
"actor": "turquoise_system"
},
{
"timestamp": "2024-03-11T10:35:00Z",
"action": "authorized",
"actor": "tpa_user@sharp-tpa.com"
},
{
"timestamp": "2024-03-11T10:35:30Z",
"action": "submitted_to_stripe",
"actor": "turquoise_system"
},
{
"timestamp": "2024-03-12T09:45:00Z",
"action": "completed",
"actor": "stripe_system"
}
]
}
Best Practices
- Always use stripe_trace_id for bank reconciliation: Never rely on claim ID
- Listen for webhooks: Don't poll; subscribe to
settlement.completedevents - Reconcile daily: Compare webhook settlements to bank deposits daily
- Track variances: Monitor
reconciliation_statusfor discrepancies - Secure webhook endpoints: Verify webhook signatures before processing
- Handle retries: Settlement webhooks may be delivered multiple times; use idempotency