Data Sync APIs (v2)
Our Data Sync APIs are perfect for integrating data from the RLDatix application into your BI Database via a JSON API. Looking for the v1 docs? See Data Sync APIs (v1).
The v2 API supports two authentication options. Pick whichever fits your integration; the same v2 endpoints accept both.
The api base domain is https://api.socialclimb.com.
- Content-Type header is required to be set as
application/json - All v2 endpoints live under
/v2/...(v1 lives under/v1/...— see Data Sync APIs (v1))
| Option | Best for | Mechanics |
|---|---|---|
| A. OAuth 2.0 with a signed JWT client assertion (RFC 7523) | Partners who can host a public JWKS and sign assertions with a private RSA key. Issues short-lived bearer access tokens. | Exchange a signed assertion at /oauth/token for an access token; send the access token on every data request. |
| B. Web Form API token | Partners who already use a Web Form API token for online submissions and want to use the same token for v2 reads. | Send your existing Web Form API token in the api-token header on every v2 request. No /oauth/token call needed. |
Note: Option B accepts Web Form API tokens specifically (generated at Settings → Web Forms — the same token type used for online submission endpoints). It does not accept the v1 Data Sync Account API Key (Preferences → Account API Key). If your integration uses the Account API Key today, choose Option A.
Both options call the same v2 endpoints. Choose A or B and follow the matching section below.
Run a Python script like the one below to generate an RSA key pair and a JWKS file:
# save as generate_keys.py
import json
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from jwt.algorithms import RSAAlgorithm
# Generate key pair
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
# Save private key PEM (you'll use this to sign assertions)
pem = private_key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption(),
)
with open("private_key.pem", "wb") as f:
f.write(pem)
# Build JWKS (you'll serve this at a URL)
public_jwk = json.loads(RSAAlgorithm.to_jwk(private_key.public_key()))
public_jwk["kid"] = "key-1"
public_jwk["use"] = "sig"
public_jwk["alg"] = "RS384"
jwks = {"keys": [public_jwk]}
with open("jwks.json", "w") as f:
json.dump(jwks, f, indent=2)
print("Generated private_key.pem and jwks.json")
print(f"\nPublic JWK kid: {public_jwk['kid']}")
Host jwks.json at a publicly reachable HTTPS URL — you’ll use it as jwk_url when creating the OAuth client.
In https://app.socialclimb.com, under Preferences → API / OAuth clients, create a new OAuth client. You will provide:
| Field | Description |
|---|---|
name |
Human-readable label for the client. |
jwk_url |
HTTPS URL serving a JWKS document that contains the public key for the private key you will sign client assertions with. Must be a globally routable HTTPS host — non-HTTPS, private IP, loopback, and cloud metadata addresses are rejected. |
On creation you will receive a client_id. You keep the matching private key on your side; RLDatix never sees it. To rotate keys, update the JWKS at the jwk_url — no changes in RLDatix are needed.
Sign a JWT with your private key using RS384. Claim set:
| Claim | Value |
|---|---|
iss |
your client_id |
sub |
your client_id |
aud |
https://api.socialclimb.com/oauth/token |
iat |
current Unix timestamp |
exp |
iat + a short lifetime. exp - iat must be ≤ 300 seconds (5 minutes); longer assertions are rejected. |
jti |
unique id (e.g. a UUID). Standard claim; include a fresh value per assertion. |
The signing key’s kid must be present in the JWKS at your jwk_url so RLDatix can select the right public key.
POST /oauth/token — Content-Type: application/x-www-form-urlencoded.
Form body:
| Param | Value |
|---|---|
grant_type |
client_credentials |
client_assertion_type |
urn:ietf:params:oauth:client-assertion-type:jwt-bearer |
client_assertion |
the signed JWT from Step 2 |
curl -X POST https://api.socialclimb.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
--data-urlencode "client_assertion=eyJhbGciOiJSUzM4NCIs..."
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": ""
}
The access_token is an HS256-signed JWT issued by RLDatix. expires_in is the lifetime in seconds. Treat the access token as opaque — do not parse it in your client; just replay it.
Token endpoint errors:
| HTTP | When |
|---|---|
| 400 | grant_type is not client_credentials or client_assertion_type is missing/wrong. |
| 401 | Assertion signature fails, client is unknown/disabled/revoked, or the account is disabled. The response body carries a generic Client authentication failed. message — detailed reasons are logged server-side only. |
Send the access token on every data request in the Authorization header:
curl --header "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
--header "Content-Type: application/json" \
https://api.socialclimb.com/v2/locations
Run the command above to quickly test authorization. Requests without a valid bearer token return 401 Invalid or expired OAuth access token. Requests from a disabled or revoked client, or against a disabled account, also return 401.
When the access token expires, exchange a new client assertion at /oauth/token and reuse the new access token until it expires. You do not need a fresh access token per request.
If you have a Web Form API token (used today for online submission endpoints), the same token authenticates to v2 endpoints. Generate or manage tokens in Settings → Web Forms.
This is not the same as the v1 Data Sync Account API Key (the one from Preferences → Account API Key). The Account API Key authenticates v1 Data Sync only; for v2 it does not work — use Option A instead.
Send your token in the api-token HTTP header on every v2 request:
curl --header "api-token: <your_web_form_token>" \
--header "Content-Type: application/json" \
https://api.socialclimb.com/v2/locations
No call to /oauth/token is needed — the token is the credential. Requests with an unknown, disabled, or expired token return 401 Invalid or expired OAuth access token. Requests against a disabled account also return 401.
To rotate, generate a new token in the Web Forms settings page, switch your integration over, and disable the old one. The token is account-scoped, so guard it like any other secret.
- Authentication — Two options. With Option A, exchange a signed JWT assertion for a short-lived bearer access token sent on every call (no account-scoped secret stored in your code). With Option B, send a Web Form API token in the
api-tokenheader on every v2 request. Note that the v1 Data Sync Account API Key (Preferences → Account API Key) does not authenticate to v2 — those integrations should switch to Option A. - Base path —
/v2/...instead of/v1/.... Endpoint shapes and response bodies are otherwise the same as v1. - Scoping filters — the Reviews, NPS Surveys, Survey Responses, and Invites endpoints gain optional
location_id,provider_id,group_id, andcustom_filtersquery parameters (see Filtering results). v1 returned the full account-scoped dataset and expected you to filter client-side.
Several v2 endpoints accept optional scoping filters and a custom-field filter on the query string. Endpoints that support filtering explicitly say so in their section below. They are:
/v2/reviews/v2/surveys(NPS Surveys)/v2/survey-responses/v2/invites
Other endpoints ignore these parameters.
| Parameter | Type | Description |
|---|---|---|
location_id |
comma-separated integers | Restrict results to rows matching any of the listed RLDatix location IDs. |
provider_id |
comma-separated integers | Restrict results to rows matching any of the listed RLDatix provider IDs. |
group_id |
comma-separated integers | Restrict results to rows in any of the listed RLDatix groups. |
Combination rules:
- Within a single parameter the list is OR-ed (
location_id=1,2means locations 1 or 2). - Across parameters the filters are AND-ed (
location_id=1,2&provider_id=9means (location 1 OR 2) AND provider 9).
Ownership check: every ID is verified to belong to the caller’s account. If any ID does not, the API returns 400 Unknown location_id(s)/provider_id(s)/group_id(s) for this account: [...]. This prevents probing IDs that belong to other tenants.
Integer validation: any non-integer list member returns 400 Invalid integer in list: '<value>'.
Partners who use RLDatix custom fields (the EAV surface underneath Invites / Reviews) can filter by custom-field value using the custom_filters query parameter. The value is a URL-encoded JSON object whose keys are of the form custom_fields.<field_name>.
| Key shape | Value shape (same as UI params["filters"] entries) |
Meaning |
|---|---|---|
custom_fields.<name> |
["eq", "Office"] |
Exact match |
custom_fields.<name> |
["in_", ["A", "B"]] |
Match any of the listed values |
<field_name> must match [A-Za-z0-9_]+. Any other key shape returns 400 Invalid custom_filters key.
Example — filter by appointment_type and referral_source:
{"custom_fields.appointment_type": ["eq", "Office"],
"custom_fields.referral_source": ["in_", ["Web", "Phone"]]}
URL-encoded (abbreviated):
?custom_filters=%7B%22custom_fields.appointment_type%22%3A%5B%22eq%22%2C%22Office%22%5D%7D
Errors:
| HTTP | When |
|---|---|
| 400 | custom_filters is not valid JSON. |
| 400 | custom_filters top-level value is not a JSON object. |
| 400 | A key does not match custom_fields.<field_name>. |
Scoping filters and custom_filters may be used together on the same request. They combine with AND semantics — the result is the intersection of the scoping predicate and the custom-field predicate.
RLDatix reviews are a normalized set of all reviews aggregated and normalized from other platforms.
Get All Reviews
This endpoint retrieves all reviews
HTTP Request
GET /v2/reviews
- date is optional and limits the results to the next 24hrs after if no end date is provided
- end is optional. If no start date is provided, results will include all reviews up to the end date.
- rating is optional. Use a comma separated list of all ratings that should be included in the results
location_id,provider_id,group_id, andcustom_filtersare optional — see Filtering results.- Response is sorted by
create_timedesc
- Example:
GET /v2/reviews?date=2020-09-01&end=2020-09-30&rating=1,2,3 - Example (scoped):
GET /v2/reviews?date=2020-09-01&end=2020-09-30&location_id=12,34&provider_id=56
- The example above will return all reviews with a rating of 1, 2, or 3 and were received between September 1st, 2020 and September 30th, 2020
Response
| Name | Type | Description |
|---|---|---|
| comment | string | Email or phone number survey was sent to |
| create_time | string | Date survey was submitted. Example: 2017-05-04T18:22:22+00:00 |
| external_location_ids | array | Array of eid given to survey’s location |
| external_provider_ids | array | Array of eid of survey provider |
| groups | array | Array of group_id of survey |
| invite_name | string | Name of survey recipient |
| invite_type | string | Contact info type of survey. sms or email |
| location | number | Total for this location/month/type combination. |
| location_id | number | location_id of survey location |
| location_oid | string | location_oid of survey location |
| message | string | Name of provider of invite |
| nps_rating | number | Overall nps rating of survey |
| platform | string | Name of survey |
| provider | string | Name of provider of invite |
| provider_id | number | Id of provider of invite |
| question_id | string | Descriptive name of question |
| rating (optional) | number | Overall rating of survey |
| review_id | number | Id of review |
| reviewer | string | Reviewer’s name |
| sent_at | string | Date and time survey invite was sent 2024-05-14T18:45:03Z |
| sent_to | string | Email or phone number invite was sent to |
JSON Response
{
"items": [
{
"comment": "Review text comment",
"create_time": "2017-05-04T18:22:22+00:00",
"external_location_ids": ["OFFICE_EXT_NAME", "EXAMPLE_ID", "EXAMPLE3"],
"external_provider_ids": ["NPI", "EXAMPLE_ID", "EXAMPLE3"],
"invite_name": "Customer's name",
"invite_type": "sms|email",
"location": "Location's name",
"location_id": 123456789,
"location_oid": "Location identifier",
"message": "Provider's Name",
"nps_rating": 10.0,
"provider": "Provider's Name",
"provider_id": "Provider's Id",
"question_id": "Recommend",
"platform": "Google|Facebook|...",
"rating": 5,
"review_id": "...",
"reviewer": "Reviewer's name",
"sent_at": "2017-05-04T18:24:58+00:00",
"sent_to": "8005550000|john@doe.com"
}
]
}
RLDatix Invites are the record of a patient visit and corresponding patient interaction with the survey or review platform.
This endpoint retrieves all invites
HTTP Request
GET /v2/invites?date=2017-07-01T00:00:00Z
- date is optional and limits the results to the next 24hrs after
location_id,provider_id,group_id, andcustom_filtersare optional — see Filtering results.- Response is sorted by
sent_atdesc
- Example (scoped):
GET /v2/invites?date=2024-01-01T00:00:00Z&group_id=42
JSON Response
{
"items": [
{
"clicked": [
{
"created_at": "2017-03-02 05:43:51+00:00",
"name": "Google|Facebook|..."
}
],
"customer_name": "John Smith",
"extras": {
"test": "A",
"address": "Stonebrick ln"
},
"location": "Location's name",
"location_oid": "Location's identifier",
"location_id": "Location's Id",
"provider": "Provider's Name",
"provider_id": "Provider's Id",
"external_provider_ids": ["NPI", "EXAMPLE_ID", "EXAMPLE3"],
"external_location_ids": ["OFFICE_EXT_NAME", "EXAMPLE_ID", "EXAMPLE3"],
"message": "RLDatix message name used in invite",
"opened": "2017-03-02 05:43:36+00:00",
"platform": "Google|Facebook|...",
"proceeded_to_review": true,
"review_rating": 5,
"sent_at": "2017-07-02 03:35:19+00:00",
"sent_by": "",
"sent_to": "5554443333|john@doe.com",
"status": "sent",
"type": "sms|email"
}
]
}
RLDatix Calls are the recorded instance of prospects having called a RLDatix Call Tracker in a Marketing Campaign.
This endpoint retrieves all Calls.
HTTP Request
GET /v2/calls
start_dateis optional and limits the results to the next 24 hrs after if noend_dateis provided.end_dateis optional. If nostart_dateis provided, results will include all calls up to the end date.- Response is sorted by
Call Datedesc
- Example:
GET /v2/calls?start_date=2022-09-01&end_date=2022-09-30
- The example above will return all calls that were received on or after September 1st, 2022 and before September 30th, 2022
JSON Response
{
"items": [
{
"appt_date": "---",
"call_date": "9/22/2022 11:06 pm",
"campaign": "Campaign Name",
"channel": "Organic Search",
"from_number": "8019982830",
"location_name": "---",
"new_patient": false,
"patient_id": "UNKNOWN",
"patient_name": "UNKNOWN",
"provider": "---",
"source": "Google Business Profiles",
"tracking_number": "8019982830"
}
]
}
Get Conversions
This endpoint retrieves Conversions. Conversions can be either a Call to RLDatix’s Call Tracker or an Online submission from a RLDatix integrated partner.
HTTP Request
GET /v2/conversions
start_dateis optional and limits the results to the next 24 hrs after if noend_dateis provided.end_dateis optional. If nostart_dateis provided, results will include all conversions up to the end date.modified_sinceis optional. It cannot be used with astart_date. Will return conversions that have been created or have been modified since the given date. Filters on themodified_atdate. See the section below on using this to keep your data up to date.- Response is sorted by
datedesc
- Example:
GET /v2/conversions?start_date=2022-09-01&end_date=2022-09-30
- The example above will return all conversions that were recorded on or after September 1st, 2022 and before September 30th, 2022
- Example:
GET /v2/conversions?modified_since=2022-09-30
- The example above will return all conversions that were created or have been modified on or after September 30th, 2022
| Field | Description |
|---|---|
| conversion_id | The unique identifier of the conversion |
| *appt_date | The date of the patient’s appointment that occurred after the conversion event |
| campaign | The marketing campaign that generated the conversion |
| channel | The marketing channel that generated the conversion |
| date | The date the call or submission occurred |
| from_number | The patient’s phone number |
| *location_name | The location of the patient’s appointment |
| new_patient | The new_patient flag is set to True if, at the time the call or submission occurred, we haven’t seen any previous appointments (invites) on that account with the given phone number. |
| *patient_id | The patient id from the corresponding appointment |
| *patient_name | Name of the patient |
| *provider | The name of provider that saw the patient |
| source | The marketing source that generated the conversion |
| tracking_number | The tracking number that the patient called |
| type | Can be one of the following values: “Call”, “Online”, “App” |
| modified_at | The date of the last modification. Will be the date the conversion was created until it becomes associated with an appointment, at which point the date of that association will populate this field |
*These fields are only populated after the conversion gets associated with an appointment for the patient. Unpopulated values mean that an appointment for the patient hasn’t occurred after the given conversion event.
JSON Response
{
"items": [
{
"appt_date": "---",
"campaign": "Your Campaign Name",
"channel": "Organic Search",
"conversion_id": "123456_Call",
"date": "9/22/2022 11:06 pm",
"from_number": "8019982830",
"location_name": "---",
"modified_at": "9/24/2022 12:37 pm",
"new_patient": false,
"patient_id": "UNKNOWN",
"patient_name": "UNKNOWN",
"provider": "---",
"source": "Google Business Profiles",
"tracking_number": "8019982830",
"type": "Call"
}
]
}
Using modified_since Parameter to Get Updates
Conversion data is a living dataset. When a new conversion is associated with an existing appointment, the order of associations along with other details are changed.
You can use the modified_since parameter to keep your data up to date and track any changes/modifications. After pulling initial data, use the modified_since paramater to pass in the date of your last data pull to get all the changes that may have occurred since then. Track the conversions with their unique conversion_id and update any that are retrieved using this parameter.
This endpoint retrieves Campaigns data for the account over a specified time period.
HTTP Request
GET /v2/campaigns
start_dateandend_dateparameters are both required.- Response is grouped by campaign channel
- Example:
GET /v2/campaigns?start_date=2022-09-01&end_date=2022-09-30
- The example above will return the Campaigns data for the specified time period, grouped by campaign channel.
JSON Response
{
"items": [
{
"Appointments": "16",
"Assists": "20",
"Channel": "Paid Search",
"Conversions": "40",
"Cost": "$320.00",
"Cost/Appt": "20",
"Cost/Assist": "16",
"Cost/Conversion": "8",
"Cost/Patient": "25",
"Estimated Revenue": "$4600.00",
"New Patients": "8",
"ROAS": "140%"
}
]
}
This endpoint retrieves a list of Survey names and IDs for the account.
HTTP Request
GET /v2/surveys-list
- This endpoint does not take any additional parameters.
JSON Response
{
"items": [
{
"id": 99999,
"name": "Survey Name"
}
]
}
This endpoint retrieves survey responses for a particular survey.
HTTP Request
GET /v2/survey-responses
- The
survey_idparameter is required. Survey IDs can be obtained using the Surveys List endpoint. start_dateis optional. If provided, results will include all records after this date.end_dateis optional. If provided, results will include all records before this date.location_id,provider_id,group_id, andcustom_filtersare optional — see Filtering results.- Response fields will vary according to the fields on the survey.
- Response is sorted by
whendesc
- Example:
GET v2/survey-responses?start_date=2022-09-01&end_date=2022-09-30&survey_id=99999 - Example (scoped):
GET v2/survey-responses?survey_id=99999&location_id=12,34
- The example above will return all responses for survey
99999that were submitted on or after September 1, 2022 and before September 30, 2022.
Response
| Name | Type | Description |
|---|---|---|
| appointment_date | string | Date of appointment |
| contact | string | Email or phone number survey was sent to |
| groups | array | Array of group_id of survey |
| location | number | Total for this location/month/type combination. |
| location_id | number | location_id of survey location |
| npi | string | Nation Provider ID |
| overall | number | Overall rating of survey |
| patient_first | string | Patient’s first name |
| patient_name | string | Patient’s full name |
| patient_id | string | Patient id |
| patient_last | string | Patient last name |
| provider | string | Provider name |
| state | string | State in address of Google Business Profile |
| survey_date | string | Date survey was submitted. Example: 1/1/2024 12:00:00 pm |
| user | string | Patient’s full name |
| user_id | string | Patient id |
| *additional rows | any | Each survey will also add a key/value pair for each question’s descriptive name and answer value. Example: {“experience”: “Very Good”} |
JSON Response
{
"items": [
{
"appointment_date": "8/30/22 12:00:00 pm",
"contact": "8019982830",
"groups": [
1234,
2345,
3456
],
"location": "Clinic Location",
"location_id": 123456,
"npi": null,
"overall": 5.0,
"patient_first": "FirstName",
"patient_name": "FirstName LastName",
"patient_id": "123456",
"patient_last": "LastName",
"provider": "Provider Name, MD",
"state": "UT",
"survey_date": "1/1/22 12:00:01 am",
"user": "FirstName LastName",
"user_id": "123456"
}
]
}
RLDatix NPS Surveys is an endpoint dedicated to pulling NPS responses from patients.
Get All NPS Surveys
This endpoint retrieves all NPS surveys. The body is very similar to the review api but with the addition of nps_rating and question_id.
HTTP Request
GET /v2/surveys
- date is optional and limits the results to the next 24hrs after if no end date is provided
- end is optional. If no start date is provided, results will include all surveys up to the end date.
- rating is optional. Use a comma separated list of all ratings that should be included in the results
location_id,provider_id,group_id, andcustom_filtersare optional — see Filtering results.- Response is sorted by
create_timedesc
- Example:
GET /v2/surveys?date=2020-09-01&end=2020-09-30&rating=1,2,3 - Example (scoped):
GET /v2/surveys?date=2020-09-01&end=2020-09-30&group_id=7,8
- The example above will return all surveys with a rating of 1, 2, or 3 and were received between September 1st, 2020 and September 30th, 2020
Response
| Name | Type | Description |
|---|---|---|
| comment | string | Email or phone number survey was sent to |
| create_time | string | Date survey was submitted. Example: 2017-05-04T18:22:22+00:00 |
| external_location_ids | array | Array of eid given to survey’s location |
| external_provider_ids | array | Array of eid of survey provider |
| groups | array | Array of group_id of survey |
| invite_name | string | Name of survey recipient |
| invite_type | string | Contact info type of survey. sms or email |
| location | number | Total for this location/month/type combination. |
| location_id | number | location_id of survey location |
| location_oid | string | location_oid of survey location |
| message | string | Name of provider of invite |
| nps_rating | number | Overall nps rating of survey |
| platform | string | Name of survey |
| provider | string | Name of provider of invite |
| provider_id | number | Id of provider of invite |
| question_id | string | Descriptive name of question |
| rating (optional) | number | Overall rating of survey |
| review_id | number | Id of review |
| reviewer | string | Reviewer’s name |
| sent_at | string | Date and time survey invite was sent 2024-05-14T18:45:03Z |
| sent_to | string | Email or phone number invite was sent to |
JSON Response
{
"items": [
{
"comment": "Review text comment",
"create_time": "2017-05-04T18:22:22+00:00",
"external_location_ids": ["OFFICE_EXT_NAME", "EXAMPLE_ID", "EXAMPLE3"],
"external_provider_ids": ["NPI", "EXAMPLE_ID", "EXAMPLE3"],
"invite_name": "Customer's name",
"invite_type": "sms|email",
"location": "Location's name",
"location_id": 123456789,
"location_oid": "Location identifier",
"message": "Provider's Name",
"nps_rating": 10.0,
"provider": "Provider's Name",
"provider_id": "Provider's Id",
"question_id": "Recommend",
"platform": "Google|Facebook|...",
"rating": 5,
"review_id": "...",
"reviewer": "Reviewer's name",
"sent_at": "2017-05-04T18:24:58+00:00",
"sent_to": "8005550000|john@doe.com"
}
]
}
The Insights API allows you to retrieve monthly aggregated data by Google Business Profile.
Request
GET /v2/insights/byMonth
{}
Response
| Name | Type | Description |
|---|---|---|
| location_id | number | Location Id |
| month | number | Number representing the month. Format: YYYYMM. |
| metric_type | string | Enum: views_maps, views_search, actions_website, actions_phone, actions_driving_directions |
| count | number | Total for this location/month/type combination. |
[
{
"location_id": 12345,
"month": 202303,
"metric_type": "views_maps",
"count": 123
}
]
Returns CAHPS parsed appointment files for the account (one object per uploaded file). Data matches the CAHPS Parsed Files UI grid. Use file_id from the list response to fetch per-file warning rows.
HTTP Request
GET /v2/cahps-parsed-files
Query parameters
| Parameter | Type | Description |
|---|---|---|
start_date |
string | Required. Filter by file created_at on or after this date (e.g. 2025-06-01). |
end_date |
string | Required. Filter by file created_at on or before this date (e.g. 2025-06-30). |
cahps_type |
string | Optional. Restrict to OASCAHPS or HCAHPS. |
- Both
start_dateandend_dateare required. Omitting either returns400. - Invalid date values return
400. - Results are ordered by
created_atdescending (newest first). - Results are scoped to the authenticated account.
- Example:
GET /v2/cahps-parsed-files?start_date=2025-06-01&end_date=2025-06-30 - Example (filtered):
GET /v2/cahps-parsed-files?start_date=2025-06-01&end_date=2025-06-30&cahps_type=OASCAHPS
Response (top-level)
| Name | Type | Description |
|---|---|---|
| items | array | List of parsed-file objects (see below). |
Response (each object in items)
| Name | Type | Description |
|---|---|---|
| file_id | number | Parsed file ID. |
| integration_connection | string | Name of the integration connection that produced the file, if any. |
| file_transform | string | Name of the file transform applied, if any. |
| download_status | string | File processing status (e.g. Done, Pending, Started). |
| is_test | boolean | Whether this is a test file. |
| cahps_type | string | OASCAHPS or HCAHPS. |
| total_patients | number | Total patient rows in the file. |
| warnings_count | number | Count of rows flagged with file-level warnings. |
| created_at | string | Date and time the appointment data for this file was uploaded |
| created_by | string | Email of the user who uploaded the file, or “system” for auto uploads. |
JSON Response
{
"items": [
{
"file_id": 15556,
"integration_connection": "My SFTP",
"file_transform": "OAS CAHPS Transform",
"download_status": "Done",
"is_test": false,
"cahps_type": "OASCAHPS",
"total_patients": 1398,
"warnings_count": 12,
"created_at": "2025-06-30T14:22:00+00:00",
"created_by": "user@example.com"
}
]
}
Returns warning and error rows for a single parsed file. Data matches the File Warnings detail page in the CAHPS Parsed Files UI.
HTTP Request
GET /v2/cahps-parsed-files/<file_id>/warnings
file_idis thefile_idfrom the list endpoint.- Returns
404if the file does not exist on this account
- Example:
GET /v2/cahps-parsed-files/15556/warnings
Response (top-level)
| Name | Type | Description |
|---|---|---|
| file_id | number | Parsed file ID. |
| cahps_type | string | OASCAHPS or HCAHPS. |
| records | array | Warning rows for this file (see below). |
Response (each object in records)
| Name | Type | Description |
|---|---|---|
| id | number | Warning record ID. |
| patient_id | string | Patient identifier from the parsed file row. |
| patient_info | object | Parsed row fields for this patient (shape varies by CAHPS type; may include first_name, last_name, location_name, and other columns from the source file). |
| location_name | string | The name of the location for this appointment record as it was sent |
| row_note | string | Human-readable summary of issues (same text as the ROW NOTE column in the UI). |
| notes | object | Structured warning metadata. May include discovered_defects, warnings, and notes_string. |
JSON Response
{
"file_id": 15556,
"cahps_type": "OASCAHPS",
"records": [
{
"id": 882341,
"patient_id": "PAT-001",
"patient_info": {
"first_name": "Jane",
"last_name": "Doe",
"location_name": "Clinic A"
},
"location_name": "Clinic A",
"row_note": "Warnings: Missing email Optional detail",
"notes": {
"warnings": "Missing email",
"notes_string": "Optional detail"
}
}
]
}
Returns a list of PX (Integration Import) runs for the account (one object per run). Data matches what is shown in the Integration Imports UI grid. Each item is one run; the API does not return a single aggregated summary.
HTTP Request
GET /v2/integration-imports
Query parameters (all optional)
| Parameter | Type | Description |
|---|---|---|
| start_date | string | Filter by run’s start_date on or after this date (e.g. 2025-06-01). |
| end_date | string | Filter by run’s start_date on or before this date (e.g. 2025-06-30). |
| show_test_runs | boolean | If true, include test runs and add is_test to each item. Default: false. |
- If only
start_date: runs withstart_date>= start_date. - If only
end_date: runs withstart_date<= end_date. - If both: runs with
start_datebetween the two (inclusive). - By default, test runs (
is_test=true) are excluded. Useshow_test_runs=trueto include them. - Results are ordered by run ID descending (newest first).
- Counts of integration errors by type for both appointments and invites are included if present. If either one does not have any errors, that section will return
{}in theerrorssegment of the response.
- Example:
GET /v2/integration-imports?start_date=2025-06-01&end_date=2025-06-30 - Example:
GET /v2/integration-imports?show_test_runs=true
Response (top-level)
| Name | Type | Description |
|---|---|---|
| items | array | List of run objects (see below). |
Response (each object in items)
| Name | Type | Description |
|---|---|---|
| import_id | number | Integration import ID. |
| rows_processed | number | Total rows in the import. |
| mismatches | number | Mismatch count. |
| warnings | number | Warning count. |
| errors | object | Error counts by error type for both appointments and invites. |
| - appointments | object | Map of error type to row count for appointment-level issues. Keys match error_types on the Appointments detail endpoint. |
| - invites | object | Map of error type to row count for invite-level issues. Keys match error_types on the Invites detail endpoint. |
| is_test | boolean | (Only when show_test_runs=true) Whether this is a test run. |
| appointment_captured | number | Appointment count. |
| new_patients | number | New patient count. |
| scheduled_invites | number | Invites scheduled. |
| skipped_appointments | number | Appointments skipped. |
| skipped_invites | number | Invites skipped. |
| start_date | string | ISO 8601 start of data range. |
| end_date | string | ISO 8601 end of data range. |
| upload_date | string | Upload date (YYYY-MM-DD HH:mm:ss). |
JSON Response (default, no test runs)
{
"items": [
{
"import_id": 9896,
"rows_processed": 1398,
"mismatches": 136,
"warnings": 0,
"errors": {
"appointments": {
"provider_mismatch": 12,
"duplicate_appointment": 4
},
"invites": {
"missing_contact": 3,
"duplicate_invite": 1
}
},
"appointment_captured": 356,
"new_patients": 142,
"scheduled_invites": 149,
"skipped_appointments": 0,
"skipped_invites": 0,
"start_date": "2025-06-30T00:00:00+00:00",
"end_date": "2025-06-30T00:00:00+00:00",
"upload_date": "2025-06-30 00:00:00"
}
]
}
JSON Response (with show_test_runs=true)
When show_test_runs=true, each item includes an is_test field:
{
"items": [
{
"import_id": 9897,
"rows_processed": 100,
"mismatches": 0,
"warnings": 0,
"errors": {
"appointments": {},
"invites": {}
},
"is_test": true,
"appointment_captured": 50,
"new_patients": 20,
"scheduled_invites": 30,
"skipped_appointments": 0,
"skipped_invites": 0,
"start_date": "2025-06-30T00:00:00+00:00",
"end_date": "2025-06-30T00:00:00+00:00",
"upload_date": "2025-06-30 00:00:00"
}
]
}
Returns appointment-level error and warning rows for a single PX (Integration Import) run. Data matches the Appointments tab on the Integration Import details page. Obtain import_id from GET /v2/integration-imports.
HTTP Request
GET /v2/integration-imports/<import_id>/appointments
Query parameters (all optional)
| Parameter | Type | Description |
|---|---|---|
error_types |
string | Comma-separated list of error types to include. Values should come from the keys in the base /integration-imports API’s errors section (e.g. provider_mismatch, duplicate_appointment). Unknown values return 400. |
- Returns only appointment rows from the integration import with errors (appointment-day rules, duplicate appointments, missing DOB/state, and shared types such as provider/location mismatch when the underlying action is an appointment).
- Returns
404if the import does not exist on the authenticated account.
- Example:
GET /v2/integration-imports/9896/appointments - Example (filtered):
GET /v2/integration-imports/9896/appointments?error_types=provider_mismatch,duplicate_appointment
Examples of error_types values
provider_mismatch, location_mismatch, silenced, duplicate_appointment, appointment_day_rule, appointment_date, stops, invite_day_rule, duplicate_invite, missing_contact, reviewer_name, monitoring_only, missing_date_of_birth, missing_state
Response (top-level)
| Name | Type | Description |
|---|---|---|
| import_id | number | Integration import ID. |
| upload_date | string | Upload date (YYYY-MM-DD HH:mm:ss). |
| records | array | Error rows (see below). |
Response (each object in records)
| Name | Type | Description |
|---|---|---|
| id | number | Error record ID. |
| error_type | string | Snake_case error type (e.g. provider_mismatch). |
| error_level | string | error or warning. |
| patient_name | string | Patient name from the import row. |
| patient_id | string | Patient identifier from the import row. |
| appointment_date | string | ISO 8601 appointment date, when present. |
| location_name | string | Location name from the import row. |
| provider | string | Provider name from the import row. |
| phone | string | Best available phone number from the import row. |
| string | Email from the import row. | |
| date_of_birth | string | ISO 8601 date of birth, when present. |
| state | string | Two-letter USPS abbreviation for State from the import row. |
| match_info | object | (Optional) Additional match metadata when present on the error. |
JSON Response
{
"import_id": 9896,
"upload_date": "2025-06-30 00:00:00",
"records": [
{
"id": 44102,
"error_type": "provider_mismatch",
"error_level": "error",
"patient_name": "Jane Doe",
"patient_id": "PAT-APPT",
"appointment_date": "2025-06-20T00:00:00+00:00",
"location_name": "Clinic A",
"provider": "Dr Smith",
"phone": "5551112222",
"email": "jane@example.com",
"date_of_birth": null,
"state": null
},
{
"id": 44103,
"error_type": "duplicate_appointment",
"error_level": "error",
"patient_name": "Jane Doe",
"patient_id": "PAT-APPT",
"appointment_date": "2025-06-20T00:00:00+00:00",
"location_name": "Clinic A",
"provider": "Dr Smith",
"phone": "5551112222",
"email": "jane@example.com",
"date_of_birth": null,
"state": null
}
]
}
Returns invite-level error and warning rows for a single PX Integration Import run. Data matches the Invites tab on the Integration Import details page. Obtain import_id from GET /v2/integration-imports.
HTTP Request
GET /v2/integration-imports/<import_id>/invites
Query parameters (all optional)
| Parameter | Type | Description |
|---|---|---|
error_types |
string | Comma-separated list of error types to include (e.g. duplicate_invite, missing_contact). Unknown values return 400. |
- Returns only invite rows in the integration import with errors (invite-day rules, duplicate invites, stops, monitoring-only, and shared types such as provider/location mismatch when the underlying action is an invite).
- Returns
404if the import does not exist on the authenticated account.
- Example:
GET /v2/integration-imports/9896/invites - Example (filtered):
GET /v2/integration-imports/9896/invites?error_types=missing_contact
Response (top-level)
| Name | Type | Description |
|---|---|---|
| import_id | number | Integration import ID. |
| upload_date | string | Upload date (YYYY-MM-DD HH:mm:ss). |
| records | array | Error rows (see below). |
Response (each object in records)
Same fields as Integration Import Appointments.
JSON Response
{
"import_id": 9896,
"upload_date": "2025-06-30 00:00:00",
"records": [
{
"id": 44110,
"error_type": "provider_mismatch",
"error_level": "error",
"patient_name": "John Invite",
"patient_id": "PAT-INV",
"appointment_date": null,
"location_name": "Clinic B",
"provider": "Dr Jones",
"phone": null,
"email": "john@example.com",
"date_of_birth": null,
"state": null
},
{
"id": 44111,
"error_type": "duplicate_invite",
"error_level": "error",
"patient_name": "John Invite",
"patient_id": "PAT-INV",
"appointment_date": null,
"location_name": "Clinic B",
"provider": "Dr Jones",
"phone": null,
"email": "john@example.com",
"date_of_birth": null,
"state": null
},
{
"id": 44112,
"error_type": "missing_contact",
"error_level": "warning",
"patient_name": "John Invite",
"patient_id": "PAT-INV",
"appointment_date": null,
"location_name": "Clinic B",
"provider": "Dr Jones",
"phone": null,
"email": "john@example.com",
"date_of_birth": null,
"state": null
}
]
}
Errors (missing or invalid Authorization: Bearer token, wrong Content-Type, or disabled account) follow the same behavior as other Data Sync endpoints.
A RLDatix Location is an aggregation of public location profiles & listings.
This endpoint retrieves all locations
HTTP Request
GET /v2/locations
JSON Response
{
"items": [
{
"id": 1,
"location_name": "name",
"external_location_ids": ["external_id_1", "external_id_2"]
}
]
}
A RLDatix Platform is a public review platform such as Google Business Profiles, Apple, Yelp, Facebook, etc.
This endpoint retrieves all platforms
HTTP Request
GET /v2/platforms
JSON Response
{
"items": [
{
"active": true,
"id": 90238,
"is_survey": false,
"name": "Google"
},
{
"active": true,
"id": 90239,
"is_survey": false,
"name": "Yelp"
},
{
"active": true,
"id": 91230,
"is_survey": false,
"name": "Facebook"
},
{
"active": true,
"id": 91232,
"is_survey": false,
"name": "Private"
},
{
"id": 100143,
"is_survey": true,
"name": "Survey #2"
}
]
}
RLDatix Messages is the configuration of the message patients receive including text message and invite experience.
This endpoint retrieves all messages
HTTP Request
GET /v2/messages
JSON Response
{
"items": [
{
"id": 52345,
"name": "Physical Therapy Patient Sat",
"languages": {
"en": {
"key": "en",
"message":
"{customer.firstname},\nThank you for choosing {account.name}. Please take a minute and leave me feedback at the link below.\n{user.name}"
},
"es": {
"key": "es",
"message":
"{customer.firstname},\nGracias por usar {account.name}. Por favor, deje un comentario en el siguiente enlace.\n{user.name}"
}
}
}
]
}
RLDatix Groups serve as a means to categorize locations and associated providers within the system. These groupings facilitate streamlined report filtering and administrative delegation within the RLDatix application.
This endpoint retrieves all groups within the account, along with the providers and locations affiliated with each group. The children generally serve as a bridge between providers and the locations where they operate.
HTTP Request
GET /v2/groups
Response
| Name | Type | Description |
|---|---|---|
| id | number | Unique identifier for the group. |
| name | string | Name of the group. |
| providers | array | List of providers associated with the group. |
| - id | number | Unique identifier for the provider. |
| - name | string | Unique identifier for the provider. |
| - external_provider_ids | array | List of external ids for provider. |
| locations | array | List of locations associated with the group. |
| - id | number | Unique identifier for the location. |
| - name | string | Name of the location. |
| - formatted | string | Formatted address of the location. |
| - external_location_ids | array | List of external ids for location. |
| - children | array | List of child entities associated with the location, typically providers. |
| - - id | number | Unique identifier for the child location entity. |
| - - name | string | Name of the child location entity. |
| - - formatted | string | Formatted address of the child entity’s location. |
| - - provider_id | number | Unique identifier for the connected provider entity. |
{
"items": [
{
"id": 5231652,
"name": "Physical Therapy North",
"providers":
[
{
"id": 12412525,
"name": "Dr. Tommy"
}
],
"locations":
[
{
"formatted": "123 S Decatur, Las Vegas, NV, 89107",
"id": 347347,
"name": "Example Therapy Office",
"children": [
{
"provider_id": 12412525,
"formated": "123 S Decatur Suite #201, Las Vegas, NV, 89107",
"id": 452346,
"name": "Dr. Tommy"
}
]
}
]
}
]
}