Overview
In the event that your use case requires the use of a custom form, the following guide provides insight on how to properly configure and integrate a custom intake form with Tellescope. For a sample form response payload, please reach out to support@tellescope.com.
Form Mapping
Within Tellescope, you will need to create a form with at least one question field. The field can be left blank. The purpose of this form is for mapping responses. You'll need to grab the form ID, which is located in the URL for the form you created.
Webhook URL
The Webhook URL should be formatted as follows:
https://api.tellescope.com/v1/webhooks/formsort/submit?formId=FORM_ID_HERE
Replace FORM_ID_HERE with the ID corresponding to the form you created above.
Webhook Authentication
Requests must include your API key as an Authorization header, using the API_KEY scheme:
Authorization: API_KEY YOUR_API_KEY_HERE
You'll need to generate an API Key to use here. We recommend generating a new key specifically for this integration point, especially if the key will be saved in an external, 3rd-party form-builder platform. Replace YOUR_API_KEY_HERE with your newly generated API Key.
Endpoint Response
By default, this endpoint returns a 200 status with an empty response body. When returnJSON=true is included as a query parameter, the endpoint returns a JSON object containing the following:
{
"formResponseId": "xxxxxxxxxxxxxxxxxxxxxxxx",
"enduserId": "xxxxxxxxxxxxxxxxxxxxxxxx",
"message": "Already Submitted"
}
-
formResponseId— the ID of the created or matched form response -
enduserId— the ID of the related enduser -
message— present only when the response was previously finalized
Posting Frequency
We recommend posting when the form flow is finalized or abandoned, though you can update a form response as needed.
Incomplete Form (Unfinalized Webhook)
When posting an incomplete form response in the event the form flow is abandoned, pass the finalized attribute as false.
- We must have at least one of
emailorphonein the payload, or we will ignore the webhook - We will attempt to match an existing enduser by email or phone; if no match is found, a new patient will be created
- We will store the form response in an unsubmitted state (
submittedAtis not defined) - The first
"finalized": falsewebhook will update any patient fields being mapped to; subsequent unfinalized webhooks will not update patient fields, only the form response- Note: email/phone excluded when matched to a pre-existing patient
- Each unfinalized webhook for the same
responder_uuidwill update the incomplete form with the new responses - We will not post webhooks or trigger a Form Submitted automation
- Forms that remain in an unsubmitted state are candidates for the Form Unsubmitted automation trigger
Submitted Form (Finalized Webhook)
When posting a completed form response, pass the finalized attribute as true.
- We will attempt to match an existing patient by
emailorphone; if no match is found, a new patient will be created - If neither
emailnorphoneis provided, a new enduser record will always be created - We will store the form response in a submitted state (
submittedAtis set) - When we receive the
"finalized": truewebhook, we will update any patient fields being mapped to- Note: email/phone excluded when matched to a pre-existing patient
- Future webhooks for the same
responder_uuidwill be ignored - Tellescope will emit a webhook for
"create" "form_responses" - Form Submitted automation triggers will be handled
Patient Matching / Insert
Form submissions will create a new patient or match an existing patient in Tellescope. Matching is done by email or phone number, so the form response payload must include questions with email and phone keys. Keys first_name and last_name will also be recognized when inserting a new patient.
This endpoint accepts an optional query parameter matchByName. When true, a submission will only match an existing enduser if (first name AND last name AND email) are the same, or (first name AND last name AND phone) are the same.
Note: to protect against a form submission overwriting an existing patient's contact information, email and phone are not updated when a submission is matched to a pre-existing patient by email, phone, or name. See the following section (Explicitly Targeting a Patient) to update these fields on an existing patient.
Explicitly Targeting a Patient
Instead of relying on email/phone matching, you can pass a known Tellescope enduserId as a query parameter to bind a submission directly to a specific patient record:https://api.tellescope.com/v1/webhooks/formsort/submit?formId=FORM_ID_HERE&enduserId=EXISTING_ENDUSER_ID
When enduserId is provided and resolves to a real patient, that patient is used directly; no email/phone/name matching is attempted. This is useful when the form is launched from a context where you already know the patient's Tellescope ID and you want to guarantee the response attaches to that exact record.
Note: if the
enduserIdprovided doesn't match a real patient, the parameter is simply ignored and normal email/phone matching (or new-patient creation) applies instead.
Variable Mapping to Tellescope Fields
Properly naming the variables in the payload allows Tellescope to sync responses as built-in and custom fields. The following table outlines the naming structure to follow in order to map form responses to Tellescope fields. For secondary insurance, you can use secondaryInsurance instead of insurance.
Variables are automatically saved as externalId in Tellescope responses (which can be passed through to OpenLoop integration). To prevent syncing a variable as an externalId on a Tellescope question, prefix the variable with ts_ignore.
| Variable (case sensitive) | Tellescope Field / Details | Formatting |
email |
{
"key": "email",
"value": "johndoe@email.com"
} |
|
phone |
Phone Number | {
"key": "phone",
"value": "8008881818"
} |
first_name (or fname) |
First Name | {
"key": "first_name",
"value": "John"
} |
last_name (or lname) |
Last Name | {
"key": "last_name",
"value": "Doe"
} |
|
Date of Birth | {
"key": "dateOfBirth",
"value": "1970-03-01"
} |
|
Gender | {
"key": "gender",
"value": "Male"
} |
healthieIntegrationId |
Only needed if your Tellescope organization has more than one Healthie connection. Set this to route the patient to a specific additional Healthie account instead of your primary one. The value should match the identifier (tenantId) you assigned to that connection on the Healthie Integration (Settings > Integrations). Leave unset to use your primary Healthie connection. Once a patient has been synced to Healthie, this value is locked and cannot be changed. | {
"key": "healthieIntegrationId",
"value": "your-tenant-id"
} |
healthie_dietitian_id |
The provider ID that should be used if syncing the patient (creating) in Healthie NOTE: If the Default Dietician ID is already set on the Healthie Integration (Settings > Integrations), providing a value in the form response would be duplicative and could impact the Healthie sync. |
{
"key": "healthie_dietitian_id",
"value": 1234567
} |
height |
The patient's full height in inches as a number (e.g. a 6'2'' patient would be 74) | {
"key": "height",
"value": 64
} |
weight |
The patient's weight in pounds as a number | {
"key": "weight",
"value": 200
} |
timezone |
Must be a valid timezone like "US/Central" or it will not sync | {
"key": "timezone",
"value": "US/Central"
} |
address |
Syncs to addressLineOne, zipCode, state, etc. | {
"key": "address",
"value": {
"address_1": "123 Main St",
"city": "Princeton",
"state": "NJ",
"postal_code": "08540"
}
} |
defaultFromPhone |
A phone number (if your account has more than 1) to use as the default | {
"key": "defaultFromPhone",
"value": "8003338888"
} |
useDefaultFromPhoneInAutomations |
boolean, use the above phone number for all automated messages | {
"key": "useDefaultFromPhoneInAutomations",
"value": false
} |
defaultFromEmail |
An email address (if your account has multiple senders) to use as the default | {
"key": "defaultFromEmail",
"value": "name@yourcompany.com"
} |
useDefaultFromEmailInAutomations |
boolean, use the above email for all automated messages | {
"key": "useDefaultFromEmailInAutomations",
"value": false
} |
language |
To sync with Healthie, currently only "Spanish" is supported | {
"key": "language",
"value": "Spanish"
} |
termsVersion |
Version of terms a patient has consented to. A string value "1.0" is the default version for our portal. If the value is "1.0", our portal will not prompt patients to re-consent when they first open it. If you set a different version value in the portal settings, you will want to match the current version value. | {
"key": "termsVersion",
"value": "1.0"
} |
ts_enduser_customField |
Any custom field. For example, a custom field called "customField". | {
"key": "ts_enduser_customField",
"value": "custom field text"
} |
insurance.memberId |
Primary insurance member ID | |
insurance.payerId |
Payer ID | |
insurance.payerName |
Payer (Name) | |
insurance.groupNumber |
Group Number | |
insurance.relationship |
Relationship to Subscriber | |
insurance.relationshipDetails.fname |
Subscriber first name | |
insurance.relationshipDetails.lname |
Subscriber last name | |
insurance.relationshipDetails.dateOfBirth |
Subscriber date of birth | |
insurance.relationshipDetails.gender |
Subscriber gender |
If an existing enduser is matched, these fields will be updated upon form submission.
Responder UUID
Every form response should include a responder_uuid — a unique string identifier used to tie responses to a patient and deduplicate submissions. The absence of a responder_uuid can have unintended consequences for patient creation, variable mapping, and downstream data sync.
Note: The
responder_uuidmust be provided at the root level of the payload.
Healthie Integration Compatibility
Syncing to Healthie (for OpenLoop Customers)
In the event you need form responses to sync to Healthie as charting notes, ensure that you have the ID of the Heathie charting note listed as the External ID on the Tellescope form as well as the "Sync via OpenLoop" setting enabled.
Routing to an additional Healthie account (multiple Healthie connections)
If your organization has connected more than one Healthie account (Settings > Integrations), patients sync to your primary Healthie connection by default. To route a specific patient to one of your additional Healthie connections instead, include the healthieIntegrationId variable in your form response payload, set to the identifier you chose for that connection on the Integrations page:
{ "key": "healthieIntegrationId", "value": "your-integration-id" }A few important things to note:
-
Leave it out to use your primary connection. If you don't include
healthieIntegrationId, or send it as an empty value, the patient will sync to your primary Healthie account as usual. -
This is a one-time setting per patient. Once a patient has been synced to Healthie for the first time, their Healthie account assignment is locked in and can't be changed. If a later form submission tries to send a different
healthieIntegrationIdfor that patient, that value will simply be ignored while the rest of the submission (all other fields and answers) will still go through normally. Because of this, make surehealthieIntegrationIdis set correctly the first time a patient submits a form, before they've been synced to Healthie. -
The Healthie sync only happens on a finalized submission. Sync to Healthie (specifically via the "Sync via OpenLoop" setting) only occurs when a form response is submitted with
"finalized": "true". SendinghealthieIntegrationIdon an unfinalized (draft) submission won't trigger a sync on its own, but it's still useful to include as it will be saved to the patient's record, so that when the finalized submission comes in later, the patient is routed correctly even if that final submission doesn't repeat the value. IfhealthieIntegrationIdis included on both an earlier draft and the final submission, the value from the final submission is what's used. - If the value you send doesn't match any of your connected Healthie accounts, the sync will be skipped for that patient rather than defaulting to your primary account, and our team will be notified so we can help you correct it.
- There will be an editable "Healthie Integration Id" field displayed on the patient profile. This field will only be displayed specifically when additional Healthie accounts are integrated outside of the primary connection.
Automation
Both finalized and unfinalized form responses can be leveraged within Tellescope to trigger automations. Common use cases include:
- Finalized form responses can activate Form Submitted triggers in Tellescope, when the
formIdfrom the webhook URL matches the corresponding form in Tellescope - Unfinalized form responses with at least one email or phone number can activate the Form Unsubmitted trigger for reengagement and re-marketing purposes
- The form in Tellescope must have at least one question field in order to be available for a trigger
- Conditional logic on form responses is not supported, but conditional logic on patient/contact fields is supported
Stripe Integration Compatibility
Stripe <> Tellescope Patient Matching
It is common to use Stripe to collect a payment during forms. The stripeCustomerId field on Tellescope's Enduser model should be set to ensure that Stripe Webhooks match the correct Enduser in Tellescope. If no Enduser matches to the Stripe Customer ID, customer email will be used for matching instead. This field should be set in Tellescope before any Stripe payments (or other webhook events) have processed.
Additionally, when possible (if using Stripe Elements or Stripe Checkout, for example) you can pre-fill some of the Stripe fields with the information provided previously by the patient (primarily name, phone, email). This ensures contact information is not entered into Stripe improperly and saves the patient the extra step of typing in information they've previously provided
Other Best Practices for Custom Intake Forms
- When testing, always use a unique first name, last name, phone number, and email address for each patient and form response to ensure proper creation and mapping in Tellescope
- Capture the patient's first name, last name, phone, and email as early as possible in your form flow — this ensures Tellescope has the information needed to match or create a patient and supports re-marketing via the Form Unsubmitted trigger
- When possible, avoid split intakes where a payment is processed mid-flow. Processing payment at the end of the intake and having it coincide with form completion reduces the need for outreach and refunds due to incomplete intake data
- Qualifying or disqualifying patients, collecting SMS consent, and handling file uploads are commonly handled within the intake form flow
Comments
0 comments
Article is closed for comments.