Is Text Messaging HIPAA Compliant? Only With a Gate Before send()

Is texting patients HIPAA compliant? Only with no PHI or a warned patient who asks. Who needs a BAA, why carriers usually don't, and the gate before send().

Clint JohnsonPublished 10 min read

Key takeaways

  • A BAA with your SMS vendor is required when it stores message bodies, but it doesn't make sending PHI by text safe.
  • Classify every outbound template as no PHI, minimum-necessary PHI with a stored Consent, or never by text, and fail closed to a portal notice.
  • Patient replies, webhook payloads, logs and retry queues hold PHI too, so strip bodies and keep STOP opt-outs separate from HIPAA preferences.

My rule for any patient-facing product: texts default to zero PHI. A link to the portal, nothing else.

I build patient-facing healthcare software (MedScrub, MedHook, eSpiral). If you build in this space, someone will eventually ask you to "just text them." My position is that PHI in a text body is an exception. It has to clear a gate. It needs a stored consent record. It gets an audit row. Some content never goes by text, whatever the patient says.

That's stricter than the letter of today's rules, and I'm fine with that. Under the current Security Rule, encryption is addressable, not required. HHS's FAQ on unencrypted email says the Privacy Rule doesn't prohibit it for treatment communications when reasonable safeguards are in place. Still, only two paths are clearly defensible. Either the message has no PHI, or the patient was warned that texts aren't secure and still asked for them.

Vendor checklists stop at "sign a BAA." You need the BAA with your SMS vendor. It assigns liability for what the vendor stores. It says nothing about whether you should have sent that content in the first place. That control is code that runs before send(), and no BAA writes it for you.

Who needs a BAA for SMS? Follow one message

A BAA covers one hop. To see the rest, follow one message from your app to the patient's phone.

Your app and database. You're the covered entity or the business associate. You hold the template, the rendered body, the phone number and the delivery status. That's PHI at rest, and it's yours.

The SMS API vendor. BAA: yes. Twilio, Sinch, Bandwidth or whoever you use receives the body in order to send it. Inbound webhooks carry the patient's reply back to you. Whether the vendor keeps bodies in its logs, for how long, and what lands in each webhook payload is in its docs and your contract. Read both, and check which of its products the BAA actually covers. HHS's cloud computing guidance says a provider that creates, receives or maintains ePHI is a business associate, even if it can't read the data because it's encrypted and it doesn't hold the key. Encryption at rest doesn't get a vendor out of a BAA. Storing bodies is what puts it in.

Aggregators and downstream routes. Ask. Your vendor may route through aggregators before the message reaches a carrier. Ask how its BAA covers them and whether its retention settings apply all the way down the chain.

The carrier. BAA: generally no. HHS limits the conduit exception to transmission-only services, "including any temporary storage of PHI incident to such transmission," where any access is "only transient in nature." OCR's examples are the Postal Service and UPS, as Holland & Hart summarizes, and the firm warns the exception is "often misunderstood or misapplied." HHS hasn't written SMS-specific guidance. But a carrier that only moves the message and holds it briefly to deliver it is the textbook conduit case. Your SMS vendor stores, so it isn't one.

The handset. BAA: no. The phone belongs to the patient, and the Security Rule doesn't apply to them. The message shows up on a lock screen, gets read by whoever picks up the phone, and sits in a thread forever.

You control your own storage, what goes into the body, and the vendor's settings. Nothing past that.

Does RCS encryption make texting patients HIPAA compliant?

Not on its own. People see the iPhone–Android RCS encryption news and ask whether texting is secure now. Your message doesn't come from a person's phone. It comes from your server through a business messaging API. Unless your vendor puts end-to-end encryption for your traffic in writing, treat it as plaintext.

Design every outbound message as if it's a plaintext SMS on a lock screen.

Can you text PHI if the patient asks?

Yes, but asking isn't the whole requirement. Per OCR's position as Holland & Hart summarizes it, the patient has to be told the risks and still prefer the unencrypted channel. Then you aren't responsible for interception in transit at their request.

Three mistakes to avoid:

  1. Treating "the patient texted us first" as consent. It isn't. The warning still has to happen, and an offhand "texting is fine" doesn't count as an informed choice.
  2. Turning one patient's preference into the default. It covers that patient, that number, and the content they agreed to. ChartRequest's guidance on emailing records lists what to record, and it maps cleanly to SMS: the request, the risk warning, the patient's confirmation, the phone number used, and what was sent.
  3. Thinking you have to comply. You can decline. If your risk assessment says some content shouldn't go by text, that rule beats the request.

The warning only works for patients. For texts to other providers, staff or third parties, saying the channel may be insecure isn't enough.

For the policy side, see HIPAA Consent: What Engineers Actually Need to Know.

What can you text a patient under HIPAA? Three tiers

Every template gets exactly one tier.

Tier 1: no PHI. "You have a new message in your portal" plus a link. Anyone can read it on a lock screen. Watch the sender name, though. "Your appointment at Riverside Behavioral Health is tomorrow" leaks a diagnosis category through the clinic name alone. For sensitive specialties, the practice name moves the message to tier 2.

Tier 2: minimum-necessary PHI. Appointment time and location, or a refill-ready notice. These go out only when an active preference is on file showing the patient was warned and opted in. That preference belongs with the patient record, not in a config table. The body carries the minimum and nothing else. Same principle as the FHIR MCP server post: give each consumer the smallest slice of PHI the task needs.

A FHIR Consent resource is a good home for it. These are the fields I'd actually set (R4 shape; R5 moved some fields, so match your server):

{
  "resourceType": "Consent",
  "status": "active",
  "scope": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/consentscope", "code": "patient-privacy" }] },
  "category": [{ "coding": [{ "system": "https://yourorg.example/consent-category", "code": "sms-unencrypted-phi" }] }],
  "patient": { "reference": "Patient/123" },
  "dateTime": "2026-03-02T15:04:00Z",
  "sourceReference": { "reference": "QuestionnaireResponse/sms-risk-warning-456" },
  "provision": {
    "type": "permit",
    "period": { "start": "2026-03-02T15:04:00Z" },
    "action": [{ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/consentaction", "code": "disclose" }] }]
  }
}

The QuestionnaireResponse holds the version of the warning the patient saw, their yes, and the phone number. Revoking sets status to inactive or closes the period. Never delete it. That record is your proof.

Tier 3: never by text. Results, diagnoses, behavioral health, and substance-use treatment covered by 42 CFR Part 2. A patient preference doesn't unlock these. They become a tier-1 "new message in your portal" notice instead.

How to enforce HIPAA texting rules in code

Classify the template, not the string. Scanning rendered text for PHI is a backstop, not the control. Each template declares its tier when it's written, and code review checks it. Free-text sends from staff are tier 3 unless someone picks a lower tier on purpose.

async function sendPatientText(msg: OutboundText) {
  const tier = TEMPLATE_TIERS[msg.templateId] ?? "never_sms"; // unknown fails closed

  // STOP blocks everything, including portal notices
  if (await isOptedOut(msg.toPhone)) return writeAudit(msg, tier, "opted_out");

  const consentRef =
    tier === "minimum_phi" ? await activeTextConsentId(msg.patientId, msg.toPhone) : null;

  if (tier === "never_sms" || (tier === "minimum_phi" && !consentRef)) {
    const vendorId = await sendPortalNotice(msg.patientId, msg.toPhone);
    return writeAudit(msg, tier, "portal_fallback", { vendorId });
  }

  const vendorId = await sms.send(msg.toPhone, render(msg));
  return writeAudit(msg, tier, "sent", { vendorId, consentRef });
}

activeTextConsentId() returns the ID of an active Consent in the sms-unencrypted-phi category whose period covers now and whose phone number matches toPhone. A different number means no consent. render() fills the template from the one appointment or order it references and pulls in nothing else.

These are deterministic rules, not a model. No LLM decides whether a lab result goes out over SMS. I've written about how GenAI projects in healthcare go sideways, and letting a model make a disclosure call is one of the fastest routes there. A missing template mapping falls back to the portal notice. So does a missing consent. The opt-out check runs first, because the portal notice is itself a text. Every return path writes an audit row.

The failure mode is always "the patient logs in," never "PHI on a lock screen." That's the whole design.

If you build one control, build this one. The gate above is under twenty lines, and it turns "we have a BAA" into a policy you can enforce.

Patient replies and vendor logs are PHI too

Outbound is the easy part. Patients reply "is this about my biopsy?" Holland & Hart, citing OCR guidance, notes that a patient's text becomes protected by HIPAA once the provider receives it. That inbound PHI now sits wherever your vendor keeps messages, in the webhook payload sent to your server, in your request logs, and in any retry queue you run. If you queue sends on a durable broker like RabbitMQ, the bodies live there too.

What to do:

  • Ask your vendor whether it can redact bodies or shorten retention. If it can, turn it on. If it can't, count that against the vendor.
  • Strip bodies from webhook logging at the edge. Log the vendor message ID and status, not the text.
  • Queue a reference to the message, not the rendered body. Render at send time.
  • Route inbound replies into the clinical inbox and stop there. Not analytics. Not your error tracker.

STOP is a messaging opt-out, typically handled by your SMS vendor. It isn't a HIPAA communication preference, and it shouldn't live in the same field. Keep two records:

  • Opt-out: keyed by phone number. It blocks every send, all tiers, until the number opts back in.
  • Unencrypted-text preference: keyed by patient and phone. It only controls whether tier 2 is allowed.

Put these in one boolean and you will get burned. Someone flips "texts OK" back on for a patient who said STOP. Or a patient revokes HIPAA consent and loses appointment reminders they never meant to give up.

HIPAA audit logging for patient text messages

Every decision gets written down, including the ones where nothing was sent.

create table sms_audit (
  id uuid primary key,
  patient_id text not null,
  template_id text not null,
  template_version text not null,
  render_ref text,               -- appointment/order id the body was rendered from
  tier text not null,            -- no_phi | minimum_phi | never_sms
  outcome text not null,         -- sent | portal_fallback | opted_out
  consent_ref text,              -- Consent id when tier = minimum_phi
  vendor_message_id text,
  body_sha256 text,              -- verify a re-rendered body without storing it twice
  decided_at timestamptz not null default now()
);

Template ID, version and render reference let you re-render the body. The hash proves the re-rendered body matches what went out. You don't need a second copy of PHI in your audit store. The consent_ref column ties each tier-2 send to the Consent and the warning behind it.

Will the proposed HIPAA Security Rule ban unencrypted texts?

It could come close. OCR issued a Security Rule NPRM on December 27, 2024, published in the Federal Register on January 6, 2025. It would make encryption of ePHI at rest and in transit required instead of addressable. The proposed exception covers a patient who requests unencrypted ePHI under §164.524 (the right of access) after being told the risks. It doesn't apply when the technology is "controlled by the covered entity or its business associate." The same proposal would require written verification from each business associate that its safeguards are in place. A signed BAA alone would no longer be enough.

Here's the problem. A provider-initiated reminder sent through your own BAA'd SMS API isn't obviously a §164.524 request, and it runs on technology you arguably control. If the rule is finalized as written, tier 2 could shrink to almost nothing. It isn't final, and current rules stay in effect. Medcurity reports that OMB's agenda now lists July 2027, a date that isn't binding.

That's one more reason to build the tiers now. If tier 2 goes away, you change one consent check and those templates fall back to portal notices. Teams that put PHI in every reminder will be rewriting templates against a deadline.

Questions people ask

Is text messaging HIPAA compliant?

The clearly defensible cases are a message with no PHI, or one sent after the patient was warned that texts aren't secure and still asked for them. A BAA with your SMS vendor is required but doesn't make an unsafe message safe.

Do cell phone carriers need to sign a BAA for SMS?

Generally no, if the carrier only transmits the message and holds it briefly to deliver it. HHS limits the conduit exception to transmission-only services with temporary storage incident to transmission and hasn't written SMS-specific guidance. Your SMS API vendor stores message bodies, so it does need a BAA.

Does a patient texting first count as consent to receive PHI by text?

No. The patient has to be told the risks of unencrypted texting and still prefer it. Record the request, the warning, the confirmation, the phone number used and what was sent.

Does iPhone-Android RCS encryption make texting patients HIPAA compliant?

Not on its own. Messages your server sends through a business messaging API should be treated as plaintext unless your vendor puts end-to-end encryption for your traffic in writing.