Skip to main content

Build a Telehealth Site with Decoda

This guide shows how to use Decoda as the EMR and billing engine behind your own telehealth front end. Your site owns the patient experience — booking, video, branding — and Decoda holds the chart, the note, and the money. The end-to-end flow is:
1

Register the patient

Create the patient record from your sign-up form.
2

Collect the intake form

Submit the patient’s form answers. Mapped answers flow straight into the chart.
3

Draft the clinical note

Pre-fill a note from the intake answers and same-day measurements, then create it for the provider to finish.
4

Build an itemized charge

List your catalog items to get their IDs, then create a charge with line items and discounts.
5

Take payment

Collect payment through the embedded payment component — either charge now at checkout, or charge a card already on file.
6

(Optional) Enroll in a membership

Turn the visit into recurring revenue by enrolling the patient in a membership billed to their saved card.
Conventions used throughout this guide
  • All amounts are in cents (10000 = $100.00).
  • Request bodies are camelCase JSON (patientId, totalOutstanding).
  • Every request needs the TENANT and API-KEY headers. Keep your API key server-side — never ship it to the browser. See the Quick Start for credentials.

Prerequisites

Set these up once in the console before you write any integration code. They’re the templates and catalog your API calls reference by ID.
Generate a note template from a form so the note mirrors the intake you already built. Call Create Note Template From Form with the formId:
The conversion flattens the form’s blocks and questions into note fields. Signature, payment, disclaimer, statement, and document questions are skipped.
Every code sample below assumes this shared setup:

Step 1: Register the patient

When someone signs up on your site, create their Decoda patient record with Create Patient. Pass an externalId to link the record back to your own user table.
Response (abbreviated):
Save the returned id (pat_…) — every later step is keyed to it. Setting patientSource (e.g. WEB_FORM, SELF_SCHEDULING) tags how the patient reached you, which is useful for acquisition reporting.

Step 2: Collect the intake form

Your site renders the intake questions (or embeds the Decoda form), then submits the patient’s answers with Submit Form. Each entry in blocks carries a blockType (DEMOGRAPHICS, MEDICAL_HISTORY, PAYMENT_METHODS, INSURANCE, or DYNAMIC). Set isCompleteSubmission to true for a finished submission. Answers mapped to patient-record fields (demographics, medical history, measurements) save to the chart automatically — that’s what makes the note pre-fill work in Step 3.
The exact answers shape per block comes from your form’s structure — see the Form Structure Reference. You can also let Decoda send the form to the patient by email/SMS instead of rendering it yourself; see Sending Forms.
Want a card on file? Add a Payment Methods block to the form, or capture the card separately with the Store Details embed. Either way you get back a paymentMethodId (pm_…) — you’ll need it for the saved-card payment path (Step 5, Option B) and for memberships (Step 6).

Step 3: Draft the pre-filled clinical note

Fetch the patient’s pre-filled answers for the template with Get Prefilled Answers, then pass them straight into Create Note. The prefill response returns each answer keyed by questionId, in the exact shape answers expects — so the provider opens a note that’s already partly filled from the intake.
Prefill response:
Only questions mapped to the patient chart (demographics, medical history, and same-day measurements) come back pre-filled. Weight and height only pre-fill when a measurement was recorded the same day. Free-text questions come back empty — the provider fills those in the note, or you can auto-draft them with the AI Scribe. See Telehealth Visits for the provider-side experience.

Step 4: Build an itemized charge

A charge is what the patient owes for the visit. Line items reference your catalog items by itemId, so first list your items to grab their IDs, then create the charge.

List items to find their IDs

Use List Items (paginated) or Search Items to find the itemId and current price for what you’re billing.
Don’t have the item yet? Create one once with Create Item ({ "name": "Consultation", "price": 10000 }) and reuse its id on every future charge.

Create the charge

Create the charge with Create Charge. Each line item takes itemId, name, quantity, price (cents), and an optional discounts array. Set totalOutstanding to the sum of the line items minus any discounts.
Discounts go in the discounts array (amount in cents, order 0-based, quantity), not a flat discountAmount field. totalOutstanding must equal item totals minus those discounts — here 10000 − 1500 = 8500. Applying discounts requires the BILLING_DISCOUNTS_APPLY permission on your API key.
Already building a cart elsewhere? Convert Cart to Charge carries a cart’s items and discounts onto a charge instead. See Payment Embed: Itemized Charges.

Step 5: Take payment

Collect payment through the embedded payment component. There are two avenues — pick per visit, or support both.

Option A — Charge now

Patient enters a card at checkout and pays immediately. Best for one-off visits and first-time patients.

Option B — Charge a card on file

You already stored the patient’s card (via the embed). Charge it server-side with no patient interaction. Best for follow-ups, no-show fees, and memberships.

Option A: Charge now (embedded checkout)

Point the embedded payment component at the charge. The embed shows the full itemized breakdown and applies the payment to the existing charge — no duplicate charge is created.
Listen for the outcome via postMessage:
The embed URL accepts allowedMethods (CARD, ACH, APPLE_PAY), theme (light / dark), and showSummary. See Payment Embed: Itemized Charges for the full parameter and event reference.

Option B: Charge a card already on file

If you saved a card earlier (a paymentMethodId, pm_…, from the Store Details embed or a form’s Payment Methods block), you can charge it from your server without any patient interaction. It’s a two-call sequence:
1

Create a pay-in config for the charge

Call Setup Payin Component with paymentMedium: "SAVED_PAYMENT_METHOD", the paymentMethodId, and the charge. It returns a payinConfigId.
2

Charge the saved card

Call Charge Payment Method with just the payinConfigId.
The charge-card response confirms the outcome:
The charge-card body is only { "payinConfigId": "…" }. Don’t send chargeId or amount there — those belong on the pay-in config. A missing payinConfigId usually surfaces from the processor as “Field is required.”
How do you get a paymentMethodId in the first place? The Store Details embed collects and saves a card without charging it, then hands you the pm_… id via postMessage or a redirect query param. That’s the “stored using the embedded payment component” step this whole option depends on.

Step 6: Enroll in a membership (recurring revenue)

Memberships turn a one-time patient into recurring revenue — a monthly or annual plan billed automatically to a card on file. This is where a telehealth business compounds: capture the card once, enroll, and Decoda bills every cycle.

Create the membership (once)

Define the plan with Create Membership, or build it in the console and reference its id. Key fields:
List existing plans anytime with List Memberships.

Enroll the patient

Enroll with Enroll Member (Deferred Billing), passing the saved paymentMethodId (from the Store Details embed in Step 5) and the firstBillingDate. Decoda bills that card on the first billing date and then every billingFrequency cycle.
Need the patient to sign a membership agreement first? Use Enroll Member (Awaiting Form) instead — same body, but billing waits until the linked form is completed. To bill an existing member outside their regular cycle, use Manual Payment; to swap the card a member is billed on, use Update Payment Method.

End-to-end example

Here’s the one-time-visit path (Steps 1–5, Option A) tied together in Python. It assumes your form template, note template, and catalog item already exist.

Next steps

Webhook Events

Get notified when forms are submitted and payments succeed — instead of polling.

Store Details Embed

Save a card on file for the saved-card and membership flows.

Payment Embed: Itemized Charges

The embedded payment component and its parameters in depth.

Patient Onboarding

Add scheduling and appointment confirmations around this flow.