Skip to content
Dashboard

Tellescope

Use the Tellescope connector to sync up to 91 clinical and operational data streams — patients, appointments, form responses, messages, tickets, and more — into your Athena lakehouse. This is a Blotout custom connector built on the Airbyte Connector Builder (declarative manifest), auto-generated from Tellescope’s @tellescope/schema npm package.

  • A tag with Blotout Cloud set up (green checkmark in the Tags table)
  • A Tellescope API key — generated in Tellescope under Settings → API Keys (POST /v1/api-key). The value is shown once and cannot be retrieved later — only replaced. Ask the client to generate it under a dedicated service user, not a clinician’s account.
  • Agreed stream list — which of the 91 models are actually allowed to copy, confirmed in writing before any key is issued
  • BAA / destination confirmation — confirmation that the destination bucket and warehouse are in PHI scope before the first sync runs
  • Know the environment — production (https://api.tellescope.com/v1) or staging (https://staging-api.tellescope.com/v1). Keys are not shared between them.

Follow the shared Create a pipeline steps until the source catalogue appears, then select Tellescope.

On the Source step, configure the connector:

FieldPurpose
Schedule TypeHow the pipeline runs — typically Scheduled
Sync FrequencyHow often Airbyte syncs (for example, Every 24 hours)
Source NameName for this pipeline — used in the Athena schema <SOURCE_NAME>_<ENV>

Every request carries a single header: Authorization: API_KEY <api key>. Note the format is literally the word API_KEY, a space, then the key — not Bearer.

MethodSupportedDetail
API keyIn useLong-lived, no refresh step.
Session tokenNot usableExpires (expirationInSeconds), needs interactive credential — unusable for scheduled sync.
OAuth / OAuth2Not availableTellescope’s OAuth2 runs the other direction (connecting Tellescope to third parties like Zoom, Google, Healthie). Tellescope is not an OAuth provider for its own API.
FieldTypeRequiredDefaultDescription
api_keysecret stringYesTellescope API key, sent as Authorization: API_KEY <key>. Generated via POST /v1/api-key (Settings → API Keys); shown once and cannot be retrieved later.
start_datestringYesEarliest record modification date to pull (YYYY-MM-DD), sent as the from query param with fromToField=updatedAt. Records edited before this date are skipped even if they were created long ago.
limitintegerNo1000Page size (limit query param). The API caps at 1000; the connector pages with lastId until a short page arrives.
lookback_hoursintegerNo1On each incremental sync, rewind this many hours before the stored cursor. Records are appended — deduplicate latest-per-id downstream.
base_urlstringNo"https://api.tellescope.com/v1"Override for the staging environment (https://staging-api.tellescope.com/v1). Default is production.

The Tellescope source connector supports the following sync modes:

  • Incremental Sync — Append

Tellescope’s API is uniform: every model is a CRUD resource with the same list contract. All 91 streams share these properties:

PropertyValue
Primary keyid — a 24-character Mongo ObjectId
Cursor fieldupdatedAt — ISO-8601 with milliseconds, e.g. 2026-08-24T14:38:51.911Z
Sync modeIncremental | Append
PaginationlastId cursor on the previous page’s final record; a short page ends the stream
Page sizelimit, default and maximum 1000
API patternGET /v1/<plural>?limit=1000&lastId=<id>&sort=oldFirst&from=<ISO timestamp>&fromToField=updatedAt
Response formatBare JSON array (no envelope, no page number, no total count)

Every model extends Tellescope’s ClientRecord base, which guarantees id and updatedAt on all records.

The connector sends fromToField=updatedAt to repoint the filter at modification time (Tellescope defaults to createdAt), and sort=oldFirst so the lastId cursor walks forward through the filtered set.

FieldJSON TypeAthena TypeNotes
idstringvarchar24-char Mongo ObjectId — primary key
businessIdstringvarchar
organizationIdsarray<string>array
sharedWithOrganizationsarray<object>array
creatorstringvarchar
updatedAtstringvarcharISO-8601, ms precision — cursor field
originalIdstringvarchar

The table below lists every stream, its endpoint, field count, and PHI classification.

StreamEndpointFieldsPHI
endusersGET /endusers99Yes
calendar_eventsGET /calendar-events100Yes
care_plansGET /care-plans17Yes
chat_roomsGET /chat-rooms40Yes
chatsGET /chats32Yes
database_recordsGET /database-records9Yes
email_sync_denialsGET /email-sync-denials8Yes
emailsGET /emails55Yes
enduser_custom_typesGET /enduser-custom-types11Yes
enduser_eligibility_resultsGET /enduser-eligibility-results13Yes
enduser_encountersGET /enduser-encounters18Yes
enduser_medicationsGET /enduser-medications35Yes
enduser_observationsGET /enduser-observations32Yes
enduser_ordersGET /enduser-orders30Yes
enduser_problemsGET /enduser-problems14Yes
enduser_profile_viewsGET /enduser-profile-views13Yes
enduser_status_updatesGET /enduser-status-updates10Yes
enduser_tasksGET /enduser-tasks11Yes
enduser_viewsGET /enduser-views17Yes
fax_logsGET /fax-logs18Yes
filesGET /files22Yes
form_responsesGET /form-responses59Yes
forum_postsGET /forum-posts17Yes
group_mms_conversationsGET /group-mms-conversations25Yes
inbox_threadsGET /inbox-threads29Yes
meetingsGET /meetings12Yes
notesGET /notes21Yes
phone_callsGET /phone-calls42Yes
post_commentsGET /post-comments18Yes
purchasesGET /purchases22Yes
sms_messagesGET /sms-messages49Yes
suggested_contactsGET /suggested-contacts10Yes
superbillsGET /superbills12Yes
ticket_thread_commentsGET /ticket-thread-comments30Yes
ticket_threadsGET /ticket-threads16Yes
ticketsGET /tickets66Yes
user_notificationsGET /user-notifications12Yes
waitlistsGET /waitlists11Yes

Configuration and reference streams (non-PHI)

Section titled “Configuration and reference streams (non-PHI)”
StreamEndpointFields
agent_recordsGET /agent-records16
ai_conversationsGET /ai-conversations17
allergy_codesGET /allergy-codes10
analytics_framesGET /analytics-frames26
appointment_booking_pagesGET /appointment-booking-pages51
appointment_locationsGET /appointment-locations21
automated_actionsGET /automated-actions17
automation_stepsGET /automation-steps15
automation_triggersGET /automation-triggers20
availability_blocksGET /availability-blocks18
background_errorsGET /background-errors13
blocked_phonesGET /blocked-phones8
calendar_event_rsvpsGET /calendar-event-RSVPs12
calendar_event_templatesGET /calendar-event-templates62
call_hold_queuesGET /call-hold-queues9
comment_likesGET /comment-likes10
configurationsGET /configurations10
custom_dashboardsGET /custom-dashboards17
databasesGET /databases12
diagnosis_codesGET /diagnosis-codes10
engagement_eventsGET /engagement-events12
flowchart_notesGET /flowchart-notes10
form_fieldsGET /form-fields34
form_groupsGET /form-groups9
formsGET /forms81
forumsGET /forums11
integration_logsGET /integration-logs14
integrationsGET /integrations38
journeysGET /journeys15
managed_content_record_assignmentsGET /managed-content-record-assignments9
managed_content_recordsGET /managed-content-records30
message_template_snippetsGET /message-template-snippets9
organization_paymentsGET /organization-payments15
organizationsGET /organizations100
phone_treesGET /phone-trees17
portal_brandingsGET /portal-brandings17
portal_customizationsGET /portal-customizations22
post_likesGET /post-likes9
prescription_routesGET /prescription-routes24
productsGET /products22
purchase_creditsGET /purchase-credits12
role_based_access_permissionsGET /role-based-access-permissions14
superbill_providersGET /superbill-providers16
table_viewsGET /table-views14
templatesGET /templates24
ticket_queuesGET /ticket-queues14
ticket_templatesGET /ticket-templates18
time_tracksGET /time-tracks27
user_logsGET /user-logs12
usersGET /users71
vital_configurationsGET /vital-configurations13
webhook_logsGET /webhook-logs11
webhooksGET /webhooks11

api_keys is deliberately excluded — credential metadata with no analytical value. Airbyte’s connection check runs against users (staff, non-PHI).

The PHI flag is a heuristic: Tellescope does not label its models, and a free-text field on almost any stream (a note on a ticket, a database record, an uploaded file) can end up holding patient information. Treat it as a floor, not a guarantee.

Clearly patient data: endusers (name, email, phone, DOB, address, external ids), chats / chat_rooms / emails / sms_messages / phone_calls / fax_logs (message bodies), form_responses (answers), notes, enduser_medications, enduser_problems, enduser_observations, enduser_encounters, care_plans, superbills, tickets / ticket_threads

Not patient records: Reference tables (allergy_codes, diagnosis_codes), configuration (templates, journeys, automation_steps, forms, products) and staff data (users, user_logs)

Practical scoping: endusers alone is usually enough — every other model joins to it by enduserId, so analytics rarely needs the message-body streams. Start from the question being answered and add streams to the connection one at a time.

  • Schema: tellescope_<client>_prod.*, one table per enabled stream
  • updatedAt moves on every edit and the connector appends, so the same id lands repeatedly. Deduplicate latest-per-id downstream:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY id
ORDER BY _airbyte_extracted_at DESC
) AS rn
FROM tellescope_<client>_prod.endusers
) WHERE rn = 1
  • Every record carries businessId and organizationIds — filter on them if the key spans multiple organizations
  • Nested objects and arrays-of-objects land as JSON; flatten what you need in dbt

manifest.yaml is generated, not hand-written. Tellescope publishes the machine-readable definition of every model in the public @tellescope/schema npm package, which exposes generateOpenAPISpec(). The connector’s regenerate.sh installs that package into a temp directory, dumps the spec, and rebuilds all 91 streams and their schemas from it:

Terminal window
cd connectors/source-tellescope/v1/
./regenerate.sh # latest @tellescope/schema
./regenerate.sh 1.256.10 # pin a version

A Tellescope API change is a re-run and a diff review, not a hand edit.

  • Agree the stream list with the client in writing, before any key is issued
  • Confirm the destination bucket / warehouse is in PHI scope under the BAA
  • Client generates an API key under a dedicated service user and sends it securely (shown once)
  • Confirm environment — production or staging base_url
  • Local smoke test: cd connectors/source-tellescope/v1 && ./test_local.sh <key> (defaults to a small stream set; logs/read_raw.jsonl will contain PHI — delete it after)
  • Publish the image: ./build_and_deploy.sh (or merge to main — CI builds it)
  • Airbyte → Settings → Sources → New → Add Docker Connector → blotout/source-tellescope, tag 1.0.0
  • Create the source; run check and confirm discover returns 91 streams
  • Create the connection and select only the agreed streams, all Incremental | Append
  • Verify fromToField=updatedAt is honoured: pick a record edited (not created) after the start date and confirm it arrives
  • Verify lastId paging on a stream with more than limit rows — ./test_debug.sh <key> <stream> sets limit=2 to force it
  • Point dbt at tellescope_<client>_prod and build the dedupe views
VersionDateDescription
1.0.02026-08-26Initial release with 91 streams auto-generated from @tellescope/schema

Continue through the Schema and Summary steps to choose streams and confirm the connection. Save and run the first sync.

After a successful sync, Airflow creates an organization-scoped DAG for the pipeline, and dbt models feed downstream analytics.