---
name: mfax-api
description: Send, track, and receive faxes via the mFax REST API. Use whenever a task involves sending a fax, faxing a PDF or document, checking fax delivery status, receiving inbound faxes, or wiring fax into an app or workflow. Holds the base URL, auth, endpoints, the Fax object, webhook signing, and error codes.
---

# mFax Fax API

A first-party REST API to send and track faxes programmatically — no fax machine,
modem, or phone line. Docs and key management: https://developers.mfax.to. API
access is included with every mFax Business plan.

## Authentication

- **Base URL:** `https://developers.mfax.to/v1`
- **Header:** `Authorization: Bearer zk_live_…` — a business API key created in the
  mFax dashboard (https://app.mfax.to). **Server-side only** — never expose the key
  in client-side or mobile code.

## Send a fax

`POST /v1/faxes` — `multipart/form-data` with exactly two fields:

| field | value |
|-------|-------|
| `to`   | recipient number in **E.164** (e.g. `+15417543010`) |
| `file` | a **PDF** |

Returns `202 Accepted` plus a Fax object. Do **not** send `from`, `quality`, or
`callback_url` — they are not part of the request.

```bash
curl -X POST https://developers.mfax.to/v1/faxes \
  -H "Authorization: Bearer $MFAX_API_KEY" \
  -F "to=+15417543010" \
  -F "file=@invoice.pdf"
```

```json
{
  "uuid": "a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809",
  "status": "queued",
  "direction": "outbound",
  "to": "+15417543010",
  "page_count": 0,
  "created_at": "2026-06-05T14:30:00Z"
}
```

## Track & manage

- `GET /v1/faxes/{uuid}` — retrieve one fax
- `GET /v1/faxes` — list faxes (filter inbound with `?direction=inbound`)
- `DELETE /v1/faxes/{uuid}` — delete a fax

## The Fax object

| field | type | notes |
|-------|------|-------|
| `uuid` | string | unique id — track or delete by it |
| `status` | enum | `queued` → `sending` → `delivered` \| `failed` |
| `direction` | enum | `outbound` \| `inbound` |
| `to` | string | recipient, E.164 |
| `page_count` | integer | pages transmitted (0 until rendered) |
| `created_at` | string | ISO 8601, UTC |
| `failure_reason` | string | set when `status` is `failed`, e.g. `user_busy` |

## Receive inbound faxes

Inbound faxes arrive on your mFax Business virtual number. Subscribe to the
`fax.received` webhook, or poll `GET /v1/faxes?direction=inbound`.

## Webhooks

Configure a delivery URL (and optional signing secret) in the dashboard. Events:
`fax.delivered`, `fax.failed`, `fax.received`. Each request is signed:

- `X-Zelda-Signature` — `t=…,v1=…`, where `v1` is an HMAC-SHA256 of
  `"<timestamp>.<rawBody>"` keyed with your signing secret
- `X-Zelda-Timestamp` — the timestamp

Verify the signature over the **raw** request body in constant time before trusting
the event.

## Errors

JSON `{ code, message }`:

| code | HTTP | meaning |
|------|------|---------|
| `invalid_number` | 400 | recipient isn't valid E.164 |
| `quota_exceeded` | 402 | plan send quota reached |
| `subscription_inactive` | 403 | billing / subscription lapsed |
| `rate_limited` | 429 | too many requests — honor the `Retry-After` header |

## Do NOT assume

There are **no** official SDKs, sandbox, numbers-provisioning API, or
`Idempotency-Key` header documented — call the REST endpoints directly. The source
of truth is the OpenAPI spec at https://developers.mfax.to/openapi.json; re-verify
fields there before relying on them.
