Version 1.0.0
LastMileRCM provides a webhook-based integration API that allows case management systems, EMRs, and other healthcare platforms to submit patient demographics, provider information, insurance coverage, and claims data directly into LastMileRCM for processing. The tenant is automatically resolved from your API key — no tenant identification is needed in the request body.
Base URL: https://lastmilercm.com
All API requests must include an API key in the x-api-key header. API keys are provisioned per integration partner during onboarding.
x-api-keylmr_xxxxxxxx...(min 32 characters)Requests are rate-limited per partner. Two limits apply: 60 requests per minute and 10,000 requests per day (rolling from midnight UTC). Exceeding either limit returns 429 Too Many Requests. The daily limit is configurable per partner.
To prevent duplicate processing, include a unique idempotency_key in the metadata object. If a payload with the same key has already been processed, the API returns 200 with a message confirming it was already processed. No entities are re-created. If the payload is still being processed, the API returns 202.
Demo tenants have configurable limits on patient counts, claim counts, and feature access. If a limit would be exceeded by the incoming batch, the entire request is blocked and the API returns 403 Forbidden with a descriptive message indicating the current usage, limit, and how many slots remain.
Limits are checked against the batch size before processing begins — partial batches are not processed. For example, if 20/25 patients are used and a batch of 10 is submitted, the entire batch is rejected.
/api/webhooks/cms/inboundReceives patient and claim data from external case management systems. The endpoint validates the API key, processes each patient record, and creates the corresponding entities in the tenant's account.
default_tenant_idexternal_id — create new or update existing patientUpsert Behavior: Patients, coverages, and claims support upsert. If a matching record exists and the incoming data differs, the record is updated. If the data is identical, it is reported as "existing" with no DB write. See the section for matching keys.
Per-Item Tracking: The response includes an items array showing what happened to each patient in the batch — which entities were created, updated, or matched, plus any item-level errors with standardized codes.
Draft Enrollments: When a provider-payer pair is seen for the first time, a draft enrollment is automatically created. This appears in the provider's detail page and can be activated once the provider is registered with the clearinghouse.
patientsarrayRequiredArray of patient records to process. Always use an array, even for a single patient.
See Patient schema below
metadataobjectOptional metadata about the submission
external_idstringYour system's unique ID for this patient. Used for deduplication — if a patient with this external_id already exists for the tenant, the existing record is reused.
Example: CMS-PAT-001
first_namestringRequiredExample: Jane
last_namestringRequiredExample: Doe
date_of_birthstringdateRequiredExample: 1985-03-15
genderstringNormalized to M/F internally
MFMaleFemalephonestringExample: 603-555-0100
emailstringemailExample: jane.doe@example.com
addressobjectPatient mailing address
The NPI is validated against the CMS NPI Registry (NPPES). If valid, the provider record is enriched with official registry data (name, address, taxonomy, credentials). If the NPI already exists for this tenant, the existing provider is reused.
npistringRequiredNational Provider Identifier (10 digits). Must be a valid, active NPI in the CMS registry.
Example: 1234567890
tax_idstringEIN or SSN (9 digits). Encrypted at rest.
Example: 123456789
tax_id_typestringType of tax identifier
EINSSNcontact_emailstringemailContact email for enrollment communications. Encrypted at rest.
Example: billing@provider.com
The payer name is matched against the Stedi payer directory. Only recognized payers are accepted. Matching tries exact payer_id, RPC search, and fuzzy display name matching.
payer_namestringRequiredInsurance company name. Matched against the payer directory.
Example: Blue Cross Blue Shield
payer_idstringOptional Stedi payer ID or primary payer ID for exact matching. Takes priority over name matching.
Example: BCBS
member_idstringRequiredInsurance member/subscriber ID. Encrypted at rest with a searchable last-4 index.
Example: XYZ123456789
group_numberstringExample: GRP-001
plan_namestringExample: PPO Gold
coverage_typestringInsurance coverage tier
primarysecondarytertiaryDefault: primary
effective_datestringdateExample: 2024-01-01
termination_datestringdateExample: 2024-12-31
Requires both a provider and coverage to be successfully resolved. Claims are created in draft status.
service_datestringdateRequiredDate of service
Example: 2024-06-15
place_of_servicestringCMS Place of Service code (e.g., 11=Office, 02=Telehealth)
Default: 11
prior_auth_numberstringPrior authorization number if applicable
Example: AUTH-12345
total_chargenumberTotal charge amount. If omitted, calculated as sum of service line charges.
diagnosesarrayRequiredICD-10 diagnosis codes. Decimal points are stripped automatically.
service_linesarrayRequiredCPT/HCPCS procedure codes with charges
The API supports re-submitting data with changes. When a matching record exists, the API compares fields and only writes to the database if something actually changed. Identical re-submissions are reported as "existing" with no database write.
Match key: external_id (per tenant)
Behavior: If a patient with the same external_id exists, the API compares first_name, last_name, date_of_birth, gender, phone, email, and address fields. Only changed fields are updated.
Action values: created updated existing
Match key: patient_id + payer_id + coverage_type
Behavior: If a coverage with the same composite key exists, the API compares member_id, group_number, plan_name, effective_date, and termination_date. Only changed fields are updated.
Action values: created updated existing
Match key: patient_id + statement_from_date (service_date)
Behavior: If a claim with the same patient and service date exists, the API performs a deep comparison of claim fields (place_of_service, prior_auth_number, total_charge_amount), diagnosis codes, and all service line details (procedure codes, units, charges, modifiers). If anything differs, the claim is updated with the new data. Diagnoses and service lines are fully replaced on update.
Action values: created updated existing
Match key: NPI (per tenant)
Behavior: If a provider with the same NPI exists, the existing record is reused. No updates are performed. Provider data is enriched from the NPPES registry on initial creation.
Action values: created existing
Every response includes a top-level code field with a machine-readable status code, and a message field with a human-readable summary. See the section for the complete reference.
successbooleantrue when all items processed without fatal errors
codestringMachine-readable status code (e.g., OK, COMPLETED_WITH_ERRORS)
messagestringHuman-readable summary of what was processed
webhook_idstringuuidUnique ID for this invocation — use for support inquiries
processedobjectAggregate counts for each entity type
patientsobjectPatient processing counts
claimsobjectClaim processing counts
providersobjectProvider processing counts
payersobjectPayer resolution counts
coveragesobjectCoverage processing counts
enrollmentsobjectProvider-payer enrollment counts
itemsarrayPer-item detail — one entry per patient in the batch
indexintegerZero-based position in the input patients array
identifierstringThe patient's external_id (or 'unknown' if missing)
statusstringOverall outcome for this item
successpartialfailedpatientobjectPatient outcome (present if patient was processed)
providerobjectProvider outcome (present if provider was resolved)
payerobjectPayer outcome (present if payer was resolved)
coverageobjectCoverage outcome (present if coverage was processed)
claimobjectClaim outcome (present if claim was processed)
enrollmentobjectEnrollment outcome (present if enrollment was processed)
errorsarrayItem-level errors (present only if this item had issues)
errorsarrayLegacy error summary array — flat list of human-readable error strings. Present only if there were item-level issues.
Payload processed. Code is OK if all items succeeded, or COMPLETED_WITH_ERRORS if some items had non-fatal issues (e.g., payer not found). Also used for idempotent responses (IDEMPOTENCY_COMPLETED).
Idempotency key matched a payload still being processed. Code: IDEMPOTENCY_PENDING.
Invalid payload structure or missing required fields. Codes: PAYLOAD_INVALID, PAYLOAD_MISSING_PATIENTS, TENANT_NOT_CONFIGURED.
Missing or invalid API key. Codes: AUTH_MISSING_KEY, AUTH_INVALID_FORMAT, AUTH_INVALID_KEY, AUTH_INACTIVE.
IP not in allowlist or demo limit exceeded. Codes: IP_NOT_ALLOWED, LIMIT_PATIENTS, LIMIT_CLAIMS.
Exceeded rate limits. Codes: RATE_LIMIT_MINUTE, RATE_LIMIT_DAILY.
Internal processing failure. Codes: INTERNAL_ERROR, STORAGE_FAILED.
All errors include a machine-readable code field. Request-level codes appear in the top-level response. Item-level codes appear in items[].errors[].code.
| Code | HTTP | Description |
|---|---|---|
OK | 200 | All items processed successfully |
COMPLETED_WITH_ERRORS | 200 | Some items had non-fatal errors (e.g., payer not found) |
IDEMPOTENCY_COMPLETED | 200 | Payload was already processed (idempotency key matched) |
IDEMPOTENCY_PENDING | 202 | Payload is still being processed |
AUTH_MISSING_KEY | 401 | x-api-key header is missing |
AUTH_INVALID_FORMAT | 401 | API key does not start with lmr_ or is too short |
AUTH_INVALID_KEY | 401 | API key not found in the system |
AUTH_INACTIVE | 401 | API key exists but is deactivated |
IP_NOT_ALLOWED | 403 | Request IP not in partner's allowlist |
LIMIT_PATIENTS | 403 | Batch would exceed demo tenant patient limit |
LIMIT_CLAIMS | 403 | Batch would exceed demo tenant claim limit |
RATE_LIMIT_MINUTE | 429 | Exceeded 60 requests per minute |
RATE_LIMIT_DAILY | 429 | Exceeded 10,000 requests per day |
PAYLOAD_INVALID | 400 | Request body is not valid JSON |
PAYLOAD_MISSING_PATIENTS | 400 | patients array is missing or empty |
TENANT_NOT_CONFIGURED | 400 | Partner does not have a default tenant assigned |
INTERNAL_ERROR | 500 | Unexpected server error during processing |
STORAGE_FAILED | 500 | Failed to store raw payload for audit trail |
These codes appear in items[].errors[].code and indicate what went wrong for a specific patient in the batch. Item-level errors do not fail the entire request.
| Code | Description |
|---|---|
PATIENT_MISSING_FIELDS | Patient is missing required fields (first_name, last_name, date_of_birth) |
PATIENT_CREATE_FAILED | Database error creating the patient record |
PATIENT_UPDATE_FAILED | Database error updating an existing patient |
PATIENT_DEDUP_FAILED | Error during deduplication check (external_id lookup) |
NPI_INVALID_FORMAT | NPI is not a valid 10-digit number |
NPI_NOT_FOUND | NPI not found in the CMS NPPES registry |
PROVIDER_CREATE_FAILED | Database error creating the provider record |
PAYER_NOT_FOUND | Payer name could not be matched in the payer directory |
COVERAGE_CREATE_FAILED | Database error creating the coverage record |
COVERAGE_UPDATE_FAILED | Database error updating an existing coverage |
CLAIM_MISSING_FIELDS | Claim is missing required fields (diagnoses, service_lines) |
CLAIM_MISSING_PROVIDER | Cannot create claim without a valid provider |
CLAIM_MISSING_COVERAGE | Cannot create claim without valid coverage (payer not found) |
CLAIM_DUPLICATE | Claim with same patient + service date already exists (legacy) |
CLAIM_CREATE_FAILED | Database error creating the claim record |
CLAIM_UPDATE_FAILED | Database error updating an existing claim |
Contact ananth@thehealthcolab.com for API key provisioning, integration support, or questions.
curl --request POST \
--url "https://lastmilercm.com/api/webhooks/cms/inbound" \
--header "x-api-key: lmr_your_api_key_here" \
--header "Content-Type: application/json" \
--data '{
"patients": [
{
"external_id": "CMS-PAT-001",
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1985-03-15",
"gender": "F",
"phone": "603-555-0100",
"email": "jane.doe@example.com",
"address": {
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "Manchester",
"state": "NH",
"postal_code": "03101"
},
"provider": {
"npi": "1003000126",
"tax_id": "061234567",
"tax_id_type": "EIN",
"contact_email": "billing@provider.com"
},
"coverage": {
"payer_name": "Blue Cross Blue Shield",
"member_id": "XYZ123456789",
"group_number": "GRP-001",
"plan_name": "PPO Gold",
"coverage_type": "primary",
"effective_date": "2024-01-01"
},
"claim": {
"service_date": "2024-06-15",
"place_of_service": "11",
"prior_auth_number": "AUTH-12345",
"diagnoses": [
{ "code": "F32.1", "type": "principal" },
{ "code": "F41.1", "type": "secondary" }
],
"service_lines": [
{
"procedure_code": "90837",
"description": "Psychotherapy, 60 min",
"units": 1,
"charge_amount": 150.00,
"modifier_1": "95"
}
]
}
}
],
"metadata": {
"source_system": "YourCMS",
"idempotency_key": "batch-20240615-001"
}
}'{
"success": true,
"code": "OK",
"message": "Processed: 1 new patient(s), 1 new claim(s), 1 new provider(s)",
"webhook_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"processed": {
"patients": { "created": 1, "updated": 0, "existing": 0, "failed": 0 },
"claims": { "created": 1, "updated": 0, "existing": 0, "skipped": 0, "failed": 0 },
"providers": { "created": 1, "existing": 0, "failed": 0 },
"payers": { "resolved": 1, "not_found": 0 },
"coverages": { "created": 1, "updated": 0, "existing": 0, "failed": 0 },
"enrollments": { "created": 1, "existing": 0 }
},
"items": [
{
"index": 0,
"identifier": "CMS-PAT-001",
"status": "success",
"patient": { "id": "f1a2...", "action": "created" },
"provider": { "id": "b3c4...", "npi": "1003000126", "action": "created" },
"payer": { "id": "d5e6...", "name": "Blue Cross Blue Shield", "action": "resolved" },
"coverage": { "id": "a7b8...", "action": "created" },
"claim": { "id": "c9d0...", "pcn": "WH-JD-M1K2N3-0", "action": "created" },
"enrollment": { "action": "created" }
}
]
}{
"success": true,
"code": "COMPLETED_WITH_ERRORS",
"message": "Processed: 2 new patient(s), 1 updated patient(s), 1 new claim(s), 1 updated claim(s)",
"webhook_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"processed": {
"patients": { "created": 2, "updated": 1, "existing": 0, "failed": 0 },
"claims": { "created": 1, "updated": 1, "existing": 0, "skipped": 0, "failed": 0 },
"providers": { "created": 0, "existing": 1, "failed": 0 },
"payers": { "resolved": 2, "not_found": 1 },
"coverages": { "created": 1, "updated": 1, "existing": 0, "failed": 0 },
"enrollments": { "created": 0, "existing": 1 }
},
"items": [
{
"index": 0, "identifier": "CMS-PAT-001", "status": "success",
"patient": { "id": "f1a2...", "action": "updated" },
"claim": { "id": "c9d0...", "pcn": "WH-JD-M1K2N3-0", "action": "updated" }
},
{
"index": 1, "identifier": "CMS-PAT-002", "status": "success",
"patient": { "id": "e3f4...", "action": "created" },
"claim": { "id": "g5h6...", "pcn": "WH-AB-M1K2N3-1", "action": "created" }
},
{
"index": 2, "identifier": "CMS-PAT-ERR", "status": "partial",
"patient": { "id": "i7j8...", "action": "created" },
"errors": [
{ "code": "PAYER_NOT_FOUND", "message": "Payer \"Totally Made Up Insurance\" not found..." }
]
}
],
"errors": [
"CMS-PAT-ERR: Payer \"Totally Made Up Insurance\" not found in payer directory..."
]
}{
"success": true,
"code": "IDEMPOTENCY_COMPLETED",
"message": "Payload already processed (idempotency key matched)",
"webhook_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}{
"success": false,
"code": "PAYLOAD_MISSING_PATIENTS",
"message": "Invalid payload. Expected \"patients\" array with at least one patient."
}{
"success": false,
"code": "TENANT_NOT_CONFIGURED",
"message": "Partner does not have a tenant configured. Contact support to set up your integration."
}{
"success": false,
"code": "AUTH_INVALID_KEY",
"message": "Invalid API key"
}{
"success": false,
"code": "LIMIT_PATIENTS",
"message": "Demo limit exceeded. You have 45 of 50 patients used and this request would add 10 more.",
"webhook_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}{
"success": false,
"code": "RATE_LIMIT_MINUTE",
"message": "Rate limit exceeded. Maximum 60 requests per minute."
}{
"success": false,
"code": "RATE_LIMIT_DAILY",
"message": "Daily rate limit exceeded. 10000/10000 requests today. Resets at midnight UTC."
}curl --request POST \
--url "https://lastmilercm.com/api/webhooks/cms/inbound" \
--header "x-api-key: lmr_your_api_key_here" \
--header "Content-Type: application/json" \
--data '{
"patients": [
{
"external_id": "CMS-PAT-001",
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1985-03-15",
"gender": "F",
"phone": "603-555-0100",
"email": "jane.doe@example.com",
"address": {
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "Manchester",
"state": "NH",
"postal_code": "03101"
},
"provider": {
"npi": "1003000126",
"tax_id": "061234567",
"tax_id_type": "EIN",
"contact_email": "billing@provider.com"
},
"coverage": {
"payer_name": "Blue Cross Blue Shield",
"member_id": "XYZ123456789",
"group_number": "GRP-001",
"plan_name": "PPO Gold",
"coverage_type": "primary",
"effective_date": "2024-01-01"
},
"claim": {
"service_date": "2024-06-15",
"place_of_service": "11",
"prior_auth_number": "AUTH-12345",
"diagnoses": [
{ "code": "F32.1", "type": "principal" },
{ "code": "F41.1", "type": "secondary" }
],
"service_lines": [
{
"procedure_code": "90837",
"description": "Psychotherapy, 60 min",
"units": 1,
"charge_amount": 150.00,
"modifier_1": "95"
}
]
}
}
],
"metadata": {
"source_system": "YourCMS",
"idempotency_key": "batch-20240615-001"
}
}'{
"success": true,
"code": "OK",
"message": "Processed: 1 new patient(s), 1 new claim(s), 1 new provider(s)",
"webhook_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"processed": {
"patients": { "created": 1, "updated": 0, "existing": 0, "failed": 0 },
"claims": { "created": 1, "updated": 0, "existing": 0, "skipped": 0, "failed": 0 },
"providers": { "created": 1, "existing": 0, "failed": 0 },
"payers": { "resolved": 1, "not_found": 0 },
"coverages": { "created": 1, "updated": 0, "existing": 0, "failed": 0 },
"enrollments": { "created": 1, "existing": 0 }
},
"items": [
{
"index": 0,
"identifier": "CMS-PAT-001",
"status": "success",
"patient": { "id": "f1a2...", "action": "created" },
"provider": { "id": "b3c4...", "npi": "1003000126", "action": "created" },
"payer": { "id": "d5e6...", "name": "Blue Cross Blue Shield", "action": "resolved" },
"coverage": { "id": "a7b8...", "action": "created" },
"claim": { "id": "c9d0...", "pcn": "WH-JD-M1K2N3-0", "action": "created" },
"enrollment": { "action": "created" }
}
]
}{
"success": true,
"code": "COMPLETED_WITH_ERRORS",
"message": "Processed: 2 new patient(s), 1 updated patient(s), 1 new claim(s), 1 updated claim(s)",
"webhook_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"processed": {
"patients": { "created": 2, "updated": 1, "existing": 0, "failed": 0 },
"claims": { "created": 1, "updated": 1, "existing": 0, "skipped": 0, "failed": 0 },
"providers": { "created": 0, "existing": 1, "failed": 0 },
"payers": { "resolved": 2, "not_found": 1 },
"coverages": { "created": 1, "updated": 1, "existing": 0, "failed": 0 },
"enrollments": { "created": 0, "existing": 1 }
},
"items": [
{
"index": 0, "identifier": "CMS-PAT-001", "status": "success",
"patient": { "id": "f1a2...", "action": "updated" },
"claim": { "id": "c9d0...", "pcn": "WH-JD-M1K2N3-0", "action": "updated" }
},
{
"index": 1, "identifier": "CMS-PAT-002", "status": "success",
"patient": { "id": "e3f4...", "action": "created" },
"claim": { "id": "g5h6...", "pcn": "WH-AB-M1K2N3-1", "action": "created" }
},
{
"index": 2, "identifier": "CMS-PAT-ERR", "status": "partial",
"patient": { "id": "i7j8...", "action": "created" },
"errors": [
{ "code": "PAYER_NOT_FOUND", "message": "Payer \"Totally Made Up Insurance\" not found..." }
]
}
],
"errors": [
"CMS-PAT-ERR: Payer \"Totally Made Up Insurance\" not found in payer directory..."
]
}{
"success": true,
"code": "IDEMPOTENCY_COMPLETED",
"message": "Payload already processed (idempotency key matched)",
"webhook_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}{
"success": false,
"code": "PAYLOAD_MISSING_PATIENTS",
"message": "Invalid payload. Expected \"patients\" array with at least one patient."
}{
"success": false,
"code": "TENANT_NOT_CONFIGURED",
"message": "Partner does not have a tenant configured. Contact support to set up your integration."
}{
"success": false,
"code": "AUTH_INVALID_KEY",
"message": "Invalid API key"
}{
"success": false,
"code": "LIMIT_PATIENTS",
"message": "Demo limit exceeded. You have 45 of 50 patients used and this request would add 10 more.",
"webhook_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}{
"success": false,
"code": "RATE_LIMIT_MINUTE",
"message": "Rate limit exceeded. Maximum 60 requests per minute."
}{
"success": false,
"code": "RATE_LIMIT_DAILY",
"message": "Daily rate limit exceeded. 10000/10000 requests today. Resets at midnight UTC."
}