By Michael Chen · Published June 4, 2026 · Updated June 4, 2026 · 10 min read
Quick answer: A cloud fax API accepts an HTTPS request with a document and a phone number, then runs the entire analog fax transmission on hosted infrastructure — conversion, dialing, protocol negotiation, retries, and confirmation. You get a job ID back in milliseconds and a webhook when the recipient's machine confirms. Start with the mFax API, included on every mFax Business plan.
Every cloud fax API looks the same from the outside: one POST, one JSON response, one webhook. That simplicity is the product. But it also hides the thing developers actually need to understand — that behind the HTTP call sits a 1980s telephony protocol negotiating with a machine that may be a decade older than your codebase.
Understanding that layer is not academic. It explains why the API returns 202 instead of 200, why page_count is 0 at first, why a fax takes 40 seconds instead of 40 milliseconds, and why user_busy is a normal outcome rather than a bug. This guide traces the full path from your request to the recipient's confirmation tone.
If you want code first, our send a fax via API tutorial has copy-paste examples in four languages. This article is the how it works companion.
What Is a Cloud Fax API?
A cloud fax API is a hosted REST interface that converts HTTPS requests into fax transmissions and incoming faxes into webhook events. The provider owns the modems, the carrier interconnects, and the protocol stack. You own an API key.
The distinction that matters is where the fax endpoint lives:
| Approach | What you operate | What breaks at 3 a.m. |
|---|---|---|
| Fax machine | A device, a paper tray, an analog line | Paper jams, busy lines, no audit trail |
| On-premise fax server | A server, fax boards or a SIP trunk, licenses | Your telephony stack, your pager |
| VoIP fax (ATA / T.38 trunk) | An adapter plus a SIP provider relationship | Jitter, codec mismatch, VoIP fax problems |
| Cloud fax API | An API key and a webhook handler | Your HTTP client — the provider owns the rest |
That last row is the entire value proposition. Everything below describes what the provider absorbed on your behalf.
Cloud fax API vs. cloud fax
Cloud fax is the service category — faxing without hardware, usually through a web dashboard. A cloud fax API is the programmatic surface of that same service. Same infrastructure, different front door: one is a UI for people, the other is endpoints for software.
What Happens Between Your POST and the Recipient's Fax Machine
Seven distinct stages run between your request and a delivered fax. Most take place after your HTTP connection has already closed.
Your request is authenticated and validated
Your backend sends multipart/form-data over TLS with a Bearer key. With the mFax API that request carries exactly two fields — to in E.164 format and file — to POST https://developers.mfax.to/v1/faxes. The service validates the number format, checks that your organization's subscription is active, and confirms you have page quota left. A malformed number fails immediately with 400 invalid_number; an exhausted quota returns 402 quota_exceeded.
The job is queued and you get 202 Accepted
Fax transmission takes tens of seconds, so no sane API makes you wait for it. The provider persists the job, returns HTTP 202 with a fax object in queued status, and closes the connection. This is why a cloud fax API is asynchronous by design: the response tells you the job was accepted, never that it was delivered.
Your PDF is rasterized to fax resolution
Fax machines do not understand PDFs. They understand 1-bit black-and-white scanlines. The provider renders your document to a bitonal image 1,728 pixels wide — the Group 3 standard scanline — at roughly 204 × 196 dpi for fine mode, then compresses it with MH, MR, or MMR encoding. This is the step that silently destroys light grey text, thin hairlines, and colour-coded information: everything becomes pure black or pure white.
A carrier route is chosen and the number is dialled
The gateway analyses the destination, picks a carrier route, and places the call. If the line is busy or nobody answers, the fax fails with a failure_reason such as user_busy — which is a property of the recipient's phone line, not of your code.
The two machines negotiate — the T.30 handshake
This is the part that has nothing to do with the internet. The receiving machine answers with a CED tone and broadcasts its capabilities (DIS): the speeds it supports, the page widths it accepts, whether it can do error correction. The sender replies with the parameters it chose (DCS), sends a training pattern, and waits for confirmation. If training fails, both sides step down to a slower modulation and try again. This handshake alone accounts for most of the 10–15 seconds before the first page moves.
Pages transmit, with error correction retransmitting the damage
In Error Correction Mode, each page is split into frames with checksums. Corrupted frames are re-requested and retransmitted rather than printed as noise. Without ECM, a burst of line noise becomes a smeared black band on the recipient's page. Cloud providers negotiate ECM by default — it is one of the quiet reasons hosted faxing beats a cheap ATA on a jittery connection.
The recipient confirms, and your webhook fires
After each page, the receiving machine returns a confirmation frame (MCF). When the last page is acknowledged and the call tears down, the job moves to delivered, page_count is populated with what the carrier actually transmitted, and the provider POSTs a fax.delivered event to your webhook URL. If any stage failed, you get fax.failed with a failure_reason instead.
Stages 5 and 6 are governed by ITU-T Recommendation T.30, the Group 3 facsimile protocol. When the leg between the provider and the recipient crosses an IP network, ITU-T T.38 relays those same T.30 signals as UDP packets with redundancy, so packet loss does not corrupt the page. Our T.38 protocol explainer covers that layer in depth.
Why the Response Is 202, Not 200
Because nothing has been delivered yet. The full mFax status lifecycle is four states:
| Status | What it means | Typical duration |
|---|---|---|
queued | Accepted and waiting for a transmission slot | Under 10 seconds |
sending | Dialling, negotiating, transmitting | 20–90 seconds |
delivered | Recipient's machine confirmed every page | Terminal |
failed | Could not deliver; read failure_reason | Terminal |
Two consequences follow, and both trip up first integrations:
page_countis0until it isn't. The carrier reports pages transmitted, so the field is only meaningful once the fax reaches a terminal state. Do not bill or log page counts off the202response body.- A
202is not a receipt. If your product tells a user "fax sent" on the strength of the POST response, you will eventually tell somebody their document arrived when the recipient's line was disconnected. Wait forfax.delivered.
curl -X POST https://developers.mfax.to/v1/faxes \
-H "Authorization: Bearer $MFAX_API_KEY" \
-F "to=+14155550100" \
-F "[email protected]"
{
"uuid": "8f3c1e2a-1c4b-4b2f-9d33-7a1e5c2b9f01",
"to": "+14155550100",
"status": "queued",
"direction": "outbound",
"page_count": 0,
"created_at": "2026-06-04T18:00:00Z",
"updated_at": "2026-06-04T18:00:00Z"
}
Poll GET /v1/faxes/{uuid} if you must, but webhooks are the correct pattern — see programmatic faxing for the full trigger-to-confirmation loop.
How Long Does a Cloud Fax Take?
Between 30 and 90 seconds for a typical short document. The budget breaks down like this:
| Phase | Time | What drives it |
|---|---|---|
| Queue | 1–10 s | Account concurrency and current load |
| Dial and answer | 5–10 s | Carrier routing, recipient's ring cycle |
| T.30 handshake and training | 5–10 s | Recipient's equipment age |
| Per page (V.34 / Super G3) | ~7 s | Modern receiving machines |
| Per page (V.17 fallback) | ~16–20 s | Older machines, noisy lines |
| Teardown and webhook | 1–3 s | Provider-side |
The single biggest variable is equipment you do not control. V.34 runs at 33.6 kbps and retrains between pages in about a quarter of a second; the older V.17 standard runs at 14.4 kbps and takes roughly six seconds to retrain. Across a four-page document that difference compounds from about 22 seconds to over 100.
Design your UX for seconds, not milliseconds
A cloud fax API is fast for a fax, not fast for an HTTP call. Never block a user-facing request on delivery. Accept the job, return immediately, and update the UI when the webhook arrives.
What the "Cloud" Part Actually Buys You
Strip away the marketing and a cloud fax API is a managed telephony stack. These are the specific problems the provider is absorbing:
- Carrier relationships and routing. Reaching a fax machine in another country means an interconnect agreement, not a config file. See our notes on international fax country codes.
- Modulation fallback. Negotiating down from V.34 to V.17 to V.29 when the far end is old or the line is poor — automatically, per call.
- Retries on transient failure. A busy signal is not a permanent failure. Hosted platforms redial on a schedule instead of handing you a dead job.
- Document normalization. Page-size fitting, rasterization, and compression, so a 12 MB colour PDF becomes a transmittable Group 3 image.
- Media storage. Delivered and inbound faxes are stored and exposed as presigned, time-limited
media_urllinks rather than left on a hard drive somewhere. - Compliance controls. TLS in transit, AES-256 at rest, audit logging, and a signed BAA when you handle PHI — covered in our HIPAA fax API guide.
Running any one of these yourself is a weekend. Running all of them, reliably, is a team.
Cloud Fax API vs. VoIP Faxing
These get conflated constantly, and the difference is operational, not technical.
| Cloud fax API | VoIP fax (ATA, fax server, SIP trunk) | |
|---|---|---|
| Fax endpoint | Provider's gateway | Your hardware or software |
| You configure | An API key, a webhook URL | Codecs, T.38 settings, jitter buffers, ECM |
| Failure surface | HTTP status codes | Packet loss, transcoding, clock drift |
| Scales by | Sending more requests | Buying more lines |
| Debugging tool | Your application logs | A packet capture |
If you already run SIP infrastructure and want fax on it, T.38 is your path — start with fax over VoIP and the VoIP fax gateway guides. If you want faxing to be someone else's on-call rotation, use a cloud fax API.
Reading Failures Like a Telephony Engineer
Cloud fax API failures are almost always telephony events wearing an HTTP costume. This table maps what you see to what actually happened.
| What you get | Layer | What really happened | What to do |
|---|---|---|---|
400 invalid_number | Your request | Not valid E.164 | Fix formatting; never retry as-is |
402 quota_exceeded | Your account | Monthly page quota exhausted | Raise the plan; queue until reset |
403 subscription_inactive | Your account | Billing lapsed | Alert an operator, do not retry |
429 rate_limited | Provider | Token bucket drained | Honour Retry-After, back off with jitter |
failed + user_busy | T.30 / PSTN | Recipient's line was in use | Retry after several minutes |
failed + no answer | T.30 / PSTN | No fax tone detected | Verify it is a fax line, not a voice line |
failed after partial pages | T.30 / ECM | Training or retransmission gave up | Retry; if it repeats, reduce page count or image density |
A fax that fails once and succeeds on retry is not a flaky API. It is a phone line that was busy. Build for that reality and see our fax error codes reference for the machine-side vocabulary.
Receiving Faxes Through a Cloud Fax API
Inbound is the mirror image of everything above, and it needs one thing sending does not: a virtual fax number on your account.
When a fax arrives, the provider answers the call, runs the T.30 handshake as the receiving party, reassembles the pages, converts them to PDF, and POSTs a fax.received event to your webhook containing the sender, page_count, and a presigned media_url. You can also sweep GET /v1/faxes?direction=inbound as a backup. Because delivery is at-least-once, dedupe on the event id.
mFax signs each webhook with an X-Zelda-Signature header — an HMAC-SHA256 of "<timestamp>.<rawBody>" — when you configure a signing secret. Verify it before you trust the payload. Our online fax API guide walks through the complete inbound handler.
What to Look For in a Cloud Fax API
- ✓Webhooks, not just polling: delivery events pushed to you, with signature verification and documented retry behaviour.
- ✓An honest status model: a real lifecycle with terminal states and a machine-readable
failure_reason, not a boolean "sent". - ✓Documented error codes: distinct codes for your fault, your account, and the phone network — they demand different handling.
- ✓Rate-limit headers:
Retry-Afterplus remaining-quota headers, so backoff is data-driven rather than guesswork. - ✓A signed BAA if you touch PHI: encryption alone is not compliance. Confirm the agreement before the first test fax.
- ✓Predictable pricing at your volume: per-page and subscription models diverge sharply at scale — see our fax API pricing comparison.
Frequently Asked Questions
Can a cloud fax API send to a regular fax machine?
Yes — that is the entire point. The recipient needs nothing but a working fax line. Their machine cannot tell that the call originated from an HTTPS request rather than another fax machine.
Why did my fax arrive with black bands or missing text?
Almost always a rasterization or line-quality issue. Light grey text and thin strokes vanish when a document is reduced to 1-bit black and white, and noise on a call without error correction prints as smeared bands. Send high-contrast black-on-white PDFs at 200 dpi or better.
Can I send a colour document through a cloud fax API?
You can upload one, but Group 3 fax transmits in black and white. Anything that relies on colour to convey meaning — a highlighted row, a red signature line — should be redesigned before it is faxed.
Do cloud fax APIs work internationally?
Yes, subject to the provider's carrier coverage. Numbers must be in full E.164 format with the country code, and international legs are slower and more failure-prone than domestic ones. Budget for more retries.
Start Building on a Cloud Fax API
The fastest path from reading to sending: create an organization at mFax Business (usage-based pricing from about $9/mo annually, with API access on every plan), generate a zk_live_… key in the mFax dashboard, and read the reference at developers.mfax.to.
One POST sends your first fax. Everything in this article happens automatically after that — which is exactly the point of putting faxing in the cloud.