Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintfax.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

mintfax dispatches a webhook attempt as soon as the event is produced. Your endpoint has one job per attempt: return a 2xx response quickly. Anything else schedules a retry.

What counts as a successful delivery

Any 2xx status code (200, 201, 202, 204) within the per-attempt timeout. Body content is ignored; only the status code matters.

What triggers a retry

OutcomeResult
2xx response within the timeoutDelivered. No retry.
4xx responseRetried.
5xx responseRetried.
Network failure (DNS, TCP, TLS)Retried.
Endpoint timeout exceeded (30 seconds)Retried.
Invalid TLS certificateRetried.
A retry sends an identical event payload with a fresh webhook-timestamp header. The webhook-id stays the same so your idempotency layer recognizes it as a re-delivery.

Retry schedule

Up to four attempts with exponential backoff. Total wall-clock window from first attempt to giving up is approximately 18 minutes.
AttemptSent
1Immediately when the event fires
210 seconds after attempt 1 failed
3About 100 seconds after attempt 2 failed
4About 17 minutes after attempt 3 failed
If attempt 4 fails, the event is marked permanently failed. The event itself is not lost - you can replay it from the dashboard or re-fetch it via the Events API.

Make your handler safe to retry

Webhook handlers must be idempotent. The same event can arrive more than once: a timeout on your side, a network blip, a retry from a previous attempt that eventually succeeded after you also processed it. Two approaches: Deduplicate on webhook-id. Persist the event ID before doing the work. If you see the same ID twice, skip.
const eventId = req.headers["webhook-id"];
const existing = await db.events.findUnique({ where: { id: eventId } });
if (existing) {
  return res.status(200).end();
}
await db.events.create({ data: { id: eventId } });
// ... your handler logic
Or design the handler to be replay-safe. Update operations that compare-and-set on a known state work without a dedupe layer. For example: “set fax X to delivered if its current status is sending” is safe to run twice.

Per-event semantics

fax.delivered and fax.failed are mutually exclusive and exactly-once per fax. fax.sending may fire multiple times if a fax retries against the destination. fax.queued fires exactly once. balance.low may fire multiple times if your balance oscillates around the threshold. balance.topup fires once per credit addition. See the per-event pages in Event types for the firing rules of each event.

Timeouts and what your endpoint should do quickly

The per-attempt timeout is 30 seconds. If you cannot respond within that window, return 200 immediately and process the event asynchronously on your side. A handler that does heavy work before responding (write to multiple databases, call third-party APIs, send email) is at risk of timing out. The pattern:
  1. Receive the request, verify the signature, enqueue a job locally.
  2. Return 200 within milliseconds.
  3. Process the job out-of-band.
This is also how mintfax dispatches its own events internally, for the same reason.

What “permanently failed” means

A permanently failed event is one that exhausted all six attempts. The event itself still exists in your account’s event log - you can find it via the Events API or in the dashboard. From the dashboard, you can replay it manually after fixing the issue on your side. See Inspect delivery attempts. mintfax does not delete events that failed to deliver. If your endpoint went down for an extended outage, your event history is intact and replayable when you are ready.

Next

Last modified on May 14, 2026