Skip to content

Fax Status Webhooks: Real-Time Delivery Tracking for Apps

The SendFax.me Team · September 21, 2026 · 6 min read

Fax Status Webhooks: Real-Time Delivery Tracking for Apps
Photo by Jakub Zerdzicki on Pexels

If your app sends faxes on behalf of users, the worst way to find out whether one actually arrived is to keep asking. Polling a fax API every few seconds burns rate limits, adds latency, and still leaves a gap between when a fax finishes and when your system notices. A fax status webhook solves that by having the fax provider push a notification to your server the moment something happens, instead of you having to ask over and over. This matters most for teams automating faxing at volume: EHR and EMR systems sending referrals, pharmacies routing prescriptions, legal ops sending signed filings, and logistics platforms pushing rate confirmations.

This guide covers how fax webhooks actually behave, which statuses and failure reasons your handler needs to plan for, and how to set one up using a REST fax API like the one at sendfax.me/developers.

Why Polling Doesn't Scale

Faxing is not instant, and that trips up a lot of first-time integrations. A fax transmission still goes through a real handshake between two endpoints, so the API accepts your request in milliseconds, but the actual transmission takes 30 to 90 seconds, meaning you learn the final outcome later rather than in the initial response. If your code polls a status endpoint on a timer to catch that outcome, you're either checking too often and wasting API calls, or too rarely and adding delay before your app can react. At any real volume, that adds up to thousands of wasted requests a day.

A webhook flips the model. You register a URL once, and the provider sends an HTTP POST to it the instant the fax reaches a final state. Webhooks are triggered by events such as the completion of a fax and transmit information about the state of that fax via HTTP or HTTPS. Your server just needs to listen.

The Statuses Your Handler Needs to Expect

A fax job typically moves through a few states before it's done:

  • Queued: the fax is accepted and waiting to dial out
  • Sending: the call has connected and the transmission is in progress
  • Sent / Delivered: the remote fax machine confirmed receipt of all pages
  • Failed: the transmission did not complete, with a reason attached

The failed state is where most integration bugs live, because "failed" isn't one thing. Real-world fax failures break down into a handful of recurring causes documented across fax providers:

  • No answer: the number dialed rings but the call is never answered, usually a T.30 timeout
  • Busy: the line was busy even after the default retries
  • No remote fax device: the number picks up but doesn't return a fax tone, often because it's a voice line or an auto-attendant
  • Remote fax aborted: a connection was established but the remote side disconnected mid-transmission, commonly due to a poor connection or a VoIP line on the receiving end

Some providers also expose these as numeric codes rather than plain text, similar to how one fax platform maps 6100 to a busy number, 6200 to a machine not answering, and 6700 to a fax blocked by the receiving party. If you're building an integration, store the raw reason string or code alongside the human-readable status. Support tickets get resolved a lot faster when you can tell a user "the recipient's line was busy" instead of just "it failed." Our own guide to failed fax transmissions breaks down the most common causes if you want the consumer-facing version of this same list.

Setting Up Webhooks With the SendFax.me API

Getting a working integration running takes four steps:

  1. Create an account and grab your API key from the dashboard at sendfax.me/signup
  2. Send your first fax with a single POST request to the fax endpoint, attaching a PDF or image and the recipient's number
  3. Point your webhook URL at an endpoint on your own server that can accept a POST request
  4. Return a fast HTTP 200 response so the provider knows the notification was received

A typical webhook payload includes the job ID, the destination number, the page count, the final status, and a timestamp, something like:

```

{

"fax_id": "fx_8a2f91",

"to": "+14155550123",

"pages": 4,

"status": "failed",

"reason": "no_answer",

"completed_at": "2026-09-21T14:32:10Z"

}

```

Exact field names differ between providers, so always check the reference docs rather than assuming a payload shape carries over from one API to another. Full request and response formats for our API are documented at sendfax.me/developers, including how volume credit packs work if you're sending enough pages that per-fax pay-as-you-go pricing shifts to bulk credits starting around 4 cents per US page.

Building a Handler That Doesn't Fall Over

A few habits separate a webhook integration that works in a demo from one that survives production traffic:

  • Acknowledge fast, process later. Return a 200 immediately, then hand the payload off to a queue or background job. Slow handlers cause providers to think the delivery failed and retry, which can duplicate your processing.
  • Make processing idempotent. Because retries happen, the same fax ID might arrive twice. Check whether you've already recorded that status before acting on it again.
  • Log the raw payload. When a customer disputes whether a fax went through, having the original webhook body with its timestamp and failure reason saves you from guessing.
  • Keep polling as a fallback, not the primary path. Webhooks can occasionally miss a delivery attempt if your endpoint is briefly down. A daily reconciliation check against the fax history endpoint catches anything a webhook missed.

Where This Actually Gets Used

The pattern shows up constantly once you start looking for it. A clinic's scheduling software faxes a referral the moment an appointment is booked, then updates the patient's chart automatically when the delivery webhook confirms it went through. A logistics platform faxes a signed rate confirmation to a carrier and marks the load as confirmed only after the webhook reports success. A legal ops tool retries automatically and alerts a paralegal only when a fax genuinely fails after several attempts, rather than making a human babysit every transmission.

If you're the one building that kind of always-on automation for a service business more broadly, it's worth looking at what else exists in the same space. A tool like Agentika applies the same idea to customer contact: a 24/7 AI assistant widget that answers website visitors and captures bookings so nothing falls through when no one's watching the inbox. And if you like keeping an eye on what other small, useful tools are shipping, Rehunt delivers a personalized Product Hunt digest straight to your inbox on a schedule you set, which is a low-effort way to spot the next integration worth trying before everyone else does.

Getting Started

If you're evaluating a fax API for the first time, send a real fax through it before you write a line of integration code. Your first fax is free, pricing is pay-as-you-go per page with no subscription, and you can send to numbers in 29 countries straight from the dashboard. Once that works, wiring up a webhook is a small addition on top of a send flow you already understand. Full documentation, including authentication, request formats, and webhook events, lives at sendfax.me/developers.

Need to send a fax right now?

Upload your document, enter the number, and it's delivered in minutes, and your first page is free. No fax machine, no subscription.

Keep reading

← All posts