By Michael Chen · Published May 21, 2026 · Updated June 8, 2026 · 11 min read
Quick Answer: A HIPAA-compliant fax API lets your application send and receive protected health information (PHI) by fax through code — but only when the provider signs a Business Associate Agreement (BAA) and the service enforces TLS 1.2+ encryption in transit, AES-256 at rest, audit logging, access controls, and signed webhooks. The technology alone is never enough: without a signed BAA, transmitting PHI through any fax API is itself a HIPAA violation. The first-party mFax API ships with a signed BAA on every plan.
If your health app sends prescriptions, lab results, referrals, or patient records by fax, you can't just reach for any HIPAA fax API. The Health Insurance Portability and Accountability Act (HIPAA) holds you responsible for every byte of PHI your code transmits — and that responsibility extends to the fax provider behind your API calls.
This guide is the compliance-focused companion to our how to send a fax via API tutorial. It covers exactly what makes a fax API HIPAA compliant, the marketing language that trips developers up, what a violation actually costs, and how to build an integration that keeps PHI safe in transit, at rest, and in your own logs — with working code against the mFax API.
BAA First, Code Second
Before you write a single line that touches PHI, you need a signed Business Associate Agreement with your provider. No BAA means no compliant faxing — full stop. Everything else in this guide assumes that contract is in place. With mFax, the BAA is included on every plan.
What Makes a Fax API HIPAA Compliant?
A fax API is HIPAA compliant when it satisfies both a contractual requirement (the BAA) and a set of technical safeguards defined by the HIPAA Security Rule. Use this as your evaluation checklist:
- ✓Signed BAA: The provider executes a Business Associate Agreement before you transmit any PHI. This is the legal foundation — "HIPAA-capable" marketing is not a substitute for a signed contract. mFax Business includes the BAA on every plan.
- ✓TLS 1.2+ in transit: Every API call and webhook callback travels over HTTPS with TLS 1.2 or higher. Reject any provider that permits unencrypted connections.
- ✓AES-256 at rest: Documents stored on the provider's servers are encrypted with AES-256. Confirm the retention window and whether you can configure auto-deletion. See our fax encryption guide for what to verify.
- ✓Audit logging: Every send, receive, view, and download is logged with timestamps and user identity, and those logs are exportable for an audit.
- ✓Access controls & MFA: Role-based access limits who can view faxes, and multi-factor authentication protects the dashboard and API key management.
- ✓Signed webhooks: Delivery and inbound callbacks are signed (HMAC or Ed25519) so your app can verify a payload genuinely came from the provider, not an attacker. mFax signs each event with HMAC-SHA256.
- ✓Retention controls: You can minimize how long PHI lives on the provider's infrastructure — ideally configuring documents to not be retained at all after delivery.
For the complete regulatory framework, see our HIPAA fax requirements guide and the broader HIPAA-compliant fax overview.
"HIPAA-Ready" vs. a Signed BAA: The Marketing Trap
The single most common compliance mistake is treating a marketing badge as legal coverage. A vendor can be technically "HIPAA-ready" — strong encryption, access controls, the works — and still leave you exposed, because compliance is a relationship, not a feature.
Under HIPAA, your fax provider becomes a business associate the moment it handles PHI on your behalf, and that relationship must be formalized in a BAA. The contract is what legally binds the provider to safeguard the data and report breaches. Without it:
- The provider has no legal obligation to protect your PHI.
- You remain fully liable for any disclosure.
- The transmission is a violation even if nothing ever leaks.
Watch the Fine Print
Some consumer fax services explicitly offer no BAA and are unsuitable for PHI. Others are HIPAA-compliant only in a specific configuration — for example, via a desktop app with email delivery disabled, where faxing over email is not covered. Always confirm the BAA covers the exact API workflow you're building.
What Happens If You Get It Wrong
Misdirected and mishandled faxes are a recurring source of HIPAA enforcement, and the penalties are tied to culpability, not intent.
In 2017, St. Luke's-Roosevelt Hospital Center settled with the HHS Office for Civil Rights for $387,200 after staff faxed a patient's highly sensitive records — including HIV status — to the patient's employer, and OCR found a similar errant fax months earlier (HHS enforcement records). One wrong number, two settlements, and a multi-year corrective action plan.
Civil penalties scale by tier. For willful neglect that goes uncorrected, fines reach up to $2,190,294 per violation category per year under the current inflation-adjusted schedule (HHS HIPAA enforcement). Even the lowest tier — a violation you had no reasonable way to know about — starts in the hundreds of dollars per record.
The Lesson for Developers
Most fax-related violations aren't exotic breaches — they're a document sent to the wrong number, PHI written to an application log, or a provider relationship without a BAA. Each of those is preventable in code and configuration.
How to Build a HIPAA-Compliant Fax Integration
Compliance is a sequence, not a single switch. Here's the order that keeps PHI protected end to end, using the mFax API as the reference implementation:
Sign the BAA
Execute the Business Associate Agreement with your provider before any PHI flows. With mFax, the BAA is included on every Business plan at no extra cost; with some providers it may be gated behind an enterprise tier.
Lock down credentials
Create a business API key in the mFax dashboard. mFax authenticates with an HTTP header — Authorization: Bearer zk_live_xxxxxxxx — and the zk_live_ key is server-side only: never ship it in a browser or mobile app. Store it in a secrets manager, scope keys narrowly, enable MFA on the dashboard, and rotate on a schedule. Treat the key like a key to a filing cabinet full of patient charts.
Enforce TLS everywhere
Every mFax endpoint lives under https://developers.mfax.to/v1 and is HTTPS-only. Make every send and every webhook callback HTTPS, pin TLS 1.2 or higher, and disable any fallback to plaintext.
Verify and secure webhooks
Configure your webhook URL and signing secret in the mFax dashboard (not per request). Expose your status endpoint over HTTPS only, and verify the signature on every payload before trusting it. Reject anything that fails verification.
Keep PHI out of your logs
Redact recipient numbers, document contents, and patient identifiers from application logs, error trackers, and analytics. A stack trace with a patient name is a breach.
Minimize retention and audit everything
Configure the shortest practical retention (ideally auto-delete after delivery), and record every send/receive/view event so you can produce an audit trail on demand.
Sending a Fax With the mFax API
The send request is deliberately small. POST /v1/faxes takes multipart/form-data with two fields — to (the recipient number in E.164) and file (the PDF). The sender number is tied to your organization's subscription, so there's no from field to leak or get wrong:
curl -X POST https://developers.mfax.to/v1/faxes \
-H "Authorization: Bearer zk_live_your_key" \
-F "to=+15417543010" \
-F "file=@patient-referral.pdf"
mFax responds with 202 Accepted and a Fax object whose status walks the lifecycle queued -> sending -> delivered | failed. Poll a single fax with GET /v1/faxes/{uuid} to read its status, page_count, and a presigned, time-limited media_url for the PDF — or, better, let a webhook tell you when it lands (next section):
curl https://developers.mfax.to/v1/faxes/<uuid> \
-H "Authorization: Bearer zk_live_your_key"
Errors and Rate Limits
mFax returns a JSON error object — { "code": "...", "message": "..." } — with codes like invalid_number (400), quota_exceeded (402), subscription_inactive (403), and rate_limited (429). On a 429, read the Retry-After header (seconds) along with RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset, and back off with jitter before retrying. The full schema lives in the mFax developer docs.
Verifying a Signed Webhook (Node.js)
Trusting an unverified callback is how a forged fax.delivered event — or worse, a malicious fax.received payload — gets into your system. mFax POSTs a WebhookEvent envelope ({ id, type, created, data }) to the URL you configure in the dashboard, and when a signing secret is set, it signs the request with two headers: X-Zelda-Timestamp (unix seconds) and X-Zelda-Signature in the format t=<timestamp>,v1=<hex>, where the hex is HMAC-SHA256(secret, "<timestamp>.<raw_body>"). Verify against the raw request body, compare in constant time, reject stale timestamps, and dedupe on the event id (delivery is at-least-once):
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const TOLERANCE_SECONDS = 5 * 60; // reject anything older than 5 minutes
const seen = new Set(); // swap for a durable store in production
// Capture the raw body so the signature matches byte-for-byte
app.post(
'/webhooks/fax',
express.raw({ type: 'application/json' }),
(req, res) => {
const timestamp = req.header('X-Zelda-Timestamp');
const header = req.header('X-Zelda-Signature') || '';
// Header looks like: t=1717545600,v1=9f86d081...
const parts = Object.fromEntries(
header.split(',').map((kv) => kv.split('=')),
);
const signature = parts.v1;
if (!timestamp || !signature) return res.sendStatus(401);
// Reject replays: the signed timestamp must be recent
const age = Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp));
if (age > TOLERANCE_SECONDS) return res.sendStatus(401);
// Recompute HMAC over "<timestamp>.<raw_body>"
const signedPayload = `${timestamp}.${req.body.toString()}`;
const expected = crypto
.createHmac('sha256', process.env.MFAX_WEBHOOK_SECRET)
.update(signedPayload)
.digest('hex');
// Constant-time compare avoids timing attacks
const ok =
signature.length === expected.length &&
crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
if (!ok) return res.sendStatus(401);
const event = JSON.parse(req.body.toString());
// At-least-once delivery: dedupe on the event id
if (seen.has(event.id)) return res.sendStatus(200);
seen.add(event.id);
// event.type is fax.delivered | fax.failed | fax.received
// event.data is the Fax object (status, failure_reason, media_url, ...)
res.sendStatus(200);
},
);
app.listen(3000);
Keep the Header Names Exact
The mFax signing headers are X-Zelda-Timestamp and X-Zelda-Signature — match them verbatim. On a fax.failed event, event.data.failure_reason carries the carrier reason (for example user_busy); on fax.received and delivered events, event.data.media_url is a presigned, time-limited link to the PDF.
Logging Without Leaking PHI
Never log the document, the recipient, or patient identifiers. Log opaque IDs and statuses instead:
import logging
logger = logging.getLogger("fax")
def log_fax_result(fax):
# Safe: opaque UUID + status, no PHI
logger.info("fax %s -> %s", fax["uuid"], fax["status"])
# NEVER do this — recipient number and patient data are PHI:
# logger.info("faxed %s to %s", patient_name, fax["to"])
Handling PHI in Your Code: Do and Don't
✓DO
- • Verify webhook signatures before trusting payloads
- • Keep the
zk_live_key server-side in a secrets manager - • Validate and confirm recipient numbers before sending
- • Auto-delete documents after successful delivery
- • Encrypt PHI in your own database, too
✕DON'T
- • Write recipient numbers or PHI to logs
- • Send PHI before a BAA is signed
- • Ship the API key in a browser or mobile app
- • Put patient identifiers on the cover sheet
- • Trust unverified or HTTP-only webhooks
For more on safely transmitting health data, see our guide to faxing PHI securely.
Use Cases for Health Apps
A HIPAA-compliant fax API shows up wherever a digital system has to reach a partner that still lives on fax:
- E-prescriptions and refills — sending scripts to pharmacies that accept fax orders. See how to fax a prescription.
- Lab results and imaging reports — routing results from a LIS to ordering providers.
- Referrals and prior authorizations — the paperwork-heavy exchanges between clinics and payers that remain stubbornly fax-based.
- EHR/EMR integration — adding outbound and inbound fax to an electronic health record so staff never leave the chart. Inbound faxes arrive on your mFax Business virtual number via the
fax.receivedwebhook and are also queryable withGET /v1/faxes?direction=inbound. - Records release — fulfilling medical record requests on demand.
Fax API Providers That Sign a BAA
Not every fax API is built for PHI. These providers sign a BAA and meet the technical safeguards (always confirm current terms directly with the provider):
| Provider | Signs BAA | BAA Cost | Notes |
|---|---|---|---|
| mFax Business | Yes | Included, all plans | First-party API + HIPAA features from about $9/mo; build your own plan; HMAC-SHA256 signed webhooks |
| Telnyx | Yes | Included | Developer-first, Ed25519-signed webhooks; no auto-retry on failed sends |
| Sinch / Phaxio | Yes | Free, signed in dashboard | Auto-retry plus configurable no-retention mode |
| Notifyre | Yes | Available | AES-256, ISO 27001, pay-as-you-go (~$0.03/page) |
| Humble Fax | No | — | Not suitable for PHI |
For a wider comparison, see our best HIPAA-compliant fax services roundup and the developer-focused fax API guide.
Why Healthcare Still Runs on Fax
If fax feels like a relic, the numbers say otherwise. An estimated 70% of healthcare communication still travels by fax — rising toward 90% when you count faxes flowing into and out of electronic health records — and U.S. healthcare exchanges billions of fax pages every year. The root cause is an interoperability gap: fewer than a third of hospitals can electronically find, send, receive, and integrate outside patient data, so fax remains the universal fallback that every provider, pharmacy, and payer can accept.
That's why modern health apps don't fight fax — they wrap it in an API. Cloud faxing abstracts away the analog plumbing (the T.38 protocol and phone lines) so your code just sends a document and gets a delivery receipt, while the compliance controls keep PHI protected the whole way.
Frequently Asked Questions
Is faxing actually HIPAA compliant?
Yes. Fax is a HIPAA-accepted transmission method, and the law has long recognized it. Compliance depends on safeguards — a signed BAA, encryption, access controls, and verifying you're faxing the right recipient — not on the medium itself. Our is faxing HIPAA compliant article covers the nuances.
Does the BAA cover faxes I receive, not just send?
It should. A proper BAA covers all PHI the business associate handles on your behalf — inbound faxes that arrive on your virtual number, documents stored on the provider's servers, and the audit logs themselves. With mFax, inbound faxes reach you through the fax.received webhook on your Business virtual fax number. Read the agreement to confirm inbound and storage are in scope.
How is a HIPAA fax API different from a regular fax API?
The send request is identical. The difference is everything around it: a signed BAA, enforced encryption at rest and in transit, exportable audit logs, configurable retention, and signed webhooks. A regular fax API may offer some of these as features; a HIPAA-compliant one like mFax guarantees them contractually.
Can I store the faxed documents in my own system?
Yes, but they remain PHI. The mFax Fax object returns a presigned, time-limited media_url you can fetch the PDF from — encrypt anything you keep at rest, apply the same access controls and audit logging you'd use for any patient data, and include that storage in your risk analysis. Minimizing what you retain reduces your exposure.
Get Started
Building PHI-safe faxing into your app comes down to two non-negotiables: a provider that signs a BAA, and code that protects health data in transit, at rest, and in your logs. Get those right and a fax API becomes one of the most reliable ways to exchange documents with the healthcare ecosystem.
For developers, create an API key in the dashboard and read the full reference at developers.mfax.to — API access is included on every mFax Business plan. mFax Business includes a signed BAA, encryption, audit logging, and first-party API access in plans starting at about $9/mo (billed annually) — HIPAA-ready out of the box. There are no rigid fixed tiers: you build your own plan, choosing the exact seats and pages you need ($3/seat + $4 per 100 pages) with a live calculator and paying only for what you use. Pair it with our send a fax via API tutorial to ship your first compliant integration. Prefer no-code? The mFax app sends and receives compliant faxes without writing a line.