# How to send a fax with ChatGPT

ChatGPT can call the SendFax MCP server at `https://mcp.sendfax.sh/mcp` through
**developer mode**. This guide covers who can turn that on, how to connect, what
to say, and how payment actually happens -- which is the part that needs the most
honesty, because ChatGPT has no wallet.

> **Naming, mid-migration.** OpenAI moved the ChatGPT app directory to the
> **Plugin Directory** on 9 July 2026. A *plugin* is now the installable
> container; an *app* (an MCP server plus optional UI) is what lives inside one.
> Older writing -- including OpenAI's -- still says "connector" and "app". The
> screens are being relabelled as this ships, so match what you see rather than
> what is written here.
>
> **An installable SendFax app for ChatGPT is coming.** Until then, developer
> mode is how you connect.

- Guide index: [../README.md](/guides/index.md) | protocol: [../usdc.md](/guides/usdc.md)
- Docs: <https://sendfax.sh/docs> | contract: <https://sendfax.sh/openapi.json>

---

## The flow

```
  you: "fax this PDF to +1 415 555 0123"
        |
  ChatGPT calls send_fax (MCP)
        |
        +--> HTTP 402: the fax is NOT sent yet
        |      the tool returns the challenge, but NOT the deposit address
        |      (see "The payment gap")
        |
  payment happens OUTSIDE ChatGPT -- it has no wallet and no shell:
        +-- you pay by card via Stripe Checkout        <-- the practical path
        +-- or you pay the deposit address yourself, from curl + any wallet
        |
  ChatGPT retries send_fax --> 202 { id, statusUrl }
        |
  ChatGPT calls get_fax_status(id) --> queued -> sending -> delivered
```

## Which payment path am I in?

ChatGPT holds no wallet, signs nothing, and -- unlike Claude Code, Codex, Hermes
or OpenClaw -- **has no shell tool to fall back on**. It can only call the MCP
tools you connect. That makes the answer unusually simple:

| Situation | Path |
|---|---|
| ChatGPT with the SendFax MCP server connected | It can submit, poll, and report. Payment is on you: use the Stripe Checkout link. |
| You also have a terminal | Run [../curl.md](/guides/curl.md) alongside; pay the deposit address from any wallet. ChatGPT can still poll the status. |
| You want full autonomy | Use an agent with a shell -- [claude.md](/guides/agents/claude.md), [codex.md](/guides/agents/codex.md), [hermes.md](/guides/agents/hermes.md), [openclaw.md](/guides/agents/openclaw.md). |

---

## Who can connect a custom MCP server

This is the biggest gate, and it is worth checking before anything else.

| Plan | Custom MCP server in developer mode |
|---|---|
| **Pro** | Yes, but **read/fetch actions only** -- no write actions |
| **Business** | Yes, full read + write. **Admins and owners only**; each enables it for themselves, and members cannot |
| **Enterprise / Edu** | Yes, full read + write. Admins grant access under Permissions & Roles, then enabled users toggle it on |
| **Free / Go / Plus** | **Not documented as supported.** OpenAI's current docs do not list them |

Two more constraints:

- **Web only.** OpenAI's FAQ is explicit: MCP apps are not available on mobile.
  Plugins are also unavailable in the IDE extension.
- **ChatGPT Work mode**, not plain Chat -- plugins live behind the
  Chat/Work/Codex switcher on web, and in the desktop app under Work or Codex.

Because `send_fax` is a write action, a **Pro** account can connect the server
but is documented as limited to read/fetch actions -- expect `get_fax_status` to
work and the send to be unavailable. Full sending needs Business, Enterprise, or
Edu.

*Sources:
<https://help.openai.com/en/articles/12584461-developer-mode-apps-and-full-mcp-connectors-in-chatgpt-beta>,
<https://help.openai.com/en/articles/11509118-admin-controls-security-and-compliance-for-plugins-and-apps>,
<https://learn.chatgpt.com/docs/plugins>. Plus is absent from all of them; a
number of third-party blog posts claim it works, and none of them cite a primary
source, so this guide does not either.*

---

## Connect the server

**OpenAI's own documentation currently describes two different click paths**, and
the labels are mid-rename. Rather than assert one, here is both, plus what is
constant.

**Constant across both:** you turn on developer mode, add a server by its public
HTTPS URL **including the `/mcp` path**, let ChatGPT scan the tools, and then
enable the connection inside a conversation.

The URL is:

```
https://mcp.sendfax.sh/mcp
```

**Path A -- as the developer docs describe it**
(<https://developers.openai.com/plugins/deploy/connect-chatgpt/>):

1. **Settings -> Security and login**, turn on **Developer mode**
2. Go to **ChatGPT Plugins**, select the **plus** button
3. Give it a name and description -- "SendFax" and "Send real faxes, paid per
   page" work
4. Enter `https://mcp.sendfax.sh/mcp`
5. Create the connection
6. Review the discovered tools: `send_fax`, `get_fax_status`,
   `get_payment_instructions`
7. In a new conversation, add the connection from the tools menu

**Path B -- as the Help Center describes it**
(<https://help.openai.com/en/articles/12584461-developer-mode-apps-and-full-mcp-connectors-in-chatgpt-beta>):

1. Admin, if applicable: **Workspace Settings -> Permissions & Roles ->
   Connected Data**, enable developer mode / custom MCP connectors
2. **Settings -> Apps -> Advanced Settings**, turn on **Developer mode**
3. **Settings -> Apps -> Create** (or Workspace settings -> Apps -> Create)
4. Provide the endpoint and metadata, pick the authentication mechanism if
   prompted, click **Scan Tools**, wait, then **Create**
5. It appears under **Enabled Apps** with a `Dev` label

If your screens match neither exactly, look for "Developer mode" under Settings
and follow the create-an-app flow from there.

### Authentication: none, and you will not be asked

SendFax is authless -- `/mcp` never requires a token -- and **ChatGPT connects to
no-auth MCP servers directly.** OpenAI's auth documentation says ChatGPT only
surfaces its OAuth linking UI when a server both advertises `oauth2` security
schemes *and* returns a runtime error carrying `_meta["mcp/www_authenticate"]`;
without both halves it will not show the linking flow
(<https://developers.openai.com/plugins/build/auth/>).

SendFax does neither, so **no sign-in prompt appears and no account is created.**
If the create form asks you to pick an authentication mechanism, choose the
no-auth option.

Worth stating plainly because other clients behave differently: SendFax also
publishes OAuth 2.1 discovery metadata with Dynamic Client Registration and
auto-approves instantly. That exists for clients like Codex and some enterprise
connectors that refuse to connect to an authless server at all. ChatGPT does not
need it, and you should not expect the browser window that Codex users see.

### `search` and `fetch` are no longer required

An earlier generation of ChatGPT connectors only supported two tools, `search`
and `fetch`. That restriction is gone -- OpenAI's FAQ now states the two tools
are not required for connected servers. `send_fax` is a first-class tool in
normal chat.

They still matter for one thing: deep research and company knowledge use only
read actions and expect `search`/`fetch`. SendFax exposes neither, so it will not
show up as a deep-research source. Deep research also refuses write actions
outright, and agent mode does not use custom apps at all.

---

## Ask for a fax

```
Use SendFax to fax the attached PDF to +14155550123. Tell me the price first.
```

```
I need to send this referral to my doctor's office at +1 415 555 0123.
It's a 3-page PDF. What will it cost, and can you start it?
```

ChatGPT should quote before spending anything: $0.05 per page on the wallet rail,
so a three-page fax is $0.15. If it does not, ask.

Expect a **confirmation prompt** before the send. ChatGPT's default permission
mode asks about important actions, and both "sending a communication on your
behalf" and "making a purchase" are on that list. That is the right behaviour for
a tool that spends money and dials a phone line; do not turn it off.

If you want standing guidance, put it in a project's custom instructions:

```
When I ask you to fax something, use the SendFax tools. SendFax delivers only to
the US, Canada, Mexico, and Saint Pierre & Miquelon. It is $0.05 per page in USDC,
or max($0.50, $0.05 x pages) by card. Always confirm the destination number and
page count with me before sending, and always tell me the price first.
```

---

<a name="the-payment-gap"></a>

## The payment gap

**The MCP `send_fax` tool does not surface the deposit address.** On a `402` it
forwards only `www-authenticate`, `payment-required`, and `content-type`
(`mcp/tools.ts:207-210`). The `x-payment-deposit-*` headers carrying the
per-request address that actually settles the payment
(`lib/payments/gate.ts:219-234`) are dropped.

Every agent guide in this set names that gap. It bites hardest here, because the
usual escape hatch -- "let the agent run curl" -- does not exist in ChatGPT.
`get_payment_instructions` will describe the flow correctly, but the address it
tells you to pay is minted per request and only appears in those dropped headers.

So there are two real options.

### Option 1: pay by card (recommended)

No wallet anywhere. Two calls you can run from any terminal, or from any HTTP
client:

```sh
curl -sS -F document=@referral.pdf -F to=+14155550123 \
  https://sendfax.sh/api/v1/uploads
# -> { "id": "133718a5-...", "pageCount": 3, "amountCents": 50 }

curl -sS -H 'content-type: application/json' -d '{"id":"133718a5-..."}' \
  https://sendfax.sh/api/v1/checkout
# -> { "url": "https://checkout.stripe.com/c/pay/cs_live_..." }
```

Open the URL, pay with a card or Stripe Link, and the fax sends. ChatGPT can then
poll it for you with `get_fax_status`, or you can watch
`https://sendfax.sh/f/{id}`.

Note the price on this rail: `max($0.50, $0.05 x pages)`, because Stripe will not
charge under 50 cents (`lib/domain/pricing.ts:16, 23`). A one-page fax is $0.05
by wallet and $0.50 by card.

If a person is doing this anyway, <https://sendfax.sh/human> is the same flow with
a drag-and-drop page and no curl.

### Option 2: pay the deposit address from a terminal

If you have a wallet and want the $0.05 price, run the flow yourself and let
ChatGPT do the watching:

```sh
curl -sS -D headers.txt -o body.json -w '%{http_code}\n' \
  -F document=@referral.pdf -F to=+14155550123 \
  https://sendfax.sh/api/v1/faxes
# 402

grep -i '^x-payment-deposit' headers.txt
# x-payment-deposit-address: 0x157a57423869bf2666d3998b1319c2263ce852bb
# x-payment-deposit-amount: 0.150000
# x-payment-deposit-amount-micros: 150000
# x-payment-deposit-network: base
# x-payment-deposit-token: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```

Send exactly `150000` base units of USDC on Base to that address, then retry the
identical request until it returns `202`. The full script, with a QR code so you
can pay from a phone, is in [../curl.md](/guides/curl.md).

Then hand ChatGPT the id: *"poll get_fax_status for 133718a5-... until it's
delivered."*

---

## How payment actually works

No account, no API key -- payment is the credential. Full mechanics in
[../usdc.md](/guides/usdc.md):

1. The 402 carries a fresh deposit address, the exact amount in USDC base units,
   and the network (`base`).
2. You send that **exact** amount of USDC on Base as a plain ERC-20 transfer. No
   signature, no approval, no facilitator.
3. You retry the **identical** request until `202`.

Two rules worth repeating:

- **Exact amount.** Use `x-payment-deposit-amount-micros`, never the decimal
  display value through a float (`lib/payments/deposit.ts:16-18`).
- **Same request, ~15 minutes.** Identical retries reuse the same PaymentIntent
  and are not a second charge (`lib/payments/deposit.ts:50, 94-108`).

---

## Troubleshooting

**No Developer mode option in Settings.** Check your plan against the table
above, and if you are on Business/Enterprise/Edu, whether an admin has enabled
it. Members of a Business workspace cannot add custom servers at all.

**The connector will not appear in a conversation.** Plugins are only available
in **ChatGPT Work** mode on web (and Work/Codex in the desktop app). They do not
exist in plain Chat, in the IDE extension, or on mobile.

**Connected, but `send_fax` is missing or refuses.** On **Pro**, developer mode
is documented as read/fetch only -- write actions like sending a fax need
Business, Enterprise, or Edu.

**It asked me to sign in.** It should not. SendFax is authless and returns no
`_meta["mcp/www_authenticate"]`, so ChatGPT has nothing to trigger the linking UI
with. If you see a sign-in screen, you are connected to something else -- check
the URL is exactly `https://mcp.sendfax.sh/mcp`.

**The tool list is stale after we ship a change.** After an admin publishes,
ChatGPT uses a frozen snapshot of the server's tools; later changes are not
applied until an admin reviews and publishes an update, and an incompatible
change makes tool calls error with no prompt and no notification. Use the
**Refresh** control on the connection.

**ChatGPT says "payment required" and stops.** That is the design -- the fax has
not been sent. See [the payment gap](#the-payment-gap).

**"Unsupported destination" (422).** SendFax delivers to the United States,
Canada, Mexico, and Saint Pierre & Miquelon (`lib/domain/fax.ts:70-78`). Checked
before any payment, so nothing was charged.

**"Invalid PDF" (422).** Encrypted or password-protected PDFs are rejected --
common for documents exported from banking and government portals, which is
exactly the kind of thing people fax.

**413.** Over the 20 MB limit.

**The fax says `failed`.** Read `failureReason` -- busy, no answer, not a fax
line. Destination-related failures on a Stripe-settled payment, which includes
every deposit-rail payment, are refunded automatically to the sending wallet
(`lib/payments/refund.ts:1-30`).

**A long tool call times out.** OpenAI does not document a number, and the
community reports vary, so do not design around a specific limit. It does not
matter here: `send_fax` returns immediately with either a 402 challenge or a
receipt, and status is a separate `get_fax_status` call. Never ask ChatGPT to
"wait until it's delivered" inside one tool call -- ask it to poll.

**SSE.** SendFax serves an SSE fallback at `https://mcp.sendfax.sh/sse`, but
OpenAI documents Streamable HTTP as the ChatGPT transport and does not describe
an SSE option. Use the `/mcp` URL.

---

## Try it without spending anything

Point a local SendFax at mock mode and the whole flow works with no wallet:

```sh
bun run dev      # http://localhost:3001, FAX_MODE=mock
curl -sS -H 'x-mock-payment: 1' \
  -F document=@test.pdf -F to=+14155550123 \
  http://localhost:3001/api/v1/faxes
```

ChatGPT cannot reach `localhost`, since it connects from OpenAI's cloud rather
than your device -- so use this to understand the flow, not to demo the
connector.

---

## Cross-references

- [../README.md](/guides/index.md) -- the chooser and the decision matrix
- [../curl.md](/guides/curl.md) -- the terminal half of both payment options
- [../usdc.md](/guides/usdc.md) -- how USDC settlement works
- [claude.md](/guides/agents/claude.md) | [codex.md](/guides/agents/codex.md) | [hermes.md](/guides/agents/hermes.md) | [openclaw.md](/guides/agents/openclaw.md)
- <https://sendfax.sh/quickstart.md> | <https://sendfax.sh/docs>
