What the Tebra API exposes, and what it does not
You need patient, appointment and billing data out of a Tebra (formerly Kareo) practice. There is no REST endpoint and no JSON. Tebra's help center page states: "Tebra's API is a SOAP-based web service." The method reference is a 129-page PDF, the Tebra API Integration Technical Guide. Both are public.
How access is granted
Access is tied to a customer account, not to a developer program. The guide states that a System Administrator on the Tebra account must generate a customer key and grant security permissions to a user. Every call carries a RequestHeader with three fields: CustomerKey, User and Password. The user is a normal Tebra login with API permission. There is no OAuth and no app registration.
Developers accept the Tebra API Terms of Use. The terms grant a revocable, non-transferable license. Section 4.4 says you may not use the API to replicate or compete with Tebra's core products. You may charge for your application. The terms mention limits on calls but do not define them; the technical guide does.
The public documentation does not state that a sandbox or test account exists. Testing happens against a customer account with the customer's permission.
Connecting
https://webservice.kareo.com/services/soap/2.1/KareoServices.svc?singleWsdl
Load the WSDL in a SOAP client to get typed request and response objects. XML special characters must be escaped in every field. The guide calls out the password field: an unescaped & in a password fails authentication.
Every response includes an ErrorResponse object with IsError, ErrorMessage and StackTrace, and a SecurityResponse object.
What is exposed
The guide documents these operations.
| Area | Read | Write |
|---|---|---|
| Patients | GetPatient, GetPatients | CreatePatient, UpdatePatient, UpdatePrimaryPatientCase |
| Appointments | GetAppointment, GetAppointments, GetAppointmentReasons | CreateAppointment, UpdateAppointment, UpdateAppointmentStatus, DeleteAppointment |
| Encounters and charges | GetEncounterDetails, GetCharges | CreateEncounter, UpdateEncounterStatus |
| Money | GetPayments, GetTransactions | CreatePayments |
| Documents | CreateDocument, DeleteDocument | |
| Reference | GetPractices, GetProviders, GetServiceLocations, GetProcedureCode |
The rate limit table also names GetAllPatients, SearchPatient, GetExternalVendors and GetThrottles. Those four have no section of their own in the guide.
Patients
GetPatients accepts FromLastModifiedDate and ToLastModifiedDate, so you can poll for changes. The help center recommends polling every 5 to 15 minutes for patient changes. Many entities carry an optional ExternalId that you fill with your own identifier and filter on later. Dates of birth are stored as YYYY-MM-DD.
Encounters and claims
There is no Claim operation. Tebra exposes claim data through GetCharges. Each charge row carries an ID the guide describes as "the unique identifier of the claim", plus AdjustedCharges, Receipts, PatientBalance, InsuranceBalance, TotalBalance, BilledTo and Status. Primary and secondary insurance company and plan names appear as billed-to fields. The guide maps each field to the Track Claim Status screen in Tebra.
CreateEncounter writes the encounter that Tebra turns into a claim. Encounter status values are Draft, Review, Approved and Rejected. UpdateEncounterStatus moves an encounter between them. The guide lists no operation to submit a claim to a payer and no operation to update a charge after it exists.
Payments
GetPayments and GetTransactions return posted money. CreatePayments posts a payment. The guide lists no operation that returns an electronic remittance advice (835) or a payer's claim status response.
Filters and field selection
The guide states that at least one filter is required on every Get operation. If you pass a start date you must pass the end date too. PracticeName is the recommended filter for all Get calls. Most Get requests accept a Fields object so you return only the columns you use. GetCharges defaults to a posting-date window of the last 7 days when you pass no dates.
Rate limits
Limits are per Tebra account and per operation. The guide lists them.
- GetPatients, GetAppointments, GetCharges, GetPayments, GetTransactions, UpdatePatient: 1 call per second.
- GetPatient, SearchPatient: 1 call every quarter second.
- GetAppointment, GetEncounterDetails, GetPractices, GetProviders, GetServiceLocations, GetProcedureCode, CreateAppointment, CreateEncounter, CreatePatient, CreatePayments, UpdateAppointment, UpdateEncounterStatus, DeleteAppointment: 1 call every half second.
- GetAllPatients, GetThrottles: 1 call every 5 seconds.
Past a limit you get a message such as 429: GetPatients endpoint requested more than allowed over time interval 1000 milliseconds. The guide says the list is subject to change. It also asks you to poll as rarely as you can, and gives every 2 hours as an example.
What is missing
- Push. The help center states: "No, Tebra does not automatically push information out to external systems." There are no webhooks. You poll.
- HL7. The help center states that HL7 messaging is not supported.
- Claim submission, claim status (276/277), eligibility (270/271) and remittance (835). None appear in the operation list.
- FHIR. The SOAP guide and the help center page do not mention a FHIR endpoint.
- A sandbox. The public documentation does not state one.
- Support for your code. Tebra states that it supports only the API side and does not debug integrator code. A support case needs the request and response XML attached.
If you need the same patient, encounter and claim fields from Tebra and from other systems in one schema, that is the problem TheFhirStorm solves.